讲道理,在没接触arm裸机前一直觉得位运算挺鸡肋的,就算是当年的汇编课设也没怎么用位操作。但是在统一编址的arm平台,操作外设主要靠操作寄存器,这时候位操作真的是必不可少,当然位操作和位运算是分不开的。
(1).位运算: 位与&,位或 | ,位取反~,位异或^(奇数个1异或结果为1,其他为0).
算数运算(逻辑运算):算数与&&,算数或 | | ,算数取反!。(逻辑里无符号要么0,要么都是1)
位移操作:左移<<,右移>>。
(2).常说的置位指的是置1,清除指的是置0。
特定位置1:位或一个特定位为1,其他位为0的数即可。-------------------------------------------->a |=(b<<c)
特定位置0:位与一个特定位为0,其他为为1的数即可。(常用取反获得) ---------------------->a &=~(b<<c)
取出特定位:位与一个特定位为1,其他位为0 的数即可。------------------------------------------> d = a & (b<<c)
有没有发现上面的数互为取反,对的!要构造这样的多用取反和移位操作。
具体实例:
a 为一寄存器值。
//现在我要让他bit 4 ~bit 7置为0;bit 8~bit 11写入965;再取出bit 8 ~ bit 11.
a & =~(0xf<<4) (从多少bit开始就移多少位)
a | =~(0xf<<8) ; a | =(965<<8)
int b= (a & ( 0xf<<8) >>8)
(3).如何构造任意位的1;例如bit n到 bit m位为1。
a = ~(~(0U)<<(m-n+1)); //U代表无符号数,~(0U)表示0xFFFF
或者
a = ~(0U)>>(32-(m-n+1));
(4).与宏定义结合的位操作解析。注意宏定义的外面一定要加上括号。
// 将x的第n位置位 //这里的第n位实际上是bit (n-1) ,下同
#define SET_NTH_BIT(x, n) (x | ((1U)<<(n-1)))
//将x的第n位清除
#define CLEAR_NTH_BIT(x, n) (x & ~((1U)<<(n-1)))
//截取x的第n到第m位
#define GETBITS(x, n, m) ((x & ~(~(0U)<<(m-n+1))<<(n-1)) >> (n-1))
分析第三个:~(~(0U)<<(m-n+1)) //获得m-n+1位的1 ,~优先级大于<<
x & ~(~(0U)<<(m-n+1)) <<(n-1) // 获得n到m位 ,<<优先级大于&
(x & ~(~(0U)<<(m-n+1))<<(n-1)) >> (n-1) //将获得到的数右移n-1位,即得到截取部分。
注意:~(0U)表示0xFFFF
优先级:~ > 移位(<<,>>) > 按位操作(&>|)