深入理解計算機系統-之-數值存儲(一)-CPU大端和小端模式詳解http://blog.csdn.net/gatieme/article/details/50642756
大端與小端
在嵌入式開發中,大端(Big-endian)和小端(Little-endian)是一個很重要的概念。
MSB與LSB
最高有效位(MSB)指二進制中最高值的比特。在16比特的數字音頻中,其第1個比特便對16bit的字的數值有最大的影響。例如,在十進制的15,389這一數字中,相當於萬數那1行(1)的數字便對數值的影響最大。比較與之相反的“最低有效位”(LSB)。
LSB(Least Significant Bit),意爲最低有效位;MSB(Most Significant Bit),意爲最高有效位
若MSB=1,則表示數據爲負值,若MSB=0,則表示數據爲正。
MSB高位前導,LSB低位前導。
談到字節序的問題,必然牽涉到兩大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列採用big endian方式存儲數據,而x86系列則採用little endian方式存儲數據。那麼究竟什麼是big endian,什麼又是little endian呢?
其實big endian是指低地址存放最高有效字節(MSB)
而little endian則是低地址存放最低有效字節(LSB)。
MSDN中關於LE和BE的解釋
Byte Ordering Byte ordering Meaning
big-endian The most significant byte is on the left end of a word.
little-endian The most significant byte is on the right end of a word.
這裏這個最重要的字節可以解釋成值的最高位,如果換成是錢的話就是最值錢的那一位
Big endian machine: It thinks the first byte it reads is the biggest.
Little endian machine: It thinks the first byte it reads is the littlest.
比如我有1234元人民幣,最值錢的是1000元,最不值錢的是4元,那麼這個1就是最重要的字節
下面我們詳細講下大小端模式的問題
端模式(Endian)
端模式(Endian)的這個詞出自Jonathan Swift書寫的《格列佛遊記》。這本書根據將雞蛋敲開的方法不同將所有的人分爲兩類,從圓頭開始將雞蛋敲開的人被歸爲Big Endian,從尖頭開始將雞蛋敲開的人被歸爲Littile Endian。小人國的內戰就源於吃雞蛋時是究竟從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開。在計算機業Big Endian和Little Endian也幾乎引起一場戰爭。在計算機業界,Endian表示數據在存儲器中的存放順序。
大端
大端(Big-endian)模式,是指數據的高字節保存在內存的低地址中,而數據的低字節保存在內存的高地址中
這樣的存儲模式有點兒類似於把數據當作字符串順序處理:地址由小向大增加,而數據從高位往低位放;這種存放方式符合人類的正常思維
小端
小端(Little-endian)模式,是指數據的高字節保存在內存的高地址中,而數據的低字節保存在內存的低地址中
這種存儲模式將地址的高低和數據位權有效地結合起來,高地址部分權值高,低地址部分權值低,和我們的邏輯方法一致。
總結
採用大小模式對數據進行存放的主要區別在於在存放的字節順序,大端方式將高位存放在低地址,小端方式將高位存放在高地址。採用大端方式進行數據存放符合人類的正常思維,而採用小端方式進行數據存放利於計算機處理。到目前爲止,採用大端或者小端進行數據存放,其孰優孰劣也沒有定論。
有的處理器系統採用了小端方式進行數據存放,如intel芯片是小端(修改分區表時要注意)。
有的處理器系統採用了大端方式進行數據存放,如IBM半導體和Freescale的PowerPC處理器以及一些常見的單片機芯片。不僅對於處理器,一些外設的設計中也存在着使用大端或者小端進行數據存放的選擇。
特別的intel x86的CPU使用的是LE(Windows中稱爲“主機字節序”),而SocksAddr中使用的則是BE(就是“網絡字節序”),所以在使用網絡編程時需要使用htns,htnl,nths,nthl來倒字節序。
因此在一個處理器系統中,有可能存在大端和小端模式同時存在的現象。這一現象爲系統的軟硬件設計帶來了不小的麻煩,這要求系統設計工程師,必須深入理解大端和小端模式的差別。大端與小端模式的差別體現在一個處理器的寄存器,指令集,系統總線等各個層次中。
示例分析
假如現有一32位int型數0x12345678,
那麼
其MSB(Most Significant Byte,最高有效字節)爲0x12,
其LSB (Least Significant Byte,最低有效字節)爲0x78
地址偏移 | 大端模式 | 小端模式 |
---|---|---|
0x00 | 12(OP0) | 78(OP3) |
0x01 | 34(OP1) | 56(OP2) |
0x02 | 56(OP2) | 34(OP1) |
0x03 | 78(OP3) | 12(OP0) |
也可以看下面這個圖
我們可以看到看到
大端(Big-endian)模式下數據的高字節保存在內存的低地址中,而數據的低字節保存在內存的高地址中,特別的MSB最高有效字節爲0x12存放在低字節
小端(Little-endian)模式,是指數據的高字節保存在內存的高地址中,而數據的低字節保存在內存的低地址中,,特別的LSB最高有效字節爲0x78存放在低字節
填寫數據時我們可以發現
BE big-endian 大端模式
最直觀的字節序
地址低位存儲值的高位
地址高位存儲值的低位
爲什麼說直觀,不要考慮對應關係
只需要把內存地址從左到右按照由低到高的順序寫出
把值按照通常的高位到低位的順序寫出
兩者對照,一個字節一個字節的填充進去LE little-endian 小端模式
最符合人的思維的字節序
地址低位存儲值的低位
地址高位存儲值的高位
怎麼講是最符合人的思維的字節序,是因爲從人的第一觀感來說
低位值小,就應該放在內存地址小的地方,也即內存地址低位
反之,高位值就應該放在內存地址大的地方,也即內存地址高位
程序分析
如何編寫程序測試看CPU使用的是大端模式還是小端模式
下面這段代碼可以用來測試一下你的編譯器是大端模式還是小端模式:
#include<stdio.h>
int main()
{
short int x;
char x0,x1;
x=0x1122;
x0=((char *)&x)[0]; //低地址單元
x1=((char *)&x)[1]; //高地址單元
printf("x0=0x%x,x1=0x%x",x0,x1);// 若x0=0x11,則是大端; 若x0=0x22,則是小端......
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
我們把他封裝成函數的形式
//返回值:大端返回1,小段返回0
int check_end()
{
int i = 0x12345678;
char *c = (char *)&i;
return (*c == 0x12);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
也可以
//返回值:大端返回1,小段返回0
int CheckEnd()
{
union
{
int a;
char b;
}u;
u.a = 1;
if (u.b == 1)
return 0;
else
return 1;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
參考
深入淺出大端和小端