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;
}
沒有留言:
張貼留言