Here is a quick play to do both algos separately. Results look like this.
1638212 = ESP stack address
87654321 +unsigned+
1638212 = ESP stack address
10293847 +unsigned+
-44444444 -signed-
-12345678 -signed-
-1 -signed-
4294967295 +unsigned+
0 +unsigned+
Press any key to continue ...
The test piece.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
utoa$ MACRO variable
LOCAL buffer
.data?
align 16
buffer db 32 dup (?)
.code
push OFFSET buffer
push variable
call unumtostr
mov eax, OFFSET buffer
EXITM <eax>
ENDM
stoa$ MACRO variable
LOCAL buffer
.data?
align 16
buffer db 32 dup (?)
.code
push OFFSET buffer
push variable
call snumtostr
mov eax, OFFSET buffer
EXITM <eax>
ENDM
ShowESP MACRO
IFNDEF esp_reg
.data?
esp_reg dd ?
.code
ENDIF
mov esp_reg, esp
print ustr$(esp_reg)," = ESP stack address",13,10
ENDM
unumtostr PROTO LongVar:DWORD,answer:DWORD
snumtostr PROTO LongVar:DWORD,answer:DWORD
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL pnum[16]:DWORD
mov pnum[0], 10293847
mov pnum[4], -44444444
lea esi, pnum
ShowESP
mov eax, 87654321
print utoa$(eax)," +unsigned+",13,10
ShowESP
print utoa$([esi])," +unsigned+",13,10
print stoa$([esi+4])," -signed-",13,10
print stoa$(-12345678)," -signed-",13,10
print stoa$(-1)," -signed-",13,10
print utoa$(4294967295)," +unsigned+",13,10
print utoa$(0)," +unsigned+",13,10
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
unumtostr proc LongVar:DWORD,answer:DWORD
; -----------------------------------------
; This algorithm was designed by Paul Dixon
; -----------------------------------------
.data
align 4
chartab \
dd "00","10","20","30","40","50","60","70","80","90"
dd "01","11","21","31","41","51","61","71","81","91"
dd "02","12","22","32","42","52","62","72","82","92"
dd "03","13","23","33","43","53","63","73","83","93"
dd "04","14","24","34","44","54","64","74","84","94"
dd "05","15","25","35","45","55","65","75","85","95"
dd "06","16","26","36","46","56","66","76","86","96"
dd "07","17","27","37","47","57","67","77","87","97"
dd "08","18","28","38","48","58","68","78","88","98"
dd "09","19","29","39","49","59","69","79","89","99"
.code
push esi
push edi
mov eax, [esp+4][8] ; LongVar get number
mov ecx, [esp+8][8] ; answer get pointer to answer string
; ; --------------------------
; ; do a signed DWORD to ASCII
; ; --------------------------
; or eax,eax ; test sign
; jns udword ; if +ve, continue as for unsigned
; neg eax ; else, make number positive
; mov byte ptr [ecx],"-" ; include the - sign
; inc ecx ; update the pointer
udword:
; -----------------------
; unsigned DWORD to ASCII
; -----------------------
mov esi,ecx ; get pointer to answer
mov edi,eax ; save a copy of the number
mov edx, 0D1B71759h ; =2^45\10000 13 bit extra shift
mul edx ; gives 6 high digits in edx
mov eax, 68DB9h ; =2^32\10000+1
shr edx,13 ; correct for multiplier offset used to give better accuracy
jz skiphighdigits ; if zero then don't need to process the top 6 digits
mov ecx,edx ; get a copy of high digits
imul ecx,10000 ; scale up high digits
sub edi,ecx ; subtract high digits from original. EDI now = lower 4 digits
mul edx ; get first 2 digits in edx
mov ecx,100 ; load ready for later
jnc next1 ; if zero, supress them by ignoring
cmp edx,9 ; 1 digit or 2?
ja ZeroSupressed ; 2 digits, just continue with pairs of digits to the end
mov edx,chartab[edx*4] ; look up 2 digits
mov [esi],dh ; but only write the 1 we need, supress the leading zero
inc esi ; update pointer by 1
jmp ZS1 ; continue with pairs of digits to the end
next1:
mul ecx ; get next 2 digits
jnc next2 ; if zero, supress them by ignoring
cmp edx,9 ; 1 digit or 2?
ja ZS1a ; 2 digits, just continue with pairs of digits to the end
mov edx,chartab[edx*4] ; look up 2 digits
mov [esi],dh ; but only write the 1 we need, supress the leading zero
inc esi ; update pointer by 1
jmp ZS2 ; continue with pairs of digits to the end
next2:
mul ecx ; get next 2 digits
jnc next3 ; if zero, supress them by ignoring
cmp edx,9 ; 1 digit or 2?
ja ZS2a ; 2 digits, just continue with pairs of digits to the end
mov edx,chartab[edx*4] ; look up 2 digits
mov [esi],dh ; but only write the 1 we need, supress the leading zero
inc esi ; update pointer by 1
jmp ZS3 ; continue with pairs of digits to the end
next3:
skiphighdigits:
mov eax,edi ; get lower 4 digits
mov ecx,100
mov edx, 28F5C29h ; 2^32\100 +1
mul edx
jnc next4 ; if zero, supress them by ignoring
cmp edx,9 ; 1 digit or 2?
ja ZS3a ; 2 digits, just continue with pairs of digits to the end
mov edx,chartab[edx*4] ; look up 2 digits
mov [esi],dh ; but only write the 1 we need, supress the leading zero
inc esi ; update pointer by 1
jmp ZS4 ; continue with pairs of digits to the end
next4:
mul ecx ; this is the last pair so don't supress a single zero
cmp edx,9 ; 1 digit or 2?
ja ZS4a ; 2 digits, just continue with pairs of digits to the end
mov edx,chartab[edx*4] ; look up 2 digits
mov [esi],dh ; but only write the 1 we need, supress the leading zero
mov byte ptr [esi+1],0 ; zero terminate string
jmp xit ; all done
ZeroSupressed:
mov edx,chartab[edx*4] ; look up 2 digits
mov [esi],dx
add esi,2 ; write them to answer
ZS1:
mul ecx ; get next 2 digits
ZS1a:
mov edx,chartab[edx*4] ; look up 2 digits
mov [esi],dx ; write them to answer
add esi,2
ZS2:
mul ecx ; get next 2 digits
ZS2a:
mov edx,chartab[edx*4] ; look up 2 digits
mov [esi],dx ; write them to answer
add esi,2
ZS3:
mov eax,edi ; get lower 4 digits
mov edx,28F5C29h ; 2^32\100 +1
mul edx ; edx= top pair
ZS3a:
mov edx,chartab[edx*4] ; look up 2 digits
mov [esi],dx ; write to answer
add esi,2 ; update pointer
ZS4:
mul ecx ; get final 2 digits
ZS4a:
mov edx,chartab[edx*4] ; look them up
mov [esi],dx ; write to answer
mov byte ptr [esi+2],0 ; zero terminate string
xit:
sdwordend:
pop edi
pop esi
ret 8
unumtostr endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
snumtostr proc LongVar:DWORD,answer:DWORD
; -----------------------------------------
; This algorithm was designed by Paul Dixon
; -----------------------------------------
.data
align 4
schartab \
dd "00","10","20","30","40","50","60","70","80","90"
dd "01","11","21","31","41","51","61","71","81","91"
dd "02","12","22","32","42","52","62","72","82","92"
dd "03","13","23","33","43","53","63","73","83","93"
dd "04","14","24","34","44","54","64","74","84","94"
dd "05","15","25","35","45","55","65","75","85","95"
dd "06","16","26","36","46","56","66","76","86","96"
dd "07","17","27","37","47","57","67","77","87","97"
dd "08","18","28","38","48","58","68","78","88","98"
dd "09","19","29","39","49","59","69","79","89","99"
.code
push esi
push edi
mov eax, [esp+4][8] ; LongVar get number
mov ecx, [esp+8][8] ; answer get pointer to answer string
; --------------------------
; do a signed DWORD to ASCII
; --------------------------
or eax,eax ; test sign
jns udword ; if +ve, continue as for unsigned
neg eax ; else, make number positive
mov byte ptr [ecx],"-" ; include the - sign
inc ecx ; update the pointer
udword:
; -----------------------
; unsigned DWORD to ASCII
; -----------------------
mov esi,ecx ; get pointer to answer
mov edi,eax ; save a copy of the number
mov edx, 0D1B71759h ; =2^45\10000 13 bit extra shift
mul edx ; gives 6 high digits in edx
mov eax, 68DB9h ; =2^32\10000+1
shr edx,13 ; correct for multiplier offset used to give better accuracy
jz skiphighdigits ; if zero then don't need to process the top 6 digits
mov ecx,edx ; get a copy of high digits
imul ecx,10000 ; scale up high digits
sub edi,ecx ; subtract high digits from original. EDI now = lower 4 digits
mul edx ; get first 2 digits in edx
mov ecx,100 ; load ready for later
jnc next1 ; if zero, supress them by ignoring
cmp edx,9 ; 1 digit or 2?
ja ZeroSupressed ; 2 digits, just continue with pairs of digits to the end
mov edx,schartab[edx*4] ; look up 2 digits
mov [esi],dh ; but only write the 1 we need, supress the leading zero
inc esi ; update pointer by 1
jmp ZS1 ; continue with pairs of digits to the end
next1:
mul ecx ; get next 2 digits
jnc next2 ; if zero, supress them by ignoring
cmp edx,9 ; 1 digit or 2?
ja ZS1a ; 2 digits, just continue with pairs of digits to the end
mov edx,schartab[edx*4] ; look up 2 digits
mov [esi],dh ; but only write the 1 we need, supress the leading zero
inc esi ; update pointer by 1
jmp ZS2 ; continue with pairs of digits to the end
next2:
mul ecx ; get next 2 digits
jnc next3 ; if zero, supress them by ignoring
cmp edx,9 ; 1 digit or 2?
ja ZS2a ; 2 digits, just continue with pairs of digits to the end
mov edx,schartab[edx*4] ; look up 2 digits
mov [esi],dh ; but only write the 1 we need, supress the leading zero
inc esi ; update pointer by 1
jmp ZS3 ; continue with pairs of digits to the end
next3:
skiphighdigits:
mov eax,edi ; get lower 4 digits
mov ecx,100
mov edx, 28F5C29h ; 2^32\100 +1
mul edx
jnc next4 ; if zero, supress them by ignoring
cmp edx,9 ; 1 digit or 2?
ja ZS3a ; 2 digits, just continue with pairs of digits to the end
mov edx,schartab[edx*4] ; look up 2 digits
mov [esi],dh ; but only write the 1 we need, supress the leading zero
inc esi ; update pointer by 1
jmp ZS4 ; continue with pairs of digits to the end
next4:
mul ecx ; this is the last pair so don't supress a single zero
cmp edx,9 ; 1 digit or 2?
ja ZS4a ; 2 digits, just continue with pairs of digits to the end
mov edx,schartab[edx*4] ; look up 2 digits
mov [esi],dh ; but only write the 1 we need, supress the leading zero
mov byte ptr [esi+1],0 ; zero terminate string
jmp xit ; all done
ZeroSupressed:
mov edx,schartab[edx*4] ; look up 2 digits
mov [esi],dx
add esi,2 ; write them to answer
ZS1:
mul ecx ; get next 2 digits
ZS1a:
mov edx,schartab[edx*4] ; look up 2 digits
mov [esi],dx ; write them to answer
add esi,2
ZS2:
mul ecx ; get next 2 digits
ZS2a:
mov edx,schartab[edx*4] ; look up 2 digits
mov [esi],dx ; write them to answer
add esi,2
ZS3:
mov eax,edi ; get lower 4 digits
mov edx,28F5C29h ; 2^32\100 +1
mul edx ; edx= top pair
ZS3a:
mov edx,schartab[edx*4] ; look up 2 digits
mov [esi],dx ; write to answer
add esi,2 ; update pointer
ZS4:
mul ecx ; get final 2 digits
ZS4a:
mov edx,schartab[edx*4] ; look them up
mov [esi],dx ; write to answer
mov byte ptr [esi+2],0 ; zero terminate string
xit:
sdwordend:
pop edi
pop esi
ret 8
snumtostr endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start