大小端及字節(jié)序在嵌入式軟件開發(fā)過程中經(jīng)常會遇到,數(shù)據(jù)傳輸、存儲、通信等這些地方都會牽涉到,下面就來給大家分享一下相關(guān)知識。
回顧字節(jié)序
字節(jié)序,即字節(jié)在電腦中存放時的序列與輸入(輸出)時的序列是先到的在前還是后到的在前。
---來自百度百科
拿數(shù)據(jù) 0x01020304為例:
在大端CPU中:數(shù)據(jù)將存儲為0x01(address + 0),0x02(address + 1),0x03(address + 2),0x04(address + 3)。
在小端CPU中:數(shù)據(jù)將存儲為0x04(address + 0),0x03(address + 1),0x02(address + 2),0x01(address + 3)。
如果你的程序使用簡單的數(shù)據(jù)結(jié)構(gòu)(例如“ int”和“ short”),則沒有什么麻煩。但是,如果數(shù)據(jù)結(jié)構(gòu)類似于以下示例,則可能會遇到問題。
union { unsigned int dat; unsigned char c[4]; }X; void foo( ) { int t0; X.dat = 0x01020304; t0 = X.c[0]; ??? }
在大端 CPU 中編譯并執(zhí)行此代碼時, t0”的值為0x01。在小端CPU中, t0”的值為0x04。
那么問題來了:要想使存儲順序從大端,變?yōu)樾《?,怎么辦呢?
方法其實有很多種,這里講講針對IAR的兩種方法:
使用__big_endian關(guān)鍵字。
使用__REV, __REV16, __REVSH, RBIT函數(shù)。
使用__big_endian關(guān)鍵字
IAR中__big_endian關(guān)鍵字提供了一種方便的方式來將應(yīng)用程序從big-endian移植到little-endian。
__big_endian關(guān)鍵字用于訪問以big-endian字節(jié)順序存儲的變量,而與應(yīng)用程序其余部分使用的字節(jié)順序無關(guān)。在ARMv6或更高版本進行編譯時,可以使用__big_endian關(guān)鍵字。
只需添加__big_endian關(guān)鍵字即可,如:
____big_endian union { unsigned int dat; unsigned char c[4]; }X; void foo( ) { int t0; X.dat = 0x01020304; t0 = X.c[0]; ??? }
修改后的代碼在低位字節(jié)CPU中編譯和執(zhí)行,變量“ t0”為0x01。
注意:此關(guān)鍵字不能用于指針。同樣,此屬性不能在數(shù)組上使用。
同時,關(guān)鍵字__big_endian插入REV指令以交換字節(jié)數(shù)據(jù),REV指令的插入會影響代碼大小和執(zhí)行時間。
關(guān)鍵字具有限制,不能應(yīng)用于復(fù)雜的數(shù)據(jù)結(jié)構(gòu),比如以下代碼會生成錯誤:
__big_endian union { unsigned long dat; unsigned char c[4]; struct { unsigned long a0: 1; unsigned long a1: 1; unsigned long a2: 2; unsigned long a3: 4; unsigned long a4: 8; unsigned long a5: 16; }s; } f1_dat2;
使用__REV, __REV16, __REVSH, RBIT函數(shù)
大端和小端之間的字節(jié)順序差異只是順序,因此我們需要做的是更改字節(jié)順序,我們再次以變量0x01020304為例:
我們可以通過代碼實現(xiàn)交換功能,比如:
typedef unsigned long uint32_t; uint32_t bswap_32(uint32_t x) { uint32_t t = x; uint32_t s; s = ( (((uint32_t)(t) (uint32_t)0x000000ffUL) << 24) | (((uint32_t)(t) (uint32_t)0x0000ff00UL) << 8) | (((uint32_t)(t) (uint32_t)0x00ff0000UL) >> 8) | (((uint32_t)(t) (uint32_t)0xff000000UL) >> 24) ); return s; }
通過這種方式實現(xiàn),將導(dǎo)致消耗更多時間和代碼大小。
在C代碼中,我們通常編寫內(nèi)聯(lián)匯編代碼實現(xiàn)交換。IAR有種內(nèi)部函數(shù)可以實現(xiàn)該功能。
比如下面交換功能:
代碼如下:
#include void x1( void ) { s2 = __REV(s1); s3 = __REV16(s1); s4 = __REVSH(s1); }
以上就是在IAR中實現(xiàn)大小端字節(jié)序的遷移方法,感興趣的讀者可以在IAR中編碼測試一下。
來源:嵌入式專欄
審核編輯:湯梓紅
-
單片機
+關(guān)注
關(guān)注
6030文章
44489瀏覽量
631996 -
嵌入式
+關(guān)注
關(guān)注
5059文章
18974瀏覽量
302065 -
cpu
+關(guān)注
關(guān)注
68文章
10805瀏覽量
210847
發(fā)布評論請先 登錄
相關(guān)推薦
評論