【发布时间】:2018-09-10 20:04:48
【问题描述】:
我正在尝试基于 Linux 命令dc 用 C 语言定义一个计算器,程序的结构并不是那么重要,你只需要知道我得到两个数字,我想在输入 @987654322 时将它们相除@。因此,我将这两个数字发送到进行除法的汇编函数(参见下面的代码)。但这仅适用于正数。
当输入 999 3 / 时,它返回 333,这是正确的,但是当输入 -999 3 / 时,我得到一个奇怪的数字 1431655432,并且当输入两个负数(如 -999 -3 /)时,对于任何两个负数,我每次都得到 0。
汇编代码为:
section .text
global _div
_div:
push rbp ; Save caller state
mov rbp, rsp
mov rax, rdi ; Copy function args to registers: leftmost...
mov rbx, rsi ; Next argument...
cqo
idiv rbx ; divide 2 arguments
mov [rbp-8], rax
pop rbp ; Restore caller state
【问题讨论】:
-
你怎么打电话给
_div? -
这就是全部代码吗?我不太明白为什么你有
mov [rbp-8], rax而没有ret -
问题是您将 128 位值 RDX:RAX 除以 64 位值,但传递给函数的是 32 位值。例如 -999 作为 FFFFFC19 的 32 位值,但如果您进行 64 位除法,则 RAX 的高 64 位可能为零(并且您将 RAX 扩展为 RDX,因此 RDX 将为零)给您值 00000000FFFFFC19 。 00000000FFFFFC19 / 3 = 0x55555408 即 1431655432(十进制)
-
您可以使用
cdq代替cqo并使用idiv ebx吗? -
RBX 是 Linux 64 位调用约定中的非易失性寄存器,如 RBP,因此需要由您的函数保留。更好的选择是使用其他易失性(调用者保存的寄存器)之一,如 RCX 而不是 RBX。 RBX、RBP、R12 到 R15 都需要由你修改它们的函数来保存。
标签: c assembly x86-64 nasm division