NASM mov 无法正常工作
NASM mov doesn't work correctly
我想得到两个数字并做除法。
但是一直抛Float Point异常,所以我用gdb调试,发现当我存值到rax时,它的高位是'corrupted'.
当[num]为20d时,rax存储0x2800000014
当[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
您正在扫描两个 int
,它们存储为两个 32 位整数(相隔 4 个字节),从地址 num
.
开始
因此,当您尝试从该位置读取 64 位时,您会得到两个 32 位值。 0x14 == 20,0x28 是您输入的另一个值。
您应该能够将 mov rax, [num]
替换为 mov eax, [num]
(对于 rdx
也是如此)。这将自动清除这些寄存器的最高 32 位。
注意IDIV r/m64
除以RDX:EAX
(由rdx
和rax
组成的128位八字)除以除数。
所以使用 rdx
作为除数不是一个好主意,因为这意味着您将 0xkkkkkkkkkkkkkkkkmmmmmmmmmmmmmmmm
除以 0xkkkkkkkkkkkkkkkk
,得到商 0x0000000000000001nnnnnnnnnnnnnnnn
。由于商的有效范围是 −2^63
到 2^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
用eax
/rax
的符号位填充edx
/rdx
)
我想得到两个数字并做除法。 但是一直抛Float Point异常,所以我用gdb调试,发现当我存值到rax时,它的高位是'corrupted'.
当[num]为20d时,rax存储0x2800000014
当[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
您正在扫描两个 int
,它们存储为两个 32 位整数(相隔 4 个字节),从地址 num
.
因此,当您尝试从该位置读取 64 位时,您会得到两个 32 位值。 0x14 == 20,0x28 是您输入的另一个值。
您应该能够将 mov rax, [num]
替换为 mov eax, [num]
(对于 rdx
也是如此)。这将自动清除这些寄存器的最高 32 位。
注意IDIV r/m64
除以RDX:EAX
(由rdx
和rax
组成的128位八字)除以除数。
所以使用 rdx
作为除数不是一个好主意,因为这意味着您将 0xkkkkkkkkkkkkkkkkmmmmmmmmmmmmmmmm
除以 0xkkkkkkkkkkkkkkkk
,得到商 0x0000000000000001nnnnnnnnnnnnnnnn
。由于商的有效范围是 −2^63
到 2^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
用eax
/rax
的符号位填充edx
/rdx
)