X86程序集 – 处理IDIV指令

我目前正在编写一个简单的C编译器,它将.c文件作为输入并生成汇编代码(X86,AT&T语法)。 一切都很好,但是当我尝试执行IDIVQ指令时,我得到一个浮点exception。 这是我的意见:

int mymain(int x){ int d; int e; d = 3; e = 6 / d; return e; } 

这是我生成的代码:

 mymain: .LFB1: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 movq %rdi, -40(%rbp) movq $3, -8(%rbp) movq $6, %rax movq -8(%rbp), %rdx movq %rdx, %rbx idivq %rbx movq %rax, -16(%rbp) movq -16(%rbp), %rax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1: .size mymain, .-mymain 

根据http://www.cs.virginia.edu/~evans/cs216/guides/x86.html,idivq%rbx应该在%rax中产生6 / d(商)。 但我得到一个浮点exception,我似乎无法找到问题。

任何帮助都感激不尽!

Mysticials的第一部分回答是正确的, idiv执行128/64位除法,因此rdx的值不包含随机值, rdx保持被除数的高64位。 但零延伸是错误的方法。

由于您已签名变量,因此需要将extend rax 签名rdx:rax 。 有一个特定的指令,在AT&T中cqto转换为quad到oct )和在Intel语法中的cqo 。 AFAIK更新版本的气体接受这两个名称。

 movq %rdx, %rbx cqto # sign extend rax to rdx:rax idivq %rbx 

idivq指令用操作数除以128位整数( rdx:rax )。

  • rax持有红利的低64位。
  • rdx保持被除数的高64位。

当商不适合64位时,它将抛出该浮点exception。

所以你需要做的是零rdx

 movq %rdx, %rbx xorq %rdx, %rdx # zero "rdx" idivq %rbx 

如果您正在处理有符号整数,则还需要将extend rax签名为rdx:rax ,这意味着将rax符号位复制到rdx:rax每一位,并使用cqo别名cqto完成:

 movq %rdx, %rbx cqo idivq %rbx