sunkue
sunkue

Reputation: 288

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 

im using msvc, // is the assembly for that C statement.

Why is signed int /=2 is different from >>=1? What are cdq and sub doing? Are they necessary?

Upvotes: 4

Views: 165

Answers (2)

Alex Lop.
Alex Lop.

Reputation: 6875

Dividing a negative integer by 2 is not the same as shifting it to the right by 1. For example

-7 / 2 = -3

With shifts:

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

Thus the compiler has to take care of the case when the integer is negative

What are cdq and sub doing? Are they necessary?

cdq performs the following EDX:EAX ← sign-extend of EAX.

Thus if the value in EAX is negative, EDX will get 0xFFFFFFFF (which is -1), otherwise it will be 0 (due to the sign extension of EAX).

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

Which in case of the above example will normalize the -7 to -7 - (-1) = -6 and then -6 >> 1 = -3.

Upvotes: 7

0___________
0___________

Reputation: 67476

Arithmetic shift right is actually the divide by 2 but is rounded to the nearest smaller integer. so -7 >> 1 is -4

Mathematical divide (as required by C standard) by two is rounded to the nearest absolute integer instead (ie towards zero).

The code is compiling to another sets of instreuctions:

        mov     edx, DWORD PTR x
        mov     eax, edx
        shr     eax, 31
        add     eax, edx
        sar     eax
        mov     DWORD PTR x, eax

https://godbolt.org/z/No6u6V

Upvotes: 1

Related Questions