【C/C++】关于移位操作的一些自学小结

2021/11/19 14:09:56

本文主要是介绍【C/C++】关于移位操作的一些自学小结,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1、常见的左移右移,以无符号整型为例

可以看到,打印16进制的x值,只有15个f,说明右移4位没问题,高位正常补0。左移同理。
右移4位
其中show方法参考《深入理解计算机系统(第三版)》写的函数,打印目标地址的字节。(我是小端,所以最低有效字节0xff在最前面打印,最高位的0x0f在最后打印。)
同理,如果将x右移63位,会得到只剩一个1,验证也没毛病。
右移63位
然后可以去看看右移63位的汇编的代码:
左边汇编代码 右边源码
红框圈起来的关键部分:

move %rdi, %rax     将%rdi寄存器的值放到%rax中,%rdi一开始会保存第一个参数,%rax会保存返回值
shrq $63, %rax      将%rax中的值逻辑右移一个立即数63

2、超过数据位数的右移


将右移位数改为64后,会出现“循环位移”的现象(应该是这个名词吧?),下面讲述一下过程。

左上为编译警告,坐下为源码,右边为汇编代码
可以看出,当右移64位时,会警告右移数>=类型宽度,但是依然可以编译,得到右边的汇编代码。

movq %rdi, %rax     同上,第一个参数放到返回值
movl $64, %ecx      将立即数放到%ecx中
shrq %cl, %rax      将%rax中的值右移%cl中的值的位数

这边比较难理解的是第二三句,其中有两个点注意到了就不难了。
1、(参照《深入理解计算机系统(第三版)》131页移位操作)位移量可以是一个立即数,或者放在单字节寄存器%cl中(只允许这个特定的寄存器作为操作数)x86-64中,移位操作对w位长的数据值进行操作,位移量由%cl寄存器的低m位决定,这里2^m=w,高位被忽略。
2、%rcx是一个64位寄存器,而他的低32位计为%ecx,低16位计为%cx,低8位计为%cl。所以此处其实就是将64拷贝到%rcx的低32位上,并将高位清0。
综上两个点,这里uint64_t是64位无符号整型,2^6=64,m=6,因此由%cl中的值(64=1000000二进制),只能使用其中的6位000000位移,右移0位也就是原数字,可以跑一下代码看看效果。
右移64位
可以看到跟我们的推论结果一致。
个人笔记,如有错误的地方,烦请指正。



这篇关于【C/C++】关于移位操作的一些自学小结的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程