Trying to implement a chunk of code Clive posted some months ago, I have strange results:
Quote
0
20
0
19
0
18
0
17
0
16
0
15
0
14
0
13
0
12
0
11
010
09
08
07099060990509904099030990209901099900,000
something is wrong with this code:
; ---------------------------------------------------------------------------
; Algo #02 to test and code to manage the display of the results.
; ---------------------------------------------------------------------------
include \masm32\include\masm32rt.inc
.686
.mmx
.xmm
;----------------------------------------------------------------------------
; Equates used
;----------------------------------------------------------------------------
Four EQU 4
One EQU 1
.data
align Four
;---------------------------------------------------------------------------------
NumToTest dword 0
dword 9
dword 10
dword 99
dword 100
dword 999
dword 1000
dword 9999
dword 10000
dword 99999
dword 100000
dword 999999
dword 1000000
dword 9999999
dword 10000000
dword 99999999
dword 100000000
dword 999999999
dword 1000000000
dword 4294967295
PtrNumToTest dword NumToTest
NumFormat db 20 dup (0)
PtrNumFormat dword NumFormat
; ---------------------------------------------------------------------------
.code
start:
Main proc
align Four
CALL AlgoN2
inkey " ---- OK ------ ",13,10
exit
Main endp
AlgoN2 proc
; EAX = 32-bit number
; ESI = string buffer for NUL terminated ASCII
; Uses ESI,EDI,EAX,ECX,EDX,EBX
xor ebx, ebx
mov ebx, 20
lea esi, NumFormat
lea eax, NumToTest
mov PtrNumToTest, eax
ConvertNext:
mov eax, PtrNumToTest
mov eax, [eax]
push 0 ; Mark stack end with NUL
divloop:
mov ecx,1000 ; Divide into 3 digit groups
xor edx,edx ; Clear high order 32-bit for divide
idiv ecx ; eax = edx:eax / ecx, edx = edx:eax % ecx
mov edi,eax ; Save division result
mov ecx,10 ; Subdivide in 10's
mov eax,edx ; Get remainder
or edi,edi ; Still number left, so at least 3 digits in remainder
jnz digit000
cmp eax,10 ; remainder has one digit
jb digit0
cmp eax,100 ; remainder has two digits
jb digit00
digit000: ; 3 digits
xor edx,edx ; Clear high order 32-bit for divide
idiv ecx ; eax = edx:eax / ecx, edx = edx:eax % ecx
add edx,30h ; += '0'
push edx ; Stack
digit00: ; 2 digits
xor edx,edx ; Clear high order 32-bit for divide
idiv ecx ; eax = edx:eax / ecx, edx = edx:eax % ecx
add edx,30h ; += '0'
push edx ; Stack
digit0: ; 1 digit
xor edx,edx ; Clear high order 32-bit for divide
; idiv ecx ; eax = edx:eax / ecx, edx = edx:eax % ecx
; The digit here is 0 to 9 no need to divide
add edx,30h ; += '0'
push edx ; Stack
mov eax,edi ; Recover remaining number
or eax,eax ; Zero?
jz poploop
push 2Ch ; Comma added to groups of three digits
jmp divloop
poploop:
pop eax ; Recover next digit
mov [esi],al ; Add to string
inc esi
or eax,eax ; Was it a NUL?
jnz poploop
push ebx
push esi
; -----------------------------------------------------------------
print ADDR NumFormat,13,10
print sstr$(ebx),13,10
; -----------------------------------------------------------------
pop esi
pop ebx
add PtrNumToTest, Four ; Next number to convert
sub ebx, One
jnz ConvertNext
ret
AlgoN2 endp
;----------------------------------------------------------------------------
; End of program
;----------------------------------------------------------------------------
end start
::) ::) ::)
; ---------------------------------------------------------------------------
; Algo #02 to test and code to manage the display of the results.
; ---------------------------------------------------------------------------
include \masm32\include\masm32rt.inc
.686
.mmx
.xmm
;----------------------------------------------------------------------------
; Equates used
;----------------------------------------------------------------------------
Four EQU 4
One EQU 1
.data
align Four
;---------------------------------------------------------------------------------
NumToTest dword 0
dword 9
dword 10
dword 99
dword 100
dword 999
dword 1000
dword 9999
dword 10000
dword 99999
dword 100000
dword 999999
dword 1000000
dword 9999999
dword 10000000
dword 99999999
dword 100000000
dword 999999999
dword 1000000000
dword 4294967295
PtrNumToTest dword offset NumToTest
NumFormat db 20 dup (0)
PtrNumFormat dword offset NumFormat
; ---------------------------------------------------------------------------
.code
start:
Main proc
align Four
CALL AlgoN2
inkey " ---- OK ------ ",13,10
exit
Main endp
AlgoN2 proc
; EAX = 32-bit number
; ESI = string buffer for NUL terminated ASCII
; Uses ESI,EDI,EAX,ECX,EDX,EBX
xor ebx, ebx
mov ebx, 20
lea eax, NumToTest
mov PtrNumToTest, eax
ConvertNext:
lea esi, NumFormat ; Helps to initialize it every time round
mov eax, PtrNumToTest
mov eax, [eax]
push 0 ; Mark stack end with NUL
divloop:
mov ecx,1000 ; Divide into 3 digit groups
xor edx,edx ; Clear high order 32-bit for divide
idiv ecx ; eax = edx:eax / ecx, edx = edx:eax % ecx
mov edi,eax ; Save division result
mov ecx,10 ; Subdivide in 10's
mov eax,edx ; Get remainder
or edi,edi ; Still number left, so at least 3 digits in remainder
jnz digit000
cmp eax,10 ; remainder has one digit
jb digit0
cmp eax,100 ; remainder has two digits
jb digit00
digit000: ; 3 digits
xor edx,edx ; Clear high order 32-bit for divide
idiv ecx ; eax = edx:eax / ecx, edx = edx:eax % ecx
add edx,30h ; += '0'
push edx ; Stack
digit00: ; 2 digits
xor edx,edx ; Clear high order 32-bit for divide
idiv ecx ; eax = edx:eax / ecx, edx = edx:eax % ecx
add edx,30h ; += '0'
push edx ; Stack
digit0: ; 1 digit
if 0
xor edx,edx ; Clear high order 32-bit for divide
idiv ecx ; eax = edx:eax / ecx, edx = edx:eax % ecx
add edx,30h ; += '0'
push edx ; Stack
else
; The digit here (IN EAX) is 0 to 9 no need to divide
add eax,30h ; += '0'
push eax ; Stack
endif
mov eax,edi ; Recover remaining number
or eax,eax ; Zero?
jz poploop
push 2Ch ; Comma added to groups of three digits
jmp divloop
poploop:
pop eax ; Recover next digit
mov [esi],al ; Add to string
inc esi
or eax,eax ; Was it a NUL?
jnz poploop
push ebx
push esi
; -----------------------------------------------------------------
print ADDR NumFormat,13,10
print sstr$(ebx),13,10,10
; -----------------------------------------------------------------
pop esi
pop ebx
add PtrNumToTest, Four ; Next number to convert
sub ebx, One
jnz ConvertNext
ret
AlgoN2 endp
;----------------------------------------------------------------------------
; End of program
;----------------------------------------------------------------------------
end start
0
20
9
19
10
18
99
17
100
16
999
15
1,000
14
9,999
13
10,000
12
99,999
11
100,000
10
999,999
9
1,000,000
8
9,999,999
7
10,000,000
6
99,999,999
5
100,000,000
4
999,999,999
3
1,000,000,000
2
4,294,967,295
1
---- OK ------
Thanks Clive :U
Now I can insert it into the Testbed and see how it performs. :bg
Four EQU 4
One EQU 1
:red
Quote from: brethren on November 18, 2010, 06:58:01 PM
Four EQU 4
One EQU 1
:red
I like code like this one:
sub ebx, One
add eax, Four
:P
Frank