<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > ARM平臺的字節對齊問(wèn)題

ARM平臺的字節對齊問(wèn)題

作者: 時(shí)間:2016-11-09 來(lái)源:網(wǎng)絡(luò ) 收藏
ARM流行已久,做嵌入式開(kāi)發(fā)的不知道ARM不大可能。鑒于其所具備的較低功耗下的較高性能,也就成了大多數嵌入式設備的首選

不過(guò)對于剛上手的人來(lái)說(shuō),有可能會(huì )遇到一些稀奇古怪的問(wèn)題。畢竟大部分人都習慣了IA-32下的程序設計,雖然兩者都是32位的
構完全不同,于是也導致了一些隱含的問(wèn)題。這里想描述一下一個(gè)有點(diǎn)蠱惑的問(wèn)題,即在A(yíng)RM上訪(fǎng)問(wèn)非對齊地址內容,會(huì )出現所
問(wèn)題。
ARM內存訪(fǎng)問(wèn)的對齊問(wèn)題
按照ARM文檔上的描述,其訪(fǎng)問(wèn)規則如下:
1. 一次訪(fǎng)問(wèn)4字節內容,該內容的起始地址必須是4字節對齊的位置上;
2. 一次訪(fǎng)問(wèn)2字節內容,該內容的起始地址必須是2字節對齊的位置上;
(單字節的沒(méi)有這個(gè)問(wèn)題,就不用考慮啦。 )
好,既然規則如此,那應該遵守。不過(guò)么,不安分的人往往喜歡破壞規則,喜歡看看不遵守規則會(huì )有什么結果;另外么,即便遵
免考慮不周,犯個(gè)錯也是正?,F象。好,那么讓我們來(lái)看看犯錯的結果吧。例如下面的代碼:
char buff[8] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, 0xbc, 0xcd};
int v32, *p32;
short v16, *p16;
p32 = (int*)&( buff[1] ); //unalignment
p16 = (short*)&( buff[1] ); //unalignment
v32 = *p32; //what’s the result?
v16 = *p16; //what’s the result?
如果上面這段代碼在IA-32上運行,那么結果應該如下:
v32 = 0x9a785634
v16 = 0x5634
即便非對齊地址上訪(fǎng)問(wèn),IA-32也就是犧牲一點(diǎn)性能,但是結果保證是正確的。恩,這也是我們所期望的……
可是…… 換到ARM上呢?我們來(lái)看看在A(yíng)DS1.2編譯后,執行的結果如下:

本文引用地址:http://dyxdggzs.com/article/201611/317698.htm

v32 = 0x12785634
v16 = 0x1234
這個(gè)結果有點(diǎn)奇怪了吧。照理說(shuō)指向0x34,那么如果是Big-Endian的話(huà),v32應該是0x3456789a,如果是Little-Endian的話(huà),就是前面
可現在的結果呢??jì)烧叨疾皇?,莫名地把更低地址?x12給湊進(jìn)來(lái)了…… 而如果看看編譯生成的匯編code的話(huà),這兩個(gè)賦值很
ldrsh指令,指令沒(méi)有問(wèn)題,分別用于讀取32位和16位數據,都是最基本的指令。嗯,嗯,這就是我們所要描述的訪(fǎng)問(wèn)非對齊地址的
問(wèn)題的緣由(個(gè)人猜測,非官方資料……)
個(gè)人感覺(jué)呢,這是ARM體系架構實(shí)現的問(wèn)題,或者說(shuō)這本來(lái)就是By Design的。這樣做簡(jiǎn)化了處理器的實(shí)現,IA-32實(shí)現的時(shí)候肯定
齊進(jìn)行判斷,然后轉換為相應的操作 ,而ARM呢?沒(méi)有做這個(gè)事情,默認認為大家都按照規矩辦事,你要是膽敢破壞,俺就給你
那有沒(méi)有辦法解決呢?
這個(gè)問(wèn)題其實(shí)ARM自己也知道,所以呢,它在編譯器里面,已經(jīng)添加了部分支持。不過(guò)有人會(huì )問(wèn),那上面那個(gè)情況呢?為什么結
有添加什么支持嘛……
嗯,其實(shí)ARM是做了一定的努力的,只是這個(gè)情況它沒(méi)辦法解決…… 它做的事情就是:在編譯器能夠的得知的情況下,盡量保證訪(fǎng)問(wèn)
話(huà)有點(diǎn)籠統,那么把具體情況一個(gè)個(gè)來(lái)看看吧。
編譯器的努力(1)—— 所有局部/全局/靜態(tài)等變量都放在4字節對齊的地址上
其實(shí)這個(gè)努力很常見(jiàn),由于在32位平臺上,一次訪(fǎng)問(wèn)4字節是效率最高的,所以大多數32平臺的編譯器都如此處理,ARM的ADS也不例外
編譯器的努力(2)—— 填充、填充、再填充
這個(gè)事情么,其實(shí)也是常見(jiàn)的。各類(lèi)編譯器上,對于某些結構定義中會(huì )產(chǎn)生不對齊的情況,自動(dòng)填充,以提高訪(fǎng)問(wèn)效率(例如IA
會(huì )加1個(gè)周期的)。而ARM的編譯器也一樣操作,不過(guò)感覺(jué)這里不單單是為了提高效率,也能夠順帶解決這個(gè)不對齊的問(wèn)題。
編譯器的努力(3)—— 產(chǎn)生特殊代碼
嗯,這個(gè)就是關(guān)鍵了,也是ARM編譯器的與眾不同之處。先來(lái)看一段代碼:
__packed typedef struct _test
{
char a;
short c;
int d;
} test;
char buff[8] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, 0xbc, 0xcd};
test *p = (test *)buff;
v32 = p->d; //這里的v32借用上面的定義;
貌似多了個(gè)限定為_(kāi)_packed的struct,以此來(lái)造成不對齊的狀況,看不出多大區別嘛??墒沁\行一下的話(huà),就會(huì )發(fā)現這里的結果是正
ADS生成的匯編代碼吧。
v32 = q->d;
[0xe2890003] add r0,r9,#3
[0xeb000088] bl __rt_uread4
[0xe1a05000] mov r5,r0

看到這里的那條"bl __rt_uread4"的指令了吧。對ARM指令有一定了解的都知道bl其實(shí)就是一個(gè)函數調用。所以,這里的代
自己提供的__rt_uread4函數,該函數完成的操作就是讀取四個(gè)字節。ADS提供了類(lèi)似的一系列函數,針對signed/unsigned,以及
寫(xiě)入操作。
估計看到這里,大家會(huì )問(wèn),如果沒(méi)有__packed限定符呢?猜對了,沒(méi)有__packed限定符,那么編譯器會(huì )對上面的情況pending,
所在的位置是4字節對齊的(編譯期信息,而非實(shí)際運行期信息)。所以就回到類(lèi)似最初的例子了。
那么,還有一種情況,就是在有__packed的情況下,而struct里的字段都是符合對齊要求的,那么生成的代碼會(huì )是怎么樣的呢?
看,和上面的這段匯編代碼,唯一的區別就是第一條指令把#3改成了#4,而后面仍舊調用__rt_uread4函數。嗯,這樣結論就出
編譯器會(huì )在使用__packed的情況下,自動(dòng)對其中的4字節/2字節訪(fǎng)問(wèn)添加特殊代碼,以保證其結果的正確。
好了,這個(gè)關(guān)于這個(gè)問(wèn)題描述得差不多了,可能的話(huà),盡量倚賴(lài)編譯器的這些功能,而對于編譯器無(wú)能為力的部分,就要靠萬(wàn)分小心了
p.s. 其實(shí)這里有很多事情可以來(lái)盡量預防此類(lèi)問(wèn)題,比如嵌入式項目往往喜歡自己管理內存分配,那么自己寫(xiě)的內存分配函數
字節對齊位置上的……



關(guān)鍵詞: ARM平臺字節對

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>