-1

I'm struggling to convert a given integer into hex. I'm not getting correct output and it's likely due to incorrect shifting of bits. The algorithm I tried was to start at the 3rd position The code:

    .globl hex_str
hex_str:
    movl $48, 0(%rsi)   
    movl $120, 1(%rsi)  
    movl $0, 10(%rsi)
    mov  $0xf, %r10d   
    mov  $1, %r8d          
    mov  $2, %r9d
    mov $0, %ecx        

loop:
    inc %r8d         
    and  %r10d, %edi
    movl %edi, %r11d    
    shr  $4, %r11d              
    movl %r11d, 2(%rsi)   
    inc %r9
    cmp  $9, %r8d       
    jg   endl           
    jmp  loop           

endl:
    ret 

Output received:

1 = 0x
34 = 0x
819 = 0x
17476 = 0x
349525 = 0x
6710886 = 0x
125269879 = 0x
19088743 = 0x
2309737967 = 0x
3735928559 = 0x
3235822174 = 0x

The correct output should contain '0x' followed by 0's and the correct hex.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • 3
    Why have you tagged it Python and Ruby? – TessellatingHeckler Feb 02 '18 at 05:13
  • It's an assembler – TigerTV.ru Feb 02 '18 at 05:15
  • I don't grok any of the tags. – user4581301 Feb 02 '18 at 05:25
  • 1
    Downvoted, as you reason about correctness of assembly code by checking the output only. Receiving correct output of assembly code is like 10% of needed validation, you can often reach correct output by accident in assembly, and to have still many subtle bugs in the code. You have to use debugger and single stepping over instructions and reasoning about purpose/effect of every one. For example just the first `movl $48, 0(%rsi)` is already incorrect, you did want to set first char to `'0'`, but you set instead first four characters to `"0\0\0\0"` (zero digit plus three zeroed bytes). Etc... – Ped7g Feb 02 '18 at 07:52

1 Answers1

1

The second part of your program obviously does not do what you want to do:

and  %r10d, %edi     # Instruction 1
movl %edi, %r11d
shr  $4, %r11d       # Instruction 2
movl %r11d, 2(%rsi)  # Instruction 3

Instruction 1:

When the and instruction is executed the first time (in the first loop) the register rdi is maskted by 0xF. After this step only the low 4 bits of the register remain. The other bits of your input are lost. So even if the rest of the program would work perfectly the first 9 digits of your output would always be "0x0000000" (followed by the only "correct" digit).

Instruction 2:

Because of "instruction 1" the result of this shift will always be 0.

But even if the rest of the program would work perfectly (including "instruction 1"): How do you think that the last digit can be printed if you shift it out?

Instruction 3:

r11d is a 32-bit register. Therefore the following instruction will overwrite the 4 "characters" after the "0x", not only one character.

Because the value of esi does never change in the whole program the instruction will always overwrite the 4 bytes after the "0x"; the last 4 digits of the buffer are never written.

In other words: The instructions writes to the same position in the destination array in every loop.

You expect digits ('0'-'9' and 'A'-'F') to be written to the array. Note that the digits '0'-'9' are the bytes 48-57, 'A'-'F' are bytes 65-70 and 'a'-'F' are the bytes 97-102.

So in the case of 2309737967 your program should write 70 to 9(esi) if you want the number to be displayed as "0x89ABCDEF" and 102 if you want it to be displayed as "0x89abcdef".

Obviously it is not as easy as you thought...

Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38