The 'dwtoa' procedure in masm32.lib works great as long as you understand that
it always treats the value being converted as signed. If you want to convert an
unsigned value greater than 07FFFFFFFh your out of luck. I modified the 'dwtoa'
procedure to always treat the value being converted as unsigned and named it
'udwtoa'. I then set an alias of 'sdwtoa' to 'dwtoa' and then derived some
procedures for converting bytes and words, signed and unsigned to ASCIIZ. If
anyone finds them useful that's great.
.386
.MODEL FLAT,STDCALL
OPTION CASEMAP:NONE
INCLUDE windows.inc
INCLUDE kernel32.inc
INCLUDE masm32.inc
INCLUDE c:\masm32\macros\macros.asm
INCLUDELIB kernel32.lib
INCLUDELIB masm32.lib
udwtoa PROTO udwValue:DWORD, pszBuffer:PTR BYTE
sdwtoa TEXTEQU <dwtoa>
uwtoa PROTO uwValue:WORD, pszBuffer:PTR BYTE
swtoa PROTO swValue:SWORD, pszBuffer:PTR BYTE
ubtoa PROTO ubValue:BYTE, pszBuffer:PTR BYTE
sbtoa PROTO sbValue:SBYTE, pszBuffer:PTR BYTE
SBYTE_MIN EQU -128
SBYTE_MAX EQU 127
UBYTE_MIN EQU 0
UBYTE_MAX EQU 255
SWORD_MIN EQU -32768
SWORD_MAX EQU 32767
UWORD_MIN EQU 0
UWORD_MAX EQU 65535
SDWORD_MIN EQU -2147483648
SDWORD_MAX EQU 2147483647
UDWORD_MIN EQU 0
UDWORD_MAX EQU 4294967295
.DATA?
szBuffer BYTE 256 DUP(?)
.CODE
start:
INVOKE StdOut, SADD("SBYTE",13,10);
FOR num, <SBYTE_MIN, SBYTE_MAX>
mov al, num
INVOKE sbtoa, al, ADDR szBuffer
INVOKE StdOut, ADDR szBuffer
INVOKE StdOut, SADD(13,10)
ENDM
INVOKE StdOut, SADD(13,10)
INVOKE StdOut, SADD("BYTE",13,10)
FOR num, <UBYTE_MIN, UBYTE_MAX>
mov al, num
INVOKE ubtoa, al, ADDR szBuffer
INVOKE StdOut, ADDR szBuffer
INVOKE StdOut, SADD(13,10)
ENDM
INVOKE StdOut, SADD(13,10)
INVOKE StdOut, SADD("SWORD",13,10)
FOR num, <SWORD_MIN, SWORD_MAX>
mov ax, num
INVOKE swtoa, ax, ADDR szBuffer
INVOKE StdOut, ADDR szBuffer
INVOKE StdOut, SADD(13,10)
ENDM
INVOKE StdOut, SADD(13,10)
INVOKE StdOut, SADD("WORD",13,10)
FOR num, <UWORD_MIN, UWORD_MAX>
mov ax, num
INVOKE uwtoa, ax, ADDR szBuffer
INVOKE StdOut, ADDR szBuffer
INVOKE StdOut, SADD(13,10)
ENDM
INVOKE StdOut, SADD(13,10)
INVOKE StdOut, SADD("SDWORD",13,10)
FOR num, <SDWORD_MIN, SDWORD_MAX>
mov eax, num
INVOKE sdwtoa, eax, ADDR szBuffer
INVOKE StdOut, ADDR szBuffer
INVOKE StdOut, SADD(13,10)
ENDM
INVOKE StdOut, SADD(13,10)
INVOKE StdOut, SADD("DWORD",13,10)
FOR num, <UDWORD_MIN, UDWORD_MAX>
mov eax, num
INVOKE udwtoa, eax, ADDR szBuffer
INVOKE StdOut, ADDR szBuffer
INVOKE StdOut, SADD(13,10)
ENDM
INVOKE StdOut, SADD(13,10)
INVOKE ExitProcess, 0
; *********************************************
; ASCIIZ conversion procedures based on 'dwtoa'
; *********************************************
ALIGN 4
udwtoa PROC udwValue:DWORD, pszBuffer:PTR BYTE
; ---------------------------------------------------------------
; Original procedure 'dwtoa' written by Tim Roberts
; Minor fix by Jibz, December 2004
; Modified to convert value as unsigned by Greg Lyon, May 2007
; -------------------------------------------------------------
; Convert unsigned DWORD to ASCIIZ string
; udwValue is value to be converted
; pszBuffer is the address of the receiving buffer
; EXAMPLE:
; invoke udwtoa, edx, ADDR buffer
;
; Uses: eax, ecx, edx.
; -------------------------------------------------------------
push ebx
push esi
push edi
mov eax, udwValue
mov edi, pszBuffer
test eax,eax
jnz pos
zero:
mov WORD PTR [edi], 30h
jmp dtaexit
pos:
mov ecx, 3435973837
mov esi, edi
.WHILE (eax > 0)
mov ebx, eax
mul ecx
shr edx, 3
mov eax, edx
lea edx, [edx*4+edx]
add edx, edx
sub ebx, edx
add bl, '0'
mov [edi], bl
add edi, 1
.ENDW
mov BYTE PTR [edi], 0 ; terminate the string
; We now have all the digits, but in reverse order.
.WHILE (esi < edi)
sub edi, 1
mov al, [esi]
mov ah, [edi]
mov [edi], al
mov [esi], ah
add esi, 1
.ENDW
dtaexit:
pop edi
pop esi
pop ebx
ret
udwtoa ENDP
; --------------------------------------------------
; sdwtoa TEXTEQU <dwtoa>
; --------------------------------------------------
uwtoa PROC uwValue:WORD, pszBuffer:PTR BYTE
movzx eax, uwValue
INVOKE udwtoa, eax, pszBuffer
ret
uwtoa ENDP
; --------------------------------------------------
swtoa PROC swValue:SWORD, pszBuffer:PTR BYTE
movsx eax, swValue
INVOKE sdwtoa, eax, pszBuffer
ret
swtoa ENDP
; --------------------------------------------------
ubtoa PROC ubValue:BYTE, pszBuffer:PTR BYTE
movzx eax, ubValue
INVOKE udwtoa, eax, pszBuffer
ret
ubtoa ENDP
; --------------------------------------------------
sbtoa PROC sbValue:SBYTE, pszBuffer:PTR BYTE
movsx eax, sbValue
INVOKE sdwtoa, eax, pszBuffer
ret
sbtoa ENDP
; --------------------------------------------------
END start
Greg,
Recently, I used this when adding syntax highlighting to my project:
udw2a proc source:DWORD, lpBuffer:DWORD
;---------------------------------------
push eax
push esi
mov edx, lpBuffer
mov esi, source
xor eax, eax
xor ecx, ecx
mov [edx+8], al
mov cl, 7
@@:
mov eax, esi
and al, 00001111b
cmp al,10
sbb al,69h
das
mov [edx + ecx], al
shr esi, 4
dec ecx
jns @B
pop esi
pop eax
ret
;---------------------------------------
udw2a endp
Paul
Paul,
If you need an 8 character hex string, that works great. That's tricky using DAS. :8)
Greg,
yep! RGB values, of course, used for syntax highlighting. BTW, if I do not want eight characters, I use the same procedure and just filter out the leading zeroes in the calling proc. An easy way would be to use the right$ macro, I guess. :8)
Paul