为什么 /=2 与有符号整数的 >>=1 不同,并编译为不同的 asm?
Why is /=2 different from >>=1 for signed integers, and compiles to different asm?
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
我使用的是 msvc,// 是该 C 语句的程序集。
为什么 signed int /=2
与 >>=1
不同? cdq
和 sub
在做什么?有必要吗?
负整数除以 2 与右移 1 不同。
例如
-7 / 2 = -3
轮班:
11111001b >> 1 = 11111100b which is -4
因此编译器必须处理整数为负数的情况
What are cdq and sub doing? Are they necessary?
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)
在上面的示例中,将 -7 规范化为 -7 - (-1) = -6
,然后是 -6 >> 1 = -3
。
算术右移实际上是除以 2,但四舍五入为最接近的较小整数。所以 -7 >> 1
是 -4
除以二的数学除法(根据 C 标准的要求)四舍五入为最接近的绝对整数(即接近零)。
代码正在编译为另一组指令:
mov edx, DWORD PTR x
mov eax, edx
shr eax, 31
add eax, edx
sar eax
mov DWORD PTR x, eax
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
我使用的是 msvc,// 是该 C 语句的程序集。
为什么 signed int /=2
与 >>=1
不同? cdq
和 sub
在做什么?有必要吗?
负整数除以 2 与右移 1 不同。 例如
-7 / 2 = -3
轮班:
11111001b >> 1 = 11111100b which is -4
因此编译器必须处理整数为负数的情况
What are cdq and sub doing? Are they necessary?
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)
在上面的示例中,将 -7 规范化为 -7 - (-1) = -6
,然后是 -6 >> 1 = -3
。
算术右移实际上是除以 2,但四舍五入为最接近的较小整数。所以 -7 >> 1
是 -4
除以二的数学除法(根据 C 标准的要求)四舍五入为最接近的绝对整数(即接近零)。
代码正在编译为另一组指令:
mov edx, DWORD PTR x
mov eax, edx
shr eax, 31
add eax, edx
sar eax
mov DWORD PTR x, eax