端序
端序(英語:Endianness),又稱位元組順序,又稱尾序,在電腦科學領域中,指電腦記憶體中或在數字通訊鏈路中,組成多位元組的字的位元組的排列順序。
在幾乎所有的機器上,多位元組對象都被儲存為連續的位元組序列。例如在C語言中,一個類型為int
的變數x
地址為0x100
,那麼其對應地址表達式&x
的值為0x100
。且x
的四個位元組將被儲存在電腦記憶體的0x100, 0x101, 0x102, 0x103
位置。[1]
位元組的排列方式有兩個通用規則。例如,將一個多位數的低位放在較小的地址處,高位放在較大的地址處,則稱小端序;反之則稱大端序。在網絡應用中,位元組序是一個必須被考慮的因素,因為不同機器類型可能採用不同標準的位元組序,所以均按照網絡標準轉化。
例如假設上述變數x
類型為int
,位於地址0x100
處,它的值為0x01234567
,地址範圍為0x100~0x103
位元組,其內部排列順序依賴於機器的類型。大端法從首位開始將是:0x100: 0x01, 0x101: 0x23, 0x102: 0x45, 0x103: 0x67
。而小端法將是:0x100: 0x67, 0x101: 0x45, 0x102: 0x23, 0x103: 0x01
。
端(endian)的起源
[編輯]「endian」一詞來源於十八世紀愛爾蘭作家喬納森·斯威夫特(Jonathan Swift)的小說《格列佛遊記》(Gulliver's Travels)。小說中,小人國為水煮蛋該從大的一端(Big-End)剝開還是小的一端(Little-End)剝開而爭論,爭論的雙方分別被稱為「大頭派(Big-Endians)」和「小頭派(Little-Endians)」。以下是1726年關於大小端之爭歷史的描述:
“ | 我下面要告訴你的是,Lilliput和Blefuscu這兩大強國在過去36個月裏一直在苦戰。戰爭開始是由於以下的原因:我們大家都認為,吃雞蛋前,原始的方法是打破雞蛋較大的一端,可是當今皇帝的祖父小時候吃雞蛋,一次按古法打雞蛋時碰巧將一個手指弄破了。因此他的父親,當時的皇帝,就下了一道敕令,命令全體臣民吃雞蛋時打破雞蛋較小的一端,違令者重罰。老百姓們對這項命令極其反感。歷史告訴我們,由此曾經發生過6次叛亂,其中一個皇帝送了命,另一個丟了王位。這些叛亂大多都是由Blefuscu的國王大臣們煽動起來的。叛亂平息後,流亡的人總是逃到那個帝國去尋求避難。據估計,先後幾次有11000人情願受死也不肯去打破雞蛋較小的一端。關於這一爭端,曾出版過幾百本大部著作,不過大頭派的書一直是受禁的,法律也規定該派任何人不得做官。」 | ” |
——《格列夫遊記》 第一卷第4章 蔣劍鋒(譯) |
1980年,丹尼·科恩(Danny Cohen),一位網絡協定的早期開發者,在其著名的論文"On Holy Wars and a Plea for Peace"中,為平息一場關於位元組該以什麼樣的順序傳送的爭論,而第一次參照了該詞。[2]
位元組順序
[編輯]在哪種位元組順序更合適的問題上,人們表現得非常情緒化,實際上,就像雞蛋的問題一樣,沒有技術上的原因來選擇位元組順序規則,因此,爭論淪為關於社會政治問題的爭論,只要選擇了一種規則並且始終如一地堅持,其實對於哪種位元組排序的選擇是任意的。
對於單一的位元組(a byte),大部分處理器以相同的順序處理位元,因此單位元組的存放方法和傳輸方式一般相同。
對於多位元組數據,如整數(32位元機中一般佔4位元組),在不同的處理器的存放方式主要有兩種,以主記憶體中0x0A0B0C0D的存放方式為例,分別有以下幾種方式:
- 注: 0x字首代表十六進制。
大端序
[編輯]大端序(英:big-endian)或稱大尾序。
- 數據以8位元為單位:
地址增長方向 → | |||||
0x0A | 0x0B | 0x0C | 0x0D |
範例中,最高位位元組是0x0A 儲存在最低的主記憶體地址處。下一個位元組0x0B存在後面的地址處。正類似於十六進制位元組從左到右的閱讀順序。
- 數據以16位元為單位:
地址增長方向 → | |||||
0x0A0B | 0x0C0D |
最高的16位元單元0x0A0B儲存在低位。
小端序
[編輯]小端序(英:little-endian)或稱小尾序。
- 數據以8位元為單位:
地址增長方向 → | |||||
0x0D | 0x0C | 0x0B | 0x0A |
最低位位元組是0x0D 儲存在最低的主記憶體地址處。後面位元組依次存在後面的地址處。
- 數據以16位元為單位:
地址增長方向 → | |||||
0x0C0D | 0x0A0B |
最低的16位元單元0x0C0D儲存在低位。
- 更改地址的增長方向:
當更改地址的增長方向,使之由右至左時,表格更具有可閱讀性。
← 地址增長方向 | |||||
0x0A | 0x0B | 0x0C | 0x0D |
最低有效位(LSB)是0x0D 儲存在最低的主記憶體地址處。後面位元組依次存在後面的地址處。
← 地址增長方向 | |||||
0x0A0B | 0x0C0D |
最低的16位元單元0x0C0D儲存在低位。
混合序
[編輯]混合序(英:middle-endian)具有更複雜的順序。以PDP-11為例,0x0A0B0C0D被儲存為:
- 32位元在PDP-11的儲存方式
地址增長方向 → | |||||
0x0B | 0x0A | 0x0D | 0x0C |
可以看作高16位元和低16位元以大端序儲存,但16位元內部以小端儲存。
處理器體系
[編輯]- x86、MOS Technology 6502、Z80、VAX、PDP-11、RISC-V等處理器為小端序;
- Motorola 6800、Motorola 68000、PowerPC 970、System/370、SPARC(除V9外)等處理器為大端序;
- ARM、PowerPC(除PowerPC 970外)、DEC Alpha、SPARC V9、MIPS、PA-RISC及IA64的位元組序是可調整的。
網絡序
[編輯]網絡傳輸一般採用大端序,也被稱之為網絡位元組序,或網絡序。IP協定中定義大端序為網絡位元組序。
Berkeley通訊端定義了一組轉換函數,用於16和32位元整數在網絡序和本機位元組序之間的轉換。htonl,htons用於本機序轉換到網絡序;ntohl,ntohs用於網絡序轉換到本機序。
位序
[編輯]一般用於描述串行裝置的傳輸順序。網絡協定中只有數據鏈路層的底端會涉及到。
小端序(先傳低位)的串行協定
[編輯]大端序(先傳高位)的串行協定
[編輯]參見
[編輯]參考資料
[編輯]外部連結
[編輯]- Endian的由來 (頁面存檔備份,存於互聯網檔案館)
- White Paper: Endianness or Where is Byte 0?(頁面存檔備份,存於互聯網檔案館)(英文)
- Byte Ordering PPC (頁面存檔備份,存於互聯網檔案館)(英文)
- The Layout of Data in Memory(英文)
- Writing endian-independent code in C (頁面存檔備份,存於互聯網檔案館)(英文)
- How to convert an integer to little endian or big endian (頁面存檔備份,存於互聯網檔案館)(英文)
- Understanding big and little endian byte order(頁面存檔備份,存於互聯網檔案館)(英文)
- Mandatory reading: ON HOLY WARS AND A PLEA FOR PEACE(英文)