> code) for converting 64-bit (in EDX:EAX, for example) or larger values to
> their text representations. I'd like more than just source code handed to
> me, preferably an exaplanation
You convert a number for display in decimal (I assume that is what
you want), by repeatedly dividing by ten and saving the remainder.
Then you display all those remainders in the opposite sequence
of the order in which you got them (saving them on the stack is
the usual way to get them back in the opposite sequence).
Now, you probably want to know how to divide a 64 bit number by
ten.
I will assume the number in EBX:EAX, not in EDX:EAX
xchg eax, ebx
xor edx, edx
div ten
xchg eax, ebx
div ten
Now the remainder is in edx and the quotient is in EBX:EAX (ready
to be divided again).
Somewhere, you need "ten dd 10" to define it, and after each
divide, you need something like
mov ecx, eax
or ecx, ebx
to find out if you are down to zero yet.
For more than 64 bits, you can extend this idea to be a "long
division" in memory.
xor edx, edx
mov ecx, number_of_dwords
mov ebx, address_of_last_dword
inner_loop:
mov eax, ds:[ebx]
div ten
mov ds:[ebx], eax
sub ebx, 4
loop inner_loop
All that divides a big number by ten. Then you need an outer loop
to save the remainders and watch for zero. Obviously you can
make it faster with things like remembering the highest order
nonzero dword and starting there, rather than blindly dividing
them all.
--
http://www.erols.com/johnfine/
http://www.geocities.com/SiliconValley/Peaks/8600/
> Does anyone have any information (either in the form of links and/or example
> code) for converting 64-bit (in EDX:EAX, for example) or larger values to
> their text representations. I'd like more than just source code handed to
> me, preferably an exaplanation of how the conversion is actually carried out
> would be included.
Below is a fast, compact routine that will write any number in ASCII
decimal up to 64,536 decimal digits! Hope that's enough. :)
--
Richard
Web site: http://www.gate.net/~pavlicek
;--- WRITE NUMBER IN ASCII DECIMAL
;--- Call with:
;--- ds:si = pointer to HIGH dword of number
;--- cx = size of number in double words
;--- es:di = END pointer for result string (if di = 0, result is
;--- stored from 0FFFFh downward, allowing maximum 64K digits)
;--- Returns:
;--- es:di = pointer to START of ASCII digit string
;--- cx = number of digits (0 = 64K)
WDECP:
push di ;save to find ASCII digit count later
WDEC1:
push cx ;save dword count
push si ;save high pointer
sub di,8 ;make space for 8 decimal digits
mov ebx,100000000 ;100 million
sub edx,edx ;initialize remainder
WDEC2:
mov eax,[si] ;get dword of dividend
div ebx ;divide by 100 million
mov [si],eax ;save quotient
sub si,4 ;move to next dword (if any)
loop WDEC2 ;repeat
mov eax,edx ;remainder (0-99999999)
sub edx,edx ;extend for division
mov ebx,10000 ;divisor to make 4-digit groups
div ebx ;dx = 0-9999, ax = 0-9999
mov bl,100 ;divisor to make 2-digit groups
div bl ;ah = 0-99, al = 0-99
push ax ;preserve al
mov al,ah ;least significant 2 digits
aam ;ah = 0-9, al = 0-9
xchg al,ah ;reverse order
shl eax,16 ;hold in upper half of eax
pop ax ;restore most significant digits
aam ;ah = 0-9, al = 0-9
xchg al,ah ;reverse order
or eax,30303030h ;make ASCII
mov es:[di],eax ;most significant 4 digits
mov ax,dx ;least significant (0-9999)
div bl ;ah = 0-99, al = 0-99
push ax ;preserve al
mov al,ah ;least significant 2 digits
aam ;ah = 0-9, al = 0-9
xchg al,ah ;reverse order
shl eax,16 ;hold in upper half of eax
pop ax ;restore most significant digits
aam ;ah = 0-9, al = 0-9
xchg al,ah ;reverse order
or eax,30303030h ;make ASCII
mov es:[di+4],eax ;least significant 4 digits
pop si ;restore high dword pointer
pop cx ;restore dword count
cmp dword ptr[si],0 ;is high dword zeroed yet?
jne WDEC1 ;no, continue with same count
sub si,4 ;yes, move to next dword (if any)
loop WDEC1 ;reduce count and continue if more
mov al,'0' ;check for leading zeros to cleanup
mov cx,8 ;maximum needed to check
repe scasb ;advances di PAST first non-zero digit
dec di ;point to first non-zero digit in string
pop cx ;restore original pointer (was di)
sub cx,di ;difference = number of ASCII digits
retn
decode proc uses esi edi, value:qword, buffer:dword
xor ecx, ecx
mov edi, buffer
mov esi, 10
mov eax, dword ptr value[0]
mov edx, dword ptr value[4]
xchg ebx, edx
@@1:
xor edx, edx
xchg ebx, eax
div esi
xchg ebx, eax
div esi
add dl, '0'
cmp dl, ':'
jb @@2
add dl, 7
@@2:
inc ecx
push edx
mov edx, eax
or edx, edx
jnz @@1
@@3:
pop edx
mov [edi], dl
loopd @@3
mov byte ptr [edi], 0
ret
decode endp