在前面的章節(jié)本教程介紹了多字節(jié)數(shù)據(jù)的big和little endian表示法的概念。這一節(jié)將詳細(xì)介紹這一主題。讀者可能會(huì)回憶起endian表示法指的是一個(gè)多字節(jié)數(shù)據(jù)的單個(gè)字節(jié)元素儲(chǔ)存在內(nèi)存中的順序。Big endian是最直接的方法。它首先儲(chǔ)存的是最高有效字節(jié),然后是第二個(gè)有效字節(jié),以些類(lèi)推。換句話說(shuō)就是,大的位被首先儲(chǔ)存。Little endian以一個(gè)相反的順序來(lái)儲(chǔ)存字節(jié)(最小的有效字節(jié)最先被儲(chǔ)存)。x86家族的處理器使用的就是little endian表示法。
看一個(gè)例子:考慮雙字
的表示。如果是big endian表示法,這些字節(jié)將像這樣儲(chǔ)存:12 34 56 78。如果是little endian表示法,這些字節(jié)就像這樣儲(chǔ)存:78 56 34 12。
現(xiàn)在讀者可能會(huì)這樣問(wèn)自己:一個(gè)理智的芯片設(shè)計(jì)者怎么會(huì)使用little endian表示法?在Intel公司里的工程師是不是虐待狂?因?yàn)樗麄兪箯V大的程序員承受了這種混亂的表示法。像這樣,CPU看起來(lái)會(huì)因?yàn)樵趦?nèi)存中向后儲(chǔ)存字節(jié)而做額外的工作(而且從內(nèi)存中讀出時(shí)又要顛倒它們)。答案是CPU使用little endian格式讀寫(xiě)內(nèi)存是不需要做額外的工作的。你必須認(rèn)識(shí)到CPU是由許多電子電路組成,簡(jiǎn)單地工作在位值上。位(和字節(jié))在CPU中不需要有任何的順序的。
考慮2個(gè)字節(jié)的寄存器AX。這可以分解成單個(gè)字節(jié)的寄存器:AH和AL。在CPU中的電路保留了AH 和AL的值。在一個(gè)CPU中,電路是沒(méi)有任何順序的。也就是說(shuō),儲(chǔ)存AH的電路可以在儲(chǔ)存AL的電路前面或后面。mov指令復(fù)
制AX的值到內(nèi)存中,首先復(fù)制AL的值,接著是AH。CPU做這件事一點(diǎn)也沒(méi)有比先儲(chǔ)存AH難。
同樣的討論還可以用到一個(gè)字節(jié)的單個(gè)比特位上。它們?cè)贑PU電路(或就此而言,內(nèi)存)里并不真的有一定順序。但是,因?yàn)樵贑PU或內(nèi)存中單個(gè)的比特位并沒(méi)有編址,所以沒(méi)有辦法知道(或關(guān)心)CPU在內(nèi)部對(duì)它們是如
何排序的。
在圖3.4中的C代碼展示了如何確定CPU的Endian格式。p指針把word變量當(dāng)作兩個(gè)元素的字符數(shù)組來(lái)看待。因此,word在內(nèi)存里的第一個(gè)字節(jié)賦值給了p[0],而這取決于CPU的Endian格式。

什么時(shí)候需要在乎Little和Big Endian
對(duì)于典型的編程,CPU的Endian格式并不是很重要。它很重要的大多數(shù)時(shí)刻是在不同的計(jì)算機(jī)系統(tǒng)間傳輸二進(jìn)制數(shù)據(jù)時(shí)。此時(shí)使用的要么是某種類(lèi)型的物理數(shù)據(jù)媒介(例如一塊硬盤(pán))要么是網(wǎng)絡(luò)。因?yàn)锳SCII數(shù)據(jù)是單個(gè)字節(jié)的,Endian格式對(duì)它來(lái)說(shuō)是沒(méi)有問(wèn)題的。
所有的內(nèi)部的TCP/IP消息頭都以big endian的格式來(lái)儲(chǔ)存整形。(稱(chēng)為網(wǎng)絡(luò)字節(jié)續(xù)). TCP/IP 庫(kù)提供了可移植處理Endian格式問(wèn)題的方法的C函數(shù)。例如:htonl () 函數(shù)把一個(gè)雙字(或長(zhǎng)整形)從主機(jī)格式轉(zhuǎn)換成了網(wǎng)絡(luò)格式。ntohl ()函數(shù)執(zhí)行一個(gè)相反的交換。對(duì)于一個(gè)big endian系統(tǒng),這兩個(gè)函數(shù)僅僅是無(wú)修改地返回它們的輸入。這就允許你寫(xiě)出的網(wǎng)絡(luò)程序可以在任何的Endian格式系統(tǒng)上成功編譯和運(yùn)行。
圖3.5展示了一個(gè)轉(zhuǎn)換雙字Endian格式的C函數(shù)。486處理器提供了一個(gè)名為BSWAP的新的指令來(lái)交換任意32位寄存器中的字節(jié)。例如:
bswap edx ; 交換edx中的字節(jié)
這條指令不可以使用在16位的寄存器上。但是XCHG 指令可以用來(lái)交換可以分解成8位寄存器的16寄存器中的字節(jié)。例如:
xchg ah,al ; 交換ax中的字節(jié)
更多建議: