【问题标题】:64bit nasm division idiv64 位 nasm 划分 idiv
【发布时间】:2012-02-10 02:25:38
【问题描述】:
;print out division message
mov rcx, 0                       ;zero out register
mov rax, [input]
mov rcx, [input2]
idiv rcx                        ;divide rax by rcx
mov rdi, rax                    ;for printing purposes
call print_int

我似乎无法弄清楚为什么这不是除法,我得到一个错误“浮点异常”我使用的是 64 位机器并且值是整数而不是浮点......想法?

我知道除法发生后,商应该在 rax 中,余数应该在 rdx 中,我相信,但现在我只是想了解商。

【问题讨论】:

标签: assembly x86-64 nasm


【解决方案1】:

你的函数在我看来有点复杂。 idiv 在这里使用此功能按预期工作:

_mydiv:
  xor  %rdx, %rdx ; clear high bits of dividend
  mov  %rdi, %rax ; copy dividend argument into rax
  idiv %rsi       ; divide by divisor argument
  ret             ; return (quotient is in rax)

翻译成 NASM 语法和 windows ABI,我认为应该是这样的:

_mydiv:
  mov  r8, rdx    ; copy divisor argument to scratch register
  xor  rdx, rdx   ; clear high bits of dividend
  mov  rax, rcx   ; copy dividend argument into rax
  idiv r8         ; divide by divisor in scratch register
  ret             ; return (quotient is in rax)

您是否可能会踩踏您的参数并在此过程中混淆某些东西?

编辑:查看您的代码,我突然想到它可能根本没有写成正确的函数。重要的步骤是:

  1. 将股息放入 RDX:RAX - 对您而言,这可能意味着清除 RDX 并将输入股息放入 RAX。
  2. 将除数放入其他寄存器 - 您选择了 RCX,应该没问题。
  3. 除法-idiv rcx
  4. 结果将在 RAX 中。

您应该特别注意第 1 步 - 确保 RDX:RAX 的内容正常!为什么你会得到一个浮点异常,我无法从你显示的代码中猜到。

【讨论】:

  • 就是这样,指导步骤帮助很大,我之前没有清除 rdx 寄存器,非常感谢!!!
  • 为什么在 nasm 中使用 r8?有必要吗?
  • @Nande,不适用于 NASM,但对 windows abi 来说是正确的,其中 rdx 是参数传递寄存器。
【解决方案2】:

您实际上是在将 RDX:RAX 中的 128 位数字除以 RCX。因此,如果 RDX 未初始化,则结果可能会大于 64 位,从而导致溢出异常。尝试在除法之前添加 CQO 以将 RAX 符号扩展到 RDX。

不过,我无法解释浮点位,也许有人决定在某个地方重用中断向量来解决通用数学错误?

【讨论】:

  • 为了将来参考,在哪里可以找到像cqo 这样的指令?在 GAS 语法中,它是 cqto,在 MASM 语法中它应该转换成什么似乎并不清楚。
  • @Vortico: The Intel Architecture Manuals 总是一个好的开始。至于 CQO,我承认我不知道 128 位字的正确后缀,但必须查找 CBW/CWD/CDQ 以查看 64 位等价物可能被称为什么
猜你喜欢
  • 2012-02-22
  • 1970-01-01
  • 2023-01-11
  • 2011-11-19
  • 1970-01-01
  • 1970-01-01
  • 2016-09-10
  • 1970-01-01
相关资源
最近更新 更多