MSB (the Most Significant Byte)和LSB (the Least Significant Byte)中的"Significant",中文解釋為「有意義的、具有權重的、意味深長的」;而前面再加上個副詞"Most / Least"來修飾後面的Significant,就變成「最有意義、具有權重的位元組」或是「最沒意義、舉無輕重的位元組」。
那麼何謂「最有意義、最沒意義的位元組」。這裡以一組印度阿拉伯數字─12,345為例,中文念成「一萬兩千三百四十五」,把萬位數的'1'刪除,就會變成2,345─兩千三百四十五,相差了10,000,所以'1'就是MSB;而把個位數的'5'刪除,就會變成12,340─一萬兩千三百四十,相差了5,所以'5'就是LSB!
要如何知道自己所應用的CPU (Chipset)是屬於MSB還是LSB?可以寫一個類似下面的程式碼來驗證一下:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { unsigned char ucTemp[4]; int a = 0xDEADBEEF; memset(ucTemp, 0x00, sizeof(unsigned char)); memcpy(ucTemp, &a, sizeof(int)); printf("%02X %02X %02X %02X \n", ucTemp[0], ucTemp[1], \ ucTemp[2], ucTemp[3]); return 0; }如果程序碼的執行結果是「DE AD BE EF」,表MSB;若為「EF BE AD DE」,則是LSB。
咦?不對呀!16進制的0xDEADBEEF,等於10進制的3,735,928,559;「DE」就是MSB,「EF」就是LSB。那為何會有兩種不一樣的結果?因為這又牽扯到Big Endian和Little Endian的問題。
Big Endian就是「記憶體位址中,較"低"的位址,存放MSB」,ucTemp[0]的記憶體位址,必定要比ucTemp[3]來的低;ucTemp[0]存放MSB (DE),ucTemp[3]存放LSB (EF),,這是Big Endian的概念。
Little Endian就是「記憶體位址中,較"高"的位址,存放MSB」,ucTemp[3]的記憶體位址,必定要比ucTemp[0]來的高;ucTemp[3]存放MSB (DE),ucTemp[0]存放LSB (EF),這是Little Endian的觀念。
寫得文謅謅的,好像很難懂?不懂沒關係,觀念通了就行了。由此可見,Big Endian / MSB,比較符合人類的思考習慣和視覺閱讀上的方式。
簡而言之,Big / Little Endian和MSB / LSB的想法就先記到這,爾后的Driver Programming (驅動程式)和Socket Programming (網路程式)都還會再用到。接下來,要記錄的是「位元運算」的一些技巧。為了方便講解,先宣告一個值:char C = 0xA5; 16進制的0xA5,等於10進制的165,等於2進制的「1010 0101」。我們把取出來的值,儲存在char cRet = 0x00; 至於應用的部份,請看以下的範例會比較快一些:
#include <stdio.h> int main(void) { char C = 0xA5, cRet = 0x00, X; cRet = (C >> X) & 0x01; // 取第X位元的值 cRet = C & (0x01 << X); // 取第X位元的值 cRet = C & 0x0F; // 取最後4位元的值 cRet = C & 0xF0; // 取最前4位元的值 C &= ~(0x01 << X); // 把C的第X位元設為0 C &= ~0x0F; // 把C的最後4個位元設為0 C &= ~0xF0; // 把C的最前4個位元設為0 // 把C的中間4個位元 (2, 3, 4, 5 Bit)均設成0 C &= ~0x3C; C |= (1 << X); // 把C的第X位元設為1 C |= 0x0F; // 把C的最後4個位元設為1 C |= 0xF0; // 把C的最前4個位元設為1 // 把C的中間4個位元 (2, 3, 4, 5 Bit)均設成1 C |= 0x3C; // 把C的中間4個位元 (2, 3, 4, 5 Bit)設成1010 C &= ~0x3C; // 先把中間4個位元都設成0 C |= (0x0A << 2); /* 把0x0A (0000 1010),往左移2個位 元,變成0010 1000,再做OR運算 */ // 把C的第X位元做Toggle (0變成1, 1變成0) C ^= (1 << X); return 0; }
沒有留言:
張貼留言