问题的提出:
unsigned char a=0xA5;
unsigned char b=~a>>4;
注意~优先级高于>>,按照逻辑b应该为0x05
而结果b=0xf5,有点不符合逻辑,反编译(VC6,32位)看了一下,发现编译器把上面的代码编译成
mov ecx, dword ptr[ebp-8] ;ecx = 0xcccccca5
and ecx, 0ffh ;ecx = 0x000000a5
not ecx ;ecx = 0xffffff5a
sar ecx, 4 ;ecx = 0xfffffff5(注意移位后用1补齐!!!)
mov byte ptr [ebp-10h], cl ;cl = 0xfff5
反思一下,为了完成b=~a>>4,编译器做了三个工作
(1)申请了一个32位的临时变量x,将a扩展后,存入x
(2)将x取反
(3)将x右移4位,并将移位后x的低8位送给b
在第一步中,存在一个是否按符号位扩展的问题,这里a为unsigned型,不需要扩展,所以x = 0x000000a5;
若a为(signed) char型,则按符号位扩展后,x =0xffffffa5,取反后x = 0x0000005a,最终b=0x05。
下面在看一下关于符号位扩展的反编译代码
unsigned char a1 = 0xA5;
int a2 = a1;
这里扩展不需要补1,应为a1是unsigned类型的,所以编译器将上面代码译为
mov byte ptr [ebp-4], 0A5h
mov eax, dword ptr [ebp-4]
and eax, 0FFh ;eax = 0x000000a5
mov dword ptr [ebp-18h], eax
对于下面的c代码,需要进行符号位扩展
char a1 = 0xA5;
int a2 = a1;
反编译后,可以看到一条movsx带符号扩展指令
mov byte ptr [ebp-4], 0A5h
movsx eax,byte ptr [ebp-4] ;eax = 0xffffffa5
mov dword ptr [ebp-18h],eax