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?
由于类型a和c具有相同的转换等级,但是a有符号并且c是无符号的,a在转换unsigned int之前转换为a / c和c / a.
因此,编译器div为这些情况发出无符号除法指令(以及c / d两个操作数都是无符号的).
乘法a * c也是无符号乘法.在这种情况下,编译器可以逃脱使用符号的乘法指令imull,因为无论截断结果是相同的是否mull还是imull使用-只有标志不同,生成的代码没有测试这些.