This one is aimed at converting a 2-digit DWORD numeric value to a string value.
I don't think this is the best way of doing it...However, I need your experience to show me how to better do it

``````
;first contains the DWORD no(max 99), second contains the address of the string

dw2numstr proc uses esi first:DWORD,second:DWORD

local temp1:BYTE
local temp2:BYTE

mov temp1,byte ptr 0
mov temp2,byte ptr 0
mov ecx,first

thisis:
cmp temp1,9
je incsecond
dec ecx
cmp ecx,0
je endo
jmp thisis

incsecond:
cmp temp2,9
je endo
mov temp1,byte ptr 0
dec ecx
cmp ecx,0
je endo
jmp thisis

endo:
xor eax,eax
mov ah,temp1
mov al,temp2
mov esi,second
mov word ptr[esi],ax
ret

dw2numstr endp
``````
Posted on 2002-10-31 08:07:59 by hosam_shahin
``````
dw2numstr PROC val:BYTE, pStr:DWORD
mov al, val
mov edx, pStr
aam

mov [edx], ah
mov [edx + 1], al
mov BYTE PTR [edx + 2], 0
ret
dw2numstr ENDP
``````
Posted on 2002-10-31 08:20:35 by Mirno
Thanx Mirno,
I didnt know that bit about 'aam', but inspiring now
Posted on 2002-10-31 09:55:39 by hosam_shahin
AAM is in fact a special division instruction which IIRC divides ax by a constant 8-bit number. It puts the result in ah and the remainder in al. That's why it's encoded as TWO bytes, 0d4h 0ah, the second byte is a '10'. Using this technique I believe limits you to 99.

Anyway to do dw2string conversions properly, you must first learn how division is done using the 'div' instruction. This is the algorithm:

put the number in an accumulator
loop1:
divide by 10
keep the result in the accumulator
keep the remainder in a buffer, add 48 to adjust to ASCII. NOTE: we will extract digits in REVERSE order, so you might want to load the buffer in REVERSE order.
if you're satisfied with the number of digits already processed, stop loop. Otherwise jmp to loop1

After the loop, you might want to strip leading zeros. If you didn't load the buffer in reverse, you also want to reverse it now.
Posted on 2002-10-31 21:27:54 by AmkG
AAM is not limited to 0xA:
``````
AX=0029  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0E9C  ES=0E9C  SS=0E9C  CS=0E9C  IP=0100   NV UP EI PL NZ NA PO NC
0E9C:0100 D420          AAM     20
-t

AX=0109  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0E9C  ES=0E9C  SS=0E9C  CS=0E9C  IP=0102   NV UP EI PL NZ NA PE NC
0E9C:0102 D408          AAM     08
-t

AX=0101  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0E9C  ES=0E9C  SS=0E9C  CS=0E9C  IP=0104   NV UP EI PL NZ NA PO NC
0E9C:0104 EBFA          JMP     0100
``````

debug.exe will dissasemble 0xD4 0x08 as AAM 08, but won't assemble it.
Posted on 2002-11-01 01:21:01 by eet_1024
Anyway to do dw2string conversions properly, you must first learn how division is done using the 'div' instruction. This is the algorithm:

put the number in an accumulator
loop1:
divide by 10
keep the result in the accumulator
keep the remainder in a buffer, add 48 to adjust to ASCII. NOTE: we will extract digits in REVERSE order, so you might want to load the buffer in REVERSE order.
if you're satisfied with the number of digits already processed, stop loop. Otherwise jmp to loop1

After the loop, you might want to strip leading zeros. If you didn't load the buffer in reverse, you also want to reverse it now.

Several examples/ideas by chorus and I in this thread:

http://www.asmcommunity.net/board/index.php?topic=8605
Posted on 2002-11-01 03:32:36 by ThoughtCriminal
Mirno,

very clever idea aam :)

eet.1024,
then aam only works in AL, not AX or EAX?

ANd then what's the difference with aad?

(aas and aaa use the carry, are another kind)
Posted on 2002-11-01 07:26:22 by slop
I don't believe that AA and DA have 32bit versions.

The AAM and AAD instructions are very expensive:
``````
8086  60    83 Clock Cycles
80486  14    15 Clock Cycles
``````

You're better off using shl for multiplies.

AAD: al = ah*Base + al
Note: Flag.AuxillaryCarry will be set if AL overflows (AH will still equal 0).

``````
AX=3135  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0E9C  ES=0E9C  SS=0E9C  CS=0E9C  IP=0100   NV UP EI PL NZ NA PE NC
0E9C:0100 250F0F        AND     AX,0F0F
-t

AX=0105  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0E9C  ES=0E9C  SS=0E9C  CS=0E9C  IP=0103   NV UP EI PL NZ NA PE NC
-t

AX=000F  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0E9C  ES=0E9C  SS=0E9C  CS=0E9C  IP=0105   NV UP EI PL NZ NA PE NC
0E9C:0105 B81001        MOV     AX,0110
-t

AX=0110  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0E9C  ES=0E9C  SS=0E9C  CS=0E9C  IP=0108   NV UP EI PL NZ NA PE NC
-t

AX=0018  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0E9C  ES=0E9C  SS=0E9C  CS=0E9C  IP=010A   NV UP EI PL NZ NA PE NC
0E9C:010A EBF4          JMP     0100
``````
Posted on 2002-11-02 01:39:54 by eet_1024
eet, sure,

but 'in extremis' it could be done with streming SIMD, 4 or eight at a time, right?
Posted on 2002-11-05 06:56:34 by slop
Hosam,
I have included some code you might find useful in the attachment. It has a lot of bells and whistles, but maybe you can trim it down to the simpler needs you have. Ask, if you have any questions. Ratch
Posted on 2002-11-17 16:11:55 by Ratch
Thank you very much Ratch,:alright:
It is to become known that your code is very helpful as it is developed in great detail.
I used the main idea to write this routine to convert a DWORD value to a string one:
``````

dw2str proc first:DWORD,second:DWORD
local temp:DWORD
MOV EAX,first
MOV temp,EAX
MOV EBX,10
MOV ECX,0
MOV ESI,second

loop1:
MOV EAX,temp
XOR EDX,EDX
DIV EBX			;~~~~~~~~~
MOV temp,EAX		;`````````
push EDX			;thanx Ratch
INC ECX			;
CMP EAX,0		;`````````
JE endo
JMP loop1

endo:
MOV EDX,0
endo1:
POP EAX
MOV byte ptr [esi+edx],al
INC EDX
DEC ECX
CMP ECX,0
JNE endo1

MOV byte ptr[ESI+EDX],0
ret
dw2numstr endp

``````

It might look bit compliacated, but I am not that professional yet!
Posted on 2002-11-17 18:18:33 by hosam_shahin
Evolving the code you posted:

``````
dw2str proc USES EBX, ESI first:DWORD,second:DWORD
; - DONT NEED -> local temp:DWORD
MOV EAX,first
; - DONT NEED -> MOV temp,EAX
MOV EBX,10       ; Added USES EBX to proc because of this
XOR ECX, ECX     ; <-Smaller opcode than -> MOV ECX,0
MOV ESI,second   ; Added USES ESI to proc because of this

loop1:
; - DONT NEED -> MOV EAX,temp <- EAX will always be equal to temp
XOR EDX,EDX
DIV EBX
; - DONT NEED -> MOV temp,EAX
push EDX
INC ECX
OR EAX, EAX   ; <-Smaller opcode than -> CMP EAX,0
JNE loop1
; JE endo
; JMP loop1

XOR EDX, EDX  ; <-Smaller opcode than -> MOV EDX,0
endo1:
POP EAX
MOV byte ptr [esi+edx],al
INC EDX
DEC ECX
; CMP not needed, DEC sets the zero flag CMP ECX,0
JNE endo1

MOV byte ptr[ESI+EDX],0
ret
dw2numstr endp
``````

And then further:
``````
dw2str proc USES ESI first:DWORD,second:DWORD
MOV EAX,first
MOV ECX,10
MOV ESI,second

@@:
XOR EDX,EDX
DIV ECX
MOV byte ptr [ESI], DL
INC ESI
OR  EAX, EAX
JNE @B

MOV byte ptr[ESI],0
ret
dw2numstr endp
``````

Mirno
Posted on 2002-11-18 04:14:33 by Mirno
.:grin:
Thnx again Mirno,