2

我在 X86 中测试了这段代码。

void func()
{
  int a, b;
  unsigned int c, d;
  int ret;

  ret = a / b;  // This line use idivl, expected
  ret = c / d;  // this line use idivl, expected
  ret = a / c;  // this line use divl..., surprised 
  ret = c / a;  // this line use divl..., supriised
  ret = a * c;  // this line use imull, expected
}

我在这里粘贴汇编代码:

func:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $36, %esp
    movl    -4(%ebp), %eax
    movl    %eax, %edx
    sarl    $31, %edx
    idivl   -8(%ebp)
    movl    %eax, -20(%ebp)
    movl    -12(%ebp), %eax
    movl    $0, %edx
    divl    -16(%ebp)
    movl    %eax, -20(%ebp)
    movl    -4(%ebp), %eax
    movl    $0, %edx
    divl    -12(%ebp)
    movl    %eax, -20(%ebp)
    movl    -4(%ebp), %eax
    movl    %eax, -36(%ebp)
    movl    -12(%ebp), %eax
    movl    $0, %edx
    divl    -36(%ebp)
    movl    %eax, -20(%ebp)
    movl    -4(%ebp), %eax
    imull   -12(%ebp), %eax
    movl    %eax, -20(%ebp)
    leave
    ret

你能告诉我,为什么 int 和 unsigned int 之间的划分使用 divl 而不是 idivl ?

4

1 回答 1

6

由于 和 的类型a具有c相同的转换等级,但a有符号和c无符号,在除法之前a转换为和。unsigned inta / cc / a

因此,编译器会针对这些情况发出无符号除法指令div(以及c / d,其中两个操作数都是无符号的)。

乘法a * c也是无符号乘法。在这种情况下,编译器可以不使用带符号的乘法指令imull,因为无论是否使用,截断的结果都是相同的mull——imull只有标志不同,生成的代码不会测试这些。

于 2012-11-18T12:32:32.450 回答