1

For example, I have: n1 db "1234" which represents a hexadecimal value. I would like to convert it to binary and store it inside 32-bit register, in this case the result would be: EAX = 0000 0000 0000 0000 0001 0010 0011 0100

What is the approach?

roditu
  • 59
  • 6
  • Curiously we do not have a canonical duplicate for hexadecimal number parsing yet. – fuz Nov 13 '22 at 11:56
  • 2
    Shift your result by 4 to the left and add the new digit which was converted from ascii depending on whether it was a letter or a digit. PS: `1234` is a misleading example/test case for hex. – Jester Nov 13 '22 at 11:59
  • `total = total * base + digit` (but note that `digit` isn't just `char - '0'` since letters and numbers aren't contiguous in ASCII.) For the other direction, binary integer to hex string, see [How to convert a binary integer number to a hex string?](https://stackoverflow.com/q/53823756) for NASM, including scalar and SSE2/AVX2/AVX-512VBMI. For doing this efficiently, see [Is there an algorithm to convert massive hex string to bytes stream QUICKLY? asm/C/C++](https://stackoverflow.com/a/67169220) for an AVX2 version, and https://github.com/zbjornson/fast-hex – Peter Cordes Nov 13 '22 at 13:23

1 Answers1

1

Inputting multi-radix multi-digit signed numbers with DOS shows how to do this particular conversion in the answer's code snippets 2a and 2b. You can also learn how to convert from octal and binary.
Don't be misguided by the mention "DOS". Many principles remain the same, and if you're currently clueless it will be a good starting point. You can change the code in accordance with your needs and skill level. And if that doesn't work out, then you can post a question including the code that you've tried.

Here's an adaptation of the mentioned snippets:

snippet 2a

    ; Hexadecimal
.a: inc   esi             ; Next character
    shl   eax, 4          ; Result = Result * 16
    movzx edx, byte [esi] ; -> DL = {["0","9"],["A","F"]} (NewDigit)
    cmp   dl, "9"
    jbe   .b
    sub   edx, 7
.b: sub   edx, 48
    or    eax, edx        ; Result = Result + NewDigit
    dec   ecx
    jnz   .a

snippet 2b with character validation and overflow detection

    ; Hexadecimal
.a: inc   esi             ; Next character
    movzx edx, byte [esi] ; -> DL = {["0","9"],["A","F"]} (NewDigit) ?
    cmp   dl, "9"
    jbe   .b
    sub   edx, 7
.b: sub   edx, 48
    cmp   dl, 15
    ja    .z              ; Stop if not a digit
    rol   eax, 4          ; Result = Result * 16
    test  al, 15
    jnz   .o              ; Overflow
    or    eax, edx        ; Result = Result + NewDigit
    dec   ecx
    jnz   .a
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • If you weren't going to port your code to 32-bit, why bother repost it instead of just linking a 16-bit answer in a comment? Stuff like 4x `rol ax,1` has no place in 32-bit code, only in code that might need to run on 8086. Also, what's up with branching in your binary version? cmp / `adc ax,ax` will shift in the new digit (and set CF if there's carry-out) – Peter Cordes Nov 13 '22 at 21:35
  • @PeterCordes I copied the snippets verbatim just for convenience. I didn't even notice that I had written them explicitly for 8086 two years ago. – Sep Roland Nov 13 '22 at 22:16