NASM mov无法正常工作

时间:2016-08-23 13:59:06

标签: nasm mov

我想获得两个数字并进行划分。 但它不断抛出浮点异常,所以我使用gdb进行调试,我发现当我将值存储到rax时,它的高位被损坏了。

当[num]为20d时,0x2800000014存储在rax。

当[num]为40d时,存储0x1400000028。

当我存储它们时,我猜它的一些高位被破坏(?)。问题是什么?

section .data
    in:     db "%d %d", 0
    len:    equ $-in

section .bss
    num:    resd 2

section .text

main:
    mov     rdi, in
    mov     rsi, num
    mov     rdx, num + 4
    xor     rax, rax
    call    scanf

    mov     rax, [num] ; ------------- here
    mov     rdx, [num + 4]
    idiv    rdx

    ...

    xor     rax, rax
    ret

1 个答案:

答案 0 :(得分:1)

您正在扫描两个int,它们存储为两个32位整数(相隔4个字节),从地址num开始。

因此,当您尝试从该位置读取64位时,您将获得两个32位值。 0x14 == 20,而0x28是您输入的另一个值。

您应该可以将mov rax, [num]替换为mov eax, [num](同样适用于rdx)。这将自动清除这些寄存器中最重要的32位。

请注意IDIV r/m64除以RDX:EAX(由rdxrax组成的128位八角形)除数。
因此,使用rdx作为除数不是一个好主意,因为这意味着您将0xkkkkkkkkkkkkkkkkmmmmmmmmmmmmmmmm除以0xkkkkkkkkkkkkkkkk,为您提供0x0000000000000001nnnnnnnnnnnnnnnn的商。由于商的有效范围为−2^632^63 − 1,因为超出范围的商,您将获得分红错误。

tl; dr:您应该可以通过将call scanf之后的3行代码更改为:

来解决此问题
mov     eax, [num]
cqo                     ; sign-extend rax into rdx
mov     ebx, [num + 4]  ; <-- note, ebx instead of edx
idiv    rbx             ; <-- note, rbx instead of rdx

或者,既然你的被除数和除数都是32位,你可以使用IDIV r/m32 likely be faster

mov     eax, [num]
cdq                     ; sign-extend eax into edx
mov     ebx, [num + 4]  
idiv    ebx             

cdq / cqo使用edx / rdx的符号位填充eax / rax