I used to do some assembly years ago and I tried to optimize this DWord to Dec conversion (or is it to string conversion =)...I'm just interested to know if I was on to something...but I suspect my code is ridiculous :lol
I think the original was 16bit code for Word to Dec conversion and this is conversion to 32bit of it and don't even remember if it works or for what I used it :lol
DWordToDec proc src:DWORD, pdst:DWORD
push ebx
push ecx
push edx
mov ecx,1
mov ebx,pdst
mov eax,src
cmp ebx,0
je DWordToDec_Err
cmp eax,0
je DWordToDec_Err
jmp @F
DWordToDec_10_ dd 1000000000
DWordToDec_9_ dd 100000000
DWordToDec_8_ dd 10000000
DWordToDec_7_ dd 1000000
DWordToDec_6_ dd 100000
DWordToDec_5_ dd 10000
DWordToDec_4_ dd 1000
DWordToDec_3_ dd 100
DWordToDec_2_ dd 10
@@:
cmp eax,10
jb DWordToDec_1
cmp eax,100
jb DWordToDec_2
cmp eax,1000
jb DWordToDec_3
cmp eax,10000
jb DWordToDec_4
cmp eax,100000
jb DWordToDec_5
cmp eax,1000000
jb DWordToDec_6
cmp eax,10000000
jb DWordToDec_7
cmp eax,100000000
jb DWordToDec_8
cmp eax,1000000000
jb DWordToDec_9
div DWordToDec_10_
add eax,'0'
mov [ebx],al
inc ebx
mov ecx,10
mov eax,edx
DWordToDec_9:
div DWordToDec_9_
add eax,'0'
mov [ebx],al
inc ebx
mov ecx,9
mov eax,edx
DWordToDec_8:
div DWordToDec_8_
add eax,'0'
mov [ebx],al
inc ebx
mov ecx,8
mov eax,edx
DWordToDec_7:
div DWordToDec_7_
add eax,'0'
mov [ebx],al
inc ebx
mov ecx,7
mov eax,edx
DWordToDec_6:
div DWordToDec_6_
add eax,'0'
mov [ebx],al
inc ebx
mov ecx,6
mov eax,edx
DWordToDec_5:
div DWordToDec_5_
add eax,'0'
mov [ebx],al
inc ebx
mov ecx,5
mov eax,edx
DWordToDec_4:
div DWordToDec_4_
add eax,'0'
mov [ebx],al
inc ebx
mov ecx,4
mov eax,edx
DWordToDec_3:
div DWordToDec_3_
add eax,'0'
mov [ebx],al
inc ebx
mov ecx,3
mov eax,edx
DWordToDec_2:
div DWordToDec_2_
add eax,'0'
mov [ebx],al
inc ebx
inc ecx
mov eax,edx
DWordToDec_1:
add eax,'0'
mov [ebx],al
mov eax,ecx
pop edx
pop ecx
pop ebx
ret
DWordToDec_Err:
mov eax,0
pop edx
pop ecx
pop ebx
ret
DWordToDec endp
About the naming:
DwordToDecimal is obviously wrong because dword is a size whereas decimal is a base. A correct name would be NumberToString.
About the function:
At first glance it looks very dodgy.
check this out:
szBuffer db 10 dup (0), 0 ; reserve 10 bytes (chars) for converting, 'cause eax can hold 10 digits max.
.....
mov eax, 2637488436 ; value to be converted to a string
mov edi, szBuffer + 9 ; pointer to the last char in the buffer
call myInt2Str
.....
myInt2Str:
xor ecx, ecx
xor ebx, ebx
mov cl, 5
mov bl, 100
ll_myI2S_Loop:
xor edx, edx ; zero edx
div ebx ; here eax = 26374884 and edx = 36
xchg eax, edx ; eax = 36, edx = 26374884
aam ; eax = 0306h, e. g. ah = 3, al = 6
or eax, 3030h ; ah = '3', al = '6'
mov byte ptr [edi], al ; store al into the buffer
dec edi ; decrement pointer to the previous char
mov byte ptr [edi], ah ; store ah into the buffer
dec edi ; decrement pointer to the previous char
mov eax, edx ; eax = 26374884
dec ecx
jnz ll_myI2S_Loop ; loop
retn
Hello!
Another method (recursive) I learnt some years ago. The base must be equal or less than 16.
Int2Str PROC USES ebx edx edi Number:DWORD,Base:DWORD,lpString:DWORD
; a wrapper for the recursive procedure
; saves registers, loads initial values
mov eax,Number
mov ebx,Base
mov edi,lpString
call @_Int2Str1
ret
Int2Str ENDP
@_Int2Str1:
xor edx,edx
div ebx ; edx: remainder=a digit from the end
or eax,eax
jz @_Int2Str2
push edx ; save the digit for later
call @_Int2Str
pop edx
@_Int2Str2:
cmp dl,0Ah ; decimal digit?
jc @_Int2Str3
add dl,'A'-'0' ; digits greater than 9 are represented as letters
@_Int2Str3:
add dl,'0' ; convert digit into character
mov [edi],dl ; store the digit
inc edi
ret
I guess calling this function DWORD2DEC is not really a mistake, since DWORD can be interpreted as a type of INT (long I think), and DEC is referring to the representation of the number in the output string...But this comment does really not matter!
Greets, Gábor
A variation of gabor's way:
DumpEAXDecimal: ;to asciiz at edi, return edi pointing at terminal null
push eax
push edx
push ebx
xor edx,edx
push edx ;a terminator
mov ebx,10
@@: div ebx
add dl,"0" ;equivalent is "or dl,30h"
push edx
cdq ;make edx zero
or eax,eax
jnz short @B
@@: pop eax
stosb ;possibly a null
or eax,eax
jnz short @B
dec edi
pop ebx
pop edx
pop eax
retn
Instead of stosb you can call an output routine. If you don't want to pass the terminator zero, a simple revision is needed.