最近一直看到对一个数进行左右移负数位的代码,刚开始认为如果一个数对应的左右移负数位的话,实际应该是朝着相反的方向移动正数位,即如果左移-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位作为移动的标准,这个猜想有待验证。
由于上面的分析是基于本人机子的结果所分析得到的结果,如果有什么不对的地方,恳请斧正!谢谢!
阅读(4865) | 评论(0) | 转发(0) |