移位的一个小错误
今天突然遇到一个奇怪的问题,代码如下
/* main.c */ #include <stdio.h> int main (void) { int dat = 0xFFFFFFFF; while (dat) { printf ( "%x\n",dat); dat >>= 1; }
return (0);
} #gcc -g -Wall main.c #./a FFFFFFFF FFFFFFFF ........ ......... ^C #
我一直以为 signed 和 unsigned 的区别在于编译器对待他们的态度,底层永远是补码,这样,0xFFFFFFFF,按我的设想,一定是32个循环完事,因为无论什么数,32次移位之后,必定是为0,看到这个结果,我本能去反汇编,汇编文件如下:
0804844c <main>: 804844c: 55 push ebp 804844d: 89 e5 mov ebp,esp 804844f: 83 e4 f0 and esp,0xfffffff0 8048452: 83 ec 20 sub esp,0x20 8048455: c7 44 24 1c ff ff ff mov DWORD PTR [esp+0x1c],0xffffffff 804845c: ff 804845d: eb 1d jmp 804847c <main+0x30> 804845f: 8b 44 24 1c mov eax,DWORD PTR [esp+0x1c] 8048463: 89 44 24 04 mov DWORD PTR [esp+0x4],eax 8048467: c7 04 24 20 85 04 08 mov DWORD PTR [esp],0x8048520 804846e: e8 9d fe ff ff call 8048310 <printf@plt> 8048473: d1 7c 24 1c sar DWORD PTR [esp+0x1c],1 //就是这里了 8048477: e8 a4 fe ff ff call 8048320 <getchar@plt> 804847c: 83 7c 24 1c 00 cmp DWORD PTR [esp+0x1c],0x0 8048481: 75 dc jne 804845f <main+0x13> 8048483: b8 00 00 00 00 mov eax,0x0 8048488: c9 leave 8048489: c3 ret 804848a: 66 90 xchg ax,ax 804848c: 66 90 xchg ax,ax 804848e: 66 90 xchg ax,ax
原来是这个 SAR捣鬼,SAR 算数逻辑(右移),因此 0xFFFFFFFF SAR操作永远是 0xFFFFFFFF。
下篇文章由我来专门讲解移位操作