Register-Based 旗標群 讀寫
旗標群佔用暫存器的部份位元,組成設定控制功能或則回報功能狀態的值。同一個暫存器可能由多組不同功能的旗標群共享。因此在控制特定功能時,常需要在不影響其他旗標的前題下,蓋寫暫存器的特定旗標群。在偵測某一功能狀態時,則需要在不受其他旗標群的影響下,擷取特定旗標群的值。為這達成這個目標,有遮罩MASK,以及平移SHIFT來個重要觀念需要先了解。
遮罩Mask
遮罩顧名思義就是用來遮住不想被看到的東西所用的罩子,單位元旗標,與單位元遮罩進行邏輯AND運算時,不論單位元為0或1經過AND 0之後都會得到0,所以值為0的遮罩位元會壓抑單位元旗標的表現。另一方面,單位元不論為0或1,經過AND 1之後都會維持原值,可以篩選浮現原值的表現。
由於C語言每次執行讀寫至少會改變1個位元組,為了要從位元組中篩選出真正要讀寫位元,需要有另外一個遮罩位元組。遮罩位元組中想要浮現原值的位元為設為1,要壓抑原值的位元則設為0。 經由AND邏輯運算,遮罩位元組可篩選出資料位元組中想浮現位元的原值,並將不想要的位元抑制為0。利用遮罩,可以由讀取外部輸入暫存器值,篩選出想要的旗標位元。
接下來我們看以下例子:
黑色為0,透明為1,遮罩0會蓋住原值的原色,遮罩1則允許原值顯現。
遮罩位元組M=b0000 1111,可以用來篩選最右邊的4個位元b3:0,即b3 到b0。若使用M遮罩來讀取某一個值,例如V=b1010 1010,則經由V and M的運算,V中每一個位元,會與M中每一個相應位元and起來,即兩者都是1才會是1。因此M and V :b0000 1111 and b1010 1010 = b0000 1010。其結果是篩選提取了V值的由遮罩選擇出的低4位元,其高位元則被壓抑為0。
利用遮罩M也可以用來提取某個變數,例如V,的部份位元值,蓋寫到某一個暫存器R的相應位元。例如,由M遮罩擷取V的低4BITS,得到b XXXX 1010,蓋寫暫存器R=b1001 1111 它的低四位元,同時維持R的高4BITS不變, 最後得到R’=b1001 1010。 前述b0000 1111,b1010 1010均為二進制所表示的數值。
平移Shift
此處的平移與日常生活中的平移概念相近,例如說,在橫排八個座位,最右邊有走道可以進出這一橫排座位,若有人想坐在由右向左數第三個位置,那就需要往左平移2個位置。因為最左第一個位置直接坐下即可,所以平移0。平常數位置是由1起算,所以第3個位置要減1才是平移次數。
日常坐位編序由1開始,平移次數會比編號少1
但電腦世界由0起算,所以由第1毎位置是b0,平移0,第3個位置b2,平移2,比常見世界在表達上更不易搞錯。
二進制位元編序由0開始,平移次數即等於編號
有些控制或狀態,需要用到超過1個以上的旗標,例如說2個旗標來表達時,它的數值可以表達0,1,2,3。
若是想以某個數值去蓋寫暫存器中未往右靠齊的旗標群,需要以先將新值往左平移到旗標群所在位置,再以遮罩選取處理後蓋寫暫存器。例如 想要把R的b3:2蓋寫為2,這時需要先將2=b0000 0010往左平移2位元,得b0000 1000,再以M2=b0000 1100擷取其旗標群得 bxxxx 10xx 再蓋寫已去除b3:2值之暫存器R=b1001 XX11,得到 R=b1001 1011。
反過來若想擷取暫存器中沒有向右靠的部份位元時,則需要先以遮罩消去其他位元只剩這幾個位元,再將結果向右平移直到所取位元向右對齊。
例如有兩旗標佔用遮罩M2=b0000 1100 中b3:2位元。以M2遮罩讀取V值, V=b1010 1010 ,會得到 M2 and V : b0000 1100 and b1010 1010 =b0000 1000。 這個遮罩擷取的結果,必需再往右平移2位之後所得的值, b0000 0010= 2,才會是b3:2兩位元共同表示的數值。