为什么 /=2 与 >>=1 对于有符号整数不同,并编译为不同的 asm?

sun*_*kue 4 c x86 assembly integer-division

unsigned int a=200;
//mov   dword ptr [a],0C8h  
a >>= 1;
//mov   eax,dword ptr [a]  
//shr   eax,1  
//mov   dword ptr [a],eax  
a /= 2;
//mov   eax,dword ptr [a]  
//shr   eax,1  
//mov   dword ptr [a],eax  
int b = -200;
//mov   dword ptr [b],0FFFFFF38h  
b /= 2;
//mov   eax,dword ptr [b]  
//cdq  
//sub   eax,edx  
//sar   eax,1  
//mov   dword ptr [b],eax  
b >>= 1;
//mov   eax,dword ptr [b]  
//sar   eax,1  
//mov   dword ptr [b],eax 
Run Code Online (Sandbox Code Playgroud)

我正在使用 msvc,// 是该 C 语句的程序集。

为什么signed int/=2不同于>>=1? 什么是cdqsub做什么?他们有必要吗?

Ale*_*op. 7

将负整数除以 2 与将其右移 1 不同。例如

-7 / 2 = -3
Run Code Online (Sandbox Code Playgroud)

有轮班:

11111001b >> 1 = 11111100b which is -4
Run Code Online (Sandbox Code Playgroud)

因此编译器必须处理整数为负的情况

cdq 和 sub 在做什么?他们有必要吗?

cdq执行以下 EDX:EAX ? EAX 的符号扩展。

因此,如果 EAX 中的值为负,则 EDX 将获得 0xFFFFFFFF(即 -1),否则将为 0(由于 EAX 的符号扩展)。

sub eax, edx ; will either result in 'eax - 0' (if EAX is positive) or
             ;                       'eax - (-1)' (if EAX is negative)
Run Code Online (Sandbox Code Playgroud)

在上述示例的情况下,将 -7 标准化为-7 - (-1) = -6,然后-6 >> 1 = -3.

  • @sunkue,我添加了对“cdq”的解释。 (2认同)