昨天有一篇關於右移位研究的文章, 網友提出了正確的觀點,真的很感謝他---Tcice.為了落實認真負責的精神,今天晚上特別再對此做個研究.下面是我的研究對象:
void FooA()
...{
unsigned char i = 160;
long c = i >> 1;
printf("%d",c);
}
void FooB()
...{
char i = 160;
long c = i >> 1;
printf("%d",c);
}
int main ()
...{
FooA();
FooB();
return 0;
}
可以看到,那兩個子函數只有一個地方不同,就是關於局部變數i,FooA是無符號char,FooB則是有符號char.現在編譯串連,
gcc -g main.c -o main.exe
加上了參數-g,是為了用gdb調試.
進入gdb,載入main.exe後,我對FooA和FooB分別進行了反組譯碼,下面是結果:
(gdb) disassemble FooA
Dump of assembler code for function FooA:
0x4012d3 <FooA>: push %ebp
0x4012d4 <FooA+1>: mov %esp,%ebp
0x4012d6 <FooA+3>: sub $0x8,%esp
0x4012d9 <FooA+6>: movb $0xa0,0xffffffff(%ebp)
0x4012dd <FooA+10>: mov 0xffffffff(%ebp),%al
0x4012e0 <FooA+13>: shr %al
0x4012e2 <FooA+15>: and $0xff,%eax
0x4012e7 <FooA+20>: mov %eax,0xfffffff8(%ebp)
0x4012ea <FooA+23>: sub $0x8,%esp
0x4012ed <FooA+26>: pushl 0xfffffff8(%ebp)
0x4012f0 <FooA+29>: push $0x4012d0
0x4012f5 <FooA+34>: call 0x401840 <printf>
0x4012fa <FooA+39>: add $0x10,%esp
0x4012fd <FooA+42>: leave
0x4012fe <FooA+43>: ret
End of assembler dump.
(gdb) disassemble FooB
Dump of assembler code for function FooB:
0x4012ff <FooB>: push %ebp
0x401300 <FooB+1>: mov %esp,%ebp
0x401302 <FooB+3>: sub $0x8,%esp
0x401305 <FooB+6>: movb $0xa0,0xffffffff(%ebp)
0x401309 <FooB+10>: mov 0xffffffff(%ebp),%al
0x40130c <FooB+13>: sar %al
0x40130e <FooB+15>: movsbl %al,%eax
0x401311 <FooB+18>: mov %eax,0xfffffff8(%ebp)
0x401314 <FooB+21>: sub $0x8,%esp
0x401317 <FooB+24>: pushl 0xfffffff8(%ebp)
0x40131a <FooB+27>: push $0x4012d0
0x40131f <FooB+32>: call 0x401840 <printf>
0x401324 <FooB+37>: add $0x10,%esp
0x401327 <FooB+40>: leave
0x401328 <FooB+41>: ret
End of assembler dump.
在反組譯碼裡,FooA中有這麼一行
0x4012e0 <FooA+13>: shr %al
shr也就是對al進行邏輯右移
在相同的地方,FooB卻是這樣的;:
0x40130c <FooB+13>: sar %al
sar就是對al進行算術右移.....
原來如此.....
我知道了.....