为什么在执行int/unsigned int除法时使用'divl'

Yan*_* Bo 2 c c++ x86 unsigned-integer

我在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
}
Run Code Online (Sandbox Code Playgroud)

我在这里粘贴汇编代码:

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
Run Code Online (Sandbox Code Playgroud)

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

caf*_*caf 6

由于类型ac具有相同的转换等级,但是a有符号并且c是无符号的,a在转换unsigned int之前转换为a / cc / a.

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

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