昨天有一篇关于右移位研究的文章, 网友提出了正确的观点,真的很感谢他---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进行算术右移.....
原来如此.....
我知道了.....


















可以看到,那两个子函数只有一个地方不同,就是关于局部变量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进行算术右移.....
原来如此.....
我知道了.....