Hi,
I know there is a macro that does this already, but here is my take on it. Uses three registers - eax, ecx and edx.
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\masm32rt.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\masm32rt.lib
includelib \masm32\lib\kernel32.lib
.code
dwrd DWORD 0F2345678h
b BYTE 0,0,0,0,0,0,0,0,0
asciitable BYTE "0123456789ABCDEF"
start:
sub esp,4
push esp
push PAGE_READWRITE
push 8
push offset b
call VirtualProtect
add esp,4
mov eax,dwrd
mov ecx,8
@@:
mov edx,eax
and edx,0Fh
mov edx,[offset asciitable+edx]
mov byte ptr [offset b+ecx-1],dl
ror eax,4
dec ecx
jnz @B
print offset b
xor eax,eax
ret
end start
Best regards,
Robin.
no need to place data in the code segent and use VirtualProtect - why not just use the data segment ?
also - no need for a table - Larry had a neat trick on this post...
http://www.masm32.com/board/index.php?topic=12964.0
(although, i wouldn't necessarily use AAM 10h)
Hi,
I put it in the .code segment as it shaved 512 bytes off the final EXE (seemed excessive when all I need is 29 bytes!).
I just did a small mod to eliminate the temporary DWORD for the required pointer destination by VirtualProtect.
I could save another register by unrolling the loop.
Best regards,
Robin.
you might try using PoLink from Pelle's C compiler package - it will make smaller EXE's
but - nowdays - most drives have cluster sizes of 4 K or larger - 8 K on mine, i think
saving 512 bytes isn't a biggy
the thing is speed - it takes more time to use VirtualProtect if you have a large number of values to convert
with the size of modern drives and memory, speed is better than size
Hmm. polink never creates smaller .EXEs for me. It is still 1536 bytes.
@echo off
echo Building...
ml /c /coff /Cp test.asm
polink /SUBSYSTEM:CONSOLE /LIBPATH:\masm32\lib test.obj
dir test.*
echo Finished!!
pause
Robin,
The idea looks OK, I would be inclined to put it inside a procedure without a stack frame and pass to the proc the size data work area you require, otherwise just create a local on the stack with the same capacity. What you have effectively done is merge the code and data sections which saves you the 512 bytes in a small test piece but affords you no size advantage when you have to write this conversion into a working app.
Hi,
Yes - it was just something I was playing with asa a stand-alone piece, but was contemplating making it a proc.
I got it to this:
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\masm32rt.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.data
dwrd DWORD 0F2345678h
asciitable BYTE "0123456789ABCDEF"
b BYTE 0,0,0,0,0,0,0,0,0
.code
start:
align 4
mov eax,dwrd
mov ecx,8
@@:
mov edx,eax
and edx,0Fh
mov edx,[offset asciitable+edx]
mov byte ptr [offset b+ecx-1],dl
ror eax,4
dec ecx
jnz @B
print offset b
xor eax,eax
ret
end start
The following is untested, but I wondered about:
.data
ASCIITable BYTE "0123456789ABCDEF"
.code
dw2ascii proc EndPos:DWORD,StartPos:DWORD,ptrAscBuf:DWORD,ptrDwrdBuf:DWORD
mov eax,ptrDwrdBuf
mov ecx,EndPos
sub ecx,StartPos
@@:
mov edx,eax
and edx,0Fh
mov edx,[offset ASCIITable+edx]
mov byte ptr [ptrAscBuf+ecx-1],dl
ror eax,4
dec ecx
jnz @B
ret 16
dw2ascii endp
It needs a bit of work for anything longer than 4 bytes. :boohoo: An outer loop in byte steps is probably the solution. Back tomorrow!
Best regards,
Robin.
i stole Larry Hammick's little snippet to make this proc
it may not even be all that fast - but it is flexible and convenient
in normal use of these kinds of routines, we usually aren't going to convert 10,000 dwords
it follows the conventions of a 32-bit proc, preserving EBX, ESI, EDI, EBP and the DF
the buffer address is returned in EDX for convenience
it is 41 bytes long
if i wanted to speed it up, i would probably align the buffer (as well as the proc)
then, i would write it so it makes 2 dword writes into the buffer instead of 8 bytes - would take a little more code
HxDwd PROTO :DWORD,:DWORD
;-----------------------------------------------------------------------------------------
OPTION EPILOGUE:NONE
OPTION PROLOGUE:NONE
HxDwd PROC dwBinVal:DWORD,lpBuffer:DWORD
;
; Convert a binary dword to ASCII hexidemal string
;
; Usage:
; INVOKE HxDwd, dwBinVal, lpBuffer
;
; dwBinVal = binary dword to convert
; lpBuffer = address of string buffer
;
; Returns:
; EDX = lpBuffer
; ECX = 0
;
; EBX, ESI, EDI, EBP, DF preserved
push edi
mov ecx,8
mov edi,[esp+12]
mov edx,[esp+8]
add edi,ecx
HxDwd0: mov eax,edx
and eax,0Fh
dec edi
cmp eax,0Ah
sbb eax,69h
das
shr edx,4
mov [edi],al
dec ecx
jnz HxDwd0
mov edx,edi
pop edi
ret
HxDwd ENDP
OPTION EPILOGUE:EpilogueDef
OPTION PROLOGUE:ProEpilogueDef
;-----------------------------------------------------------------------------------------