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

问题描述 投票:2回答:2
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 

im使用msvc,//是该C语句的程序集。

为什么对有符号的int /=2>>=1不同? cdqsub在做什么?他们有必要吗?

c assembly x86 integer-division
2个回答
5
投票

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

-7 / 2 = -3

有班次:

11111001b >> 1 = 11111100b which is -4

因此,当整数为负数时,编译器必须处理这种情况

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)

在上述示例中,将-4归一化为-4 - (-1) = -3


0
投票

算术右移实际上是除以2,但四舍五入为最接近的较小整数。因此-7 >> 1-4

数学除以2会四舍五入为最接近的绝对整数。

该代码正在编译为另一组说明:

        mov     edx, DWORD PTR x
        mov     eax, edx
        shr     eax, 31
        add     eax, edx
        sar     eax
        mov     DWORD PTR x, eax
© www.soinside.com 2019 - 2024. All rights reserved.