講道理,在沒接觸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
優先級:~ > 移位(<<,>>) > 按位操作(&>|)