ely*_*bhy 23 c compiler-construction x86 assembly
我目前正在编写一个简单的C编译器,它将.c文件作为输入并生成汇编代码(X86,AT&T语法).一切都很好,但是当我尝试执行IDIVQ指令时,我得到一个浮点异常.这是我的意见:
int mymain(int x){
int d;
int e;
d = 3;
e = 6 / d;
return e;
}
Run Code Online (Sandbox Code Playgroud)
这是我生成的代码:
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
Run Code Online (Sandbox Code Playgroud)
据http://www.cs.virginia.edu/~evans/cs216/guides/x86.html,idivq%RBX应该产生在6/d(商)%RAX.但我得到一个浮点异常,我似乎无法找到问题.
任何帮助都感激不尽!
Gun*_*iez 24
Mysticials的第一部分答案是正确的,idiv
进行128/64位除法,因此rdx
保持被除数的高64位的值不得包含随机值.但零扩展是错误的方法.
正如你所签署的变量,你需要签署延长rax
至rdx:rax
.在AT&T和Intel语法中有一个特定的指令cqto
(将quad转换为oct)cqo
.AFAIK更新版本的气体接受这两个名称.
movq %rdx, %rbx
cqto # sign extend rax to rdx:rax
idivq %rbx
Run Code Online (Sandbox Code Playgroud)
Mys*_*ial 11
该idivq
指令rdx:rax
用操作数除以128位整数().
rax
保持红利的低64位.rdx
保持红利的高64位.当商不符合64位时,它将抛出该浮点异常.
所以你需要做的是零rdx
:
movq %rdx, %rbx
xorq %rdx, %rdx # zero "rdx"
idivq %rbx
Run Code Online (Sandbox Code Playgroud)
如果你正在处理的有符号整数,您还需要签署延长rax
到rdx:rax
,这意味着复制rax
符号位的每一位rdx
,并与CQO别名cqto完成:
movq %rdx, %rbx
cqo
idivq %rbx
Run Code Online (Sandbox Code Playgroud)