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