典故
端模式(Endian)的這個詞出自Jonathan Swift書寫的《格列佛遊記》。這本書根據將雞蛋敲開的方法不同將所有的人分為兩類,從圓頭開始將雞蛋敲開的人被歸為Big Endian,從尖頭開始將雞蛋敲開的人被歸為Littile Endian。小人國的內戰就源於吃雞蛋時是究竟從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開。在電腦業Big Endian和Little Endian也幾乎引起一場戰爭。在電腦業界,Endian表示資料在儲存空間中的存放順序。
簡介
嵌入式系統開發人員應該對Little-endian和Big-endian模式非常瞭解。採用Little-endian模式的CPU對運算元的存放方式是從低位元組到高位元組,而Big-endian模式對運算元的存放方式是從高位元組到低位元組。例如,32bit寬的數0x12345678的存放方式如下:
地址位移 |
大端模式 |
小端模式 |
0x00 |
12 |
78 |
0x01 |
34 |
56 |
0x02 |
56 |
34 |
0x03 |
78 |
12 |
由上表所知,採用大小模式對資料進行存放的主要區別在於在存放的位元組順序,大端方式將高位存放在低地址,小端方式將低位存放在高地址。採用大端方式 進行資料存放符合人類的正常思維,而採用小端方式進行資料存放利於電腦處理。到目前為止,採用大端或者小端進行資料存放,其孰優孰劣也沒有定論。
有的處理器系統採用了小端方式進行資料存放,如Intel的奔騰。有的處理器系統採用了大端方式進行資料存放,如IBM半導體和Freescale的PowerPC處理器。不僅對於處理器,一些外設的設計中也存在著使用大端或者小端進行資料存放的選擇。
因此在一個處理器系統中,有可能存在大端和小端模式同時存在的現象。這一現象為系統的軟硬體設計帶來了不小的麻煩,這要求系統設計工程師,必須深入理解大端和小端模式的差別。大端與小端模式的差別體現在一個處理器的寄存器,指令集,系統匯流排等各個層次中。
判斷方法
1
- int bigendian()
- {
- int i = 1;
- return *(char *) &i == 0;
- }
2.
- int test(){
- union w
- {
- int a;
- char b;
- }var;
- var.a=1;
- return(var.b==1);
- }
- ret=test();
- if(ret)
- //small
- else
- //big
--原理都一樣
小端轉為大端
這個分析二進位檔案時經常遇到,其實也很簡單,移一下位元組就可以了。
- typedef unsigned int u_bits_32; // 32 bits
- typedef int bits_32;// 32 bits
- typedef unsigned short u_bits_16; //16 bits
- typedef short bits_16; //16 bits
- typedef unsigned char u_bits_8; //8 bits
- typedef char bits_8; //8 bits
- //little-endian X86
- inline u_bits_16 convert_chars_to_bits(bits_8 l,bits_8 r)
- {
- u_bits_8 left = (u_bits_8) l;
- u_bits_8 right = (u_bits_8) r;
- u_bits_16 ret=0;
- ret |= right;
- if (ret)
- ret = ret << 8;
- ret |= left;
- return ret;
- }
- //little-endian X86
- inline bits_32 convert_chars_to_bits(bits_8 l1,bits_8 l2,bits_8 r1,bits_8 r2)
- {
- u_bits_16 ret_l = convert_chars_to_bits(l1,l2);
- u_bits_16 ret_r = convert_chars_to_bits(r1,r2);
- u_bits_32 ret = 0;
- ret |= ret_r;
- if (ret)
- ret = ret << 16;
- ret |= ret_l;
- return (bits_32)ret;
- }