News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Dword To Hex Conversion in MASM

Started by Sean1337, August 06, 2007, 04:44:31 AM

Previous topic - Next topic

Sean1337

Hey,

I wouldn't say I'm much of a beginner but I've been trying to convert a dword to hexa for the past few hours and haven't really succeeded.

Basically what I'm doing is this.

I get a value (type dword) from a pointer.

My objective is to convert this dword to hexadecimal. E.g. if value is 16, I want to convert it to 10 in hex.

I'm not exactly sure how one might do this in MASM32 since I only started probably a few months back, but I do know, in visual basic you can use the modulus and integer division operators to do it. I.e.

16 div 16 = 1
16 mod 16 = 0 (remainder)

1 div 16 = 0
1 mod 16 = 1 (remainder)

Reading remainder's backwards, decimal 16 = hexadecimal 10.

Does anyone know how to do this in MASM32? I'd greatly appreciate it.

Thanks,
-Sean


hutch--

Sean,

Welcome on board.

Cheat, See how its done in the masm32 library.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

MichaelW

Hi Sean,

Welcome to the forum. There are multiple methods, and two possibilities are the dw2hex and dw2h_ex procedures. The source files are dw2hex.asm and dw2h_ex.asm in the m32lib directory.
eschew obfuscation

Sean1337

Thanks guys, however I did look at these previously and I didn't really understand what the code is doing, e.g. "nibbling."

dw2hex proc source:DWORD, lpBuffer:DWORD

    push esi

    mov edx, lpBuffer
    mov esi, source

    xor eax, eax
    xor ecx, ecx

    mov [edx+8], al         ; put terminator at correct length
    mov cl, 7               ; length of hexstring - 1

  @@:
    mov eax, esi            ; we're going to work on AL
    and al, 00001111b       ; mask out high nibble

    cmp al,10
    sbb al,69h
    das

    mov [edx + ecx], al     ; store the asciihex(AL) in the string
    shr esi, 4              ; next nibble
    dec ecx                 ; decrease counter (one byte less than dec cl :-)
    jns @B                  ; eat them if there's any more

    pop esi

    ret

dw2hex endp


or

dw2hex_ex proc src:DWORD,buf:DWORD

    movzx ecx, BYTE PTR [esp+4]
    mov edx, DWORD PTR [ecx+ecx+hex_table]
    mov eax, [esp+8]                        ; load buffer address
    shl edx, 16
    movzx ecx, BYTE PTR [esp+5]
    mov dx, WORD PTR [ecx+ecx+hex_table]

    movzx ecx, BYTE PTR [esp+6]
    mov [eax+4], edx                        ; write 2nd DWORD
    mov ecx, DWORD PTR [ecx+ecx+hex_table]
    movzx edx, BYTE PTR [esp+7]
    shl ecx, 16
    mov cx, WORD PTR [edx+edx+hex_table]
    xor edx, edx
    mov [eax], ecx                          ; write 1st DWORD

    mov BYTE PTR [eax+8], dl

    ret 8

dw2hex_ex endp


Could one of you possibly go through the algorithm with me, showing how say, 10 (type byte) would be converted into A (hex) and where it would be stored?

Thanks,
-Sean

Tedd

The first thing to notice is that four binary-bits map directly on to each hex digit, so you can chop the number up into 'nibble' sized chunks and convert them one at a time (so there's no need to mess around with division - though you can still do it that way if you really want to; and it is necessary for other conversion like to decimal.)
So, a 32-bit dword then becomes: 0101 1010 0000 1111 0110 0100 1111 1101 -- representing the numbers 5, 10, 0, 15, 6, 4, 15, 13.
Now the task is to convert each of these into a hex digit - '0' to '9' for values 0 to 9, and 'A' to 'F' for values 10 to 15.
There are two common ways to do it (we'll leave out any black magic unless you want your brain to hurt :wink):
The first is to take advantage of the way ascii is set out and just add '0' (that's the ascii value of the character zero, not the value zero) which will magically convert 0 into '0' and 9 into '9' (and all the numbers in between) unfortunately this doesn't help with values above 9. So you do another trick for those numbers and add on 'A'-10 (the ascii value of the letter A minus ten; same as subtracting ten and adding 'A', but in one step). But before you convert each digit you need to decide which method to use, which is as simple as comparing it against 9.
The other way is to have a string of the ascii hex digits "0123456789ABCDEF" and then use the value you're converting as an index into it. So hexstring[5] will, amazingly, give you '5', and hexstring[13] gives 'D'.
After converting each digit, you'll need to store them in an array/string so you can print them out or do whatever you want to do with them. Usually you'll be converting the right-most digit first, so you'll need to either store the characters in reverse, or print it backwards one character at a time; or do the left-most first.



(The binary string above represents: 5A0F64FD -- do a conversion by hand so it sinks in :wink)
No snowflake in an avalanche feels responsible.

hutch--

Sean,

Be careful with the _ex version, you have clipped off important directives because this procedure is written without a stack frame. The leading and trailing "OPTION" statements must be there or the procedure will not run. It uses a cruder but faster method of a preset table for the hex bytes but the price is its larger due to the table size.


align 16

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

dw2hex_ex proc src:DWORD,buf:DWORD

    movzx ecx, BYTE PTR [esp+4]
    mov edx, DWORD PTR [ecx+ecx+hex_table]
    mov eax, [esp+8]                        ; load buffer address
    shl edx, 16
    movzx ecx, BYTE PTR [esp+5]
    mov dx, WORD PTR [ecx+ecx+hex_table]

    movzx ecx, BYTE PTR [esp+6]
    mov [eax+4], edx                        ; write 2nd DWORD
    mov ecx, DWORD PTR [ecx+ecx+hex_table]
    movzx edx, BYTE PTR [esp+7]
    shl ecx, 16
    mov cx, WORD PTR [edx+edx+hex_table]
    xor edx, edx
    mov [eax], ecx                          ; write 1st DWORD

    mov BYTE PTR [eax+8], dl

    ret 8

dw2hex_ex endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Sean1337

Well someone helped me out with this and I think we've solved it..this should work:

I had made a mistake in my original post. I had mistakingly thought that dword was type decimal. What I wanted to do is convert decimal #'s to hexadecimal #'s.


.data
lpHexString db "0123456789ABCDEF"
.code

Dec2Hex proc dwValue:DWORD, lpBuffer:DWORD

mov edi, lpBuffer
mov eax, dwValue
mov ecx, 8

.repeat
mov esi, eax
and esi, 0F0000000h
shr esi, 28

movzx edx, byte ptr [lpHexString+esi]
mov byte ptr [edi], dl

shl eax, 4
inc edi
.untilcxz

ret

Dec2Hex endp


Example:

invoke Dec2Hex, 1337C0DEh, addr lpBuffer

dsouza123

A MMX version without loops.


  hold   dd 91234567h
  buffer db 16 dup (0)
  nines  db  8 dup (57)
  sevens db  8 dup (7)
  szCap  db "DWord to Hex string MMX",0

.code 
start:
  mov esi, hold
  mov edi, offset buffer

  mov eax, esi
  shr eax, 4
  and eax, 0f0f0f0fh
  or  eax, 30303030h
  bswap eax
  mov [edi], eax

  mov eax, esi
  and eax, 0f0f0f0fh
  or  eax, 30303030h
  bswap eax
  mov [edi+4], eax

  movq mm1, [edi]
  movq mm0, mm1
  movq mm3, qword ptr nines
  movq mm4, qword ptr sevens
  psllq mm1, 32
  punpckhbw mm1, mm0
  movq mm2, mm1
  pcmpgtb mm2, mm3
  pand mm2, mm4
  paddb mm1, mm2
  movq [edi], mm1

[attachment deleted by admin]

Tedd

Two things:

1. Don't forget to add a null (zero byte) to the end of your string; if you're lucky and do this into an empty buffer there will already be one left over, but you should generally do it in any case.

2. In the code you have, there's "and esi, 0F0000000h" followed by "shr esi, 28" - the 'and' is unnecessary since the shift removes the lower bits anyway (and the upper bits are filled with zeroes.)

(Okay three things..)
3. "movzx edx, byte ptr [lpHexString+esi]" may as well be "mov dl, [lpHexString+esi]" since you're only using dl anyway.


(By the by, that is the method I explained :P)
No snowflake in an avalanche feels responsible.

SideSwipe

And in your procedure don't forget  uses esi,edi

SS
"Crashing through life !"