Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1013485
  • 博文数量: 123
  • 博客积分: 5051
  • 博客等级: 大校
  • 技术积分: 1356
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-14 10:56
文章分类
文章存档

2012年(1)

2011年(21)

2010年(13)

2009年(55)

2008年(33)

分类: C/C++

2011-05-22 09:20:48

最近一直看到对一个数进行左右移负数位的代码,刚开始认为如果一个数对应的左右移负数位的话,实际应该是朝着相反的方向移动正数位,即如果左移-a位(a为正数),那么就会右移a位;如果右移-a位的话,那么就会左移a位。但是这样的猜想毫无依据,只是想当然这样,实验了几个例子,发现这样的猜测是错误的。最后通过所进行的实验例子,分析了左右移负数位的结果。
首先有下面的这段代码:
int a = 0x7fffffff;
int b = 8;

printf("%d\n", (a>>-2));
printf("%d\n", (a>>-3));
printf("%d\n", (a>>-4));
printf("%d\n", (a>>-5));
printf("%d\n", (a>>-6));
printf("%d\n", (a>>-7));
printf("%d\n", (b>>128));
return 0;
输出结果为:
1
3
7
15
31
63
8
刚开始看到这个结果很奇怪,经过分析后,发现了其中所隐含的实际操作。
我们来看看经过gcc编译器所得到的汇编代码:
      movl    $2147483647, -8(%ebp)
      movl    -8(%ebp), %eax
      movl    $-2, %ecx
      sarl    %cl, %eax
      ...
      movl    $-3, %ecx
      sarl    %cl, %eax
      ...
会发现,sarl指令只提取ecx寄存器的最后一个字节,即cl字节,结果已经比较清晰了,但是还不是最终结果。cl有8bit,8bit的取值范围为0~255(无符号数),但是在32位系统中,左右移动超过32位是没有意义的操作的。经过所打印的结果来看,sarl实际上只取了cl的低5位作为左右移的标准,也就是说如果右移了32,即100000B,sarl只取后5个0,也就是右移0位,这样所要进行移位的数经过移位后,结果不会发生变化。
好了,上面的分析,仅仅是基于测试用例所分析得到的结果,而实际sarl指令到底如何实现,这是CPU指令集设计人员来决定了。如果我所使用的系统是64位,那么sarl可能会取cl的后6位作为移动的标准,这个猜想有待验证。

由于上面的分析是基于本人机子的结果所分析得到的结果,如果有什么不对的地方,恳请斧正!谢谢!
阅读(4796) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~