X86汇编——处理IDIV指令

时间:2022-12-01 03:15:17

I am currently writing a simple C compiler, that takes a .c file as input and generates assembly code (X86, AT&T syntax). Everyting is good, but when I try to execute a IDIVQ instruction, I get a floating-point exception. Here's my input:

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

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

And here is my generated code:

这是我生成的代码:

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

According to http://www.cs.virginia.edu/~evans/cs216/guides/x86.html, idivq %rbx should produce 6/d (the quotient) in %rax. But I'm getting a floating-point exception, and I can't seem to find the problem.

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

Any help will be much appreciated!

如有任何帮助,我们将不胜感激!

2 个解决方案

#1


23  

The first part of Mysticials answer is correct, idiv does a 128/64 bit division, so the value of rdx, which holds the upper 64 bit from the dividend must not contain a random value. But a zero extension is the wrong way to go.

神秘的答案的第一部分是正确的,idiv做了128/64位的除法,所以rdx的值,它持有股息的上64位,不能包含一个随机值。但是0的扩展是错误的。

As you have signed variables, you need to sign extend rax to rdx:rax. There is a specific instruction for this, cqto (convert quad to oct) in AT&T and cqo in Intel syntax. AFAIK newer versions of gas accept both names.

当你有符号变量时,你需要将rax扩展到rdx:rax。这里有一个具体的指令,cqto(转换quad到oct)在AT&T和cqo在Intel语法。AFAIK新版本的气体接受这两个名字。

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

#2


11  

The idivq instruction divides a 128-bit integer (rdx:rax) by the operand.

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

  • rax holds the lower 64-bits of the dividend.
  • rax持有较低的64位股息。
  • rdx holds the upper 64-bits of the dividend.
  • rdx拥有股息的上64位。

When the quotient doesn't fit into 64-bits, it will throw that floating-point exception.

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

So what you need to do is to zero rdx:

所以你需要做的是把rdx:

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

If you are dealing with signed integers, you also need to sign extend rax to rdx:rax, that means copying the rax sign bit to every bit of rdx and is accomplished with cqo alias cqto:

如果要处理有符号的整数,还需要将rax符号扩展到rdx:rax,这意味着将rax符号位复制到每一个rdx,并使用cqo别名cqto完成:

movq    %rdx, %rbx
cqo
idivq   %rbx

#1


23  

The first part of Mysticials answer is correct, idiv does a 128/64 bit division, so the value of rdx, which holds the upper 64 bit from the dividend must not contain a random value. But a zero extension is the wrong way to go.

神秘的答案的第一部分是正确的,idiv做了128/64位的除法,所以rdx的值,它持有股息的上64位,不能包含一个随机值。但是0的扩展是错误的。

As you have signed variables, you need to sign extend rax to rdx:rax. There is a specific instruction for this, cqto (convert quad to oct) in AT&T and cqo in Intel syntax. AFAIK newer versions of gas accept both names.

当你有符号变量时,你需要将rax扩展到rdx:rax。这里有一个具体的指令,cqto(转换quad到oct)在AT&T和cqo在Intel语法。AFAIK新版本的气体接受这两个名字。

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

#2


11  

The idivq instruction divides a 128-bit integer (rdx:rax) by the operand.

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

  • rax holds the lower 64-bits of the dividend.
  • rax持有较低的64位股息。
  • rdx holds the upper 64-bits of the dividend.
  • rdx拥有股息的上64位。

When the quotient doesn't fit into 64-bits, it will throw that floating-point exception.

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

So what you need to do is to zero rdx:

所以你需要做的是把rdx:

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

If you are dealing with signed integers, you also need to sign extend rax to rdx:rax, that means copying the rax sign bit to every bit of rdx and is accomplished with cqo alias cqto:

如果要处理有符号的整数,还需要将rax符号扩展到rdx:rax,这意味着将rax符号位复制到每一个rdx,并使用cqo别名cqto完成:

movq    %rdx, %rbx
cqo
idivq   %rbx