32位无符号整数到十六进制字符串 - 输出不正确

时间:2018-02-02 05:10:52

标签: assembly x86-64 gas att

我努力将给定的整数转换为十六进制。我没有得到正确的输出,这可能是由于位的错误移位造成的。 我尝试的算法是从第3位开始 代码:

    .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 

收到的输出:

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

正确的输出应包含' 0x'然后是0和正确的十六进制。

1 个答案:

答案 0 :(得分:1)

你的程序的第二部分显然没有做你想做的事情:

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

说明1:

第一次执行and指令时(在第一个循环中)rdi掩码寄存器0xF。在此步骤之后,仅保留寄存器的低4位。您输入的其他位是丢失。因此,即使程序的其余部分完美地工作,输出的前9位数也总是" 0x0000000" (其次是唯一的"正确的"数字)。

指示2:

因为"指令1"这种转变的结果总是为0。

但是,即使程序的其余部分完美运行(包括"指令1和#34;):如果将其移出,您认为最后一位数字如何打印?

指示3:

r11d是一个32位寄存器。因此,以下指令将覆盖4"字符"在" 0x"之后,不仅仅是一个字符。

因为esi的值在整个程序中永远不会改变,所以指令将始终覆盖" 0x"之后的4个字节;从不写入缓冲区的最后4位数。

换句话说:指令在每个循环中写入目标数组中的相同位置。

您希望将数字(' 0' - ' 9'以及' A' - ' F')写入数组。请注意数字' 0' - ' 9'是字节48-57,' A' - ' F'是字节65-70和'' - ' F'是字节97-102。

因此,对于2309737967,如果您希望将数字显示为" 0x89ABCDEF"则程序应写入70到9(esi)。和102如果你希望它显示为" 0x89abcdef"。

显然它并不像你想象的那么容易......