移位的一个小错误

今天突然遇到一个奇怪的问题,代码如下

/* 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。

下篇文章由我来专门讲解移位操作

 

posted @ 2013-10-17 17:42  moon_cat  Views(260)  Comments(0Edit  收藏  举报