1. 程式人生 > >armcm3權威指南筆記----arm程式設計中地址未對齊方面的影響

armcm3權威指南筆記----arm程式設計中地址未對齊方面的影響

P152當使用C開發程式時,推薦開啟CM3的雙字對齊管理機制(在NVIC配置與控制暫存器中,把STKALIGN置位),程式碼形如:

#define NVIC_CCR ((volatile unsigned long *)(0xE000ED14))

*NVIC_CCR = *NVIC_CCR | 0x200; //設定STKALIGN

STKALIGN 的名詞解釋P306

在響應異常的自動入棧操作時,強制SP對齊到雙字地址上(為什麼要設定STKALIGN,是因為即使保證棧初始是8位元組對齊的,編譯器也只能保證在呼叫sprintf那個時刻棧是8位元組對齊的但不能保證任意時刻棧都是8位元組對齊的,如果恰巧在MSP沒有8位元組對齊的時刻發生了中斷,而中斷中又呼叫了sprintf,這種情況下仍會出錯

)。修訂版

0無此功能 ,位於配置與控制暫存器0xE000_ED14中。

這是用於確保系統能嚴格遵守AAPCS過程呼叫標準,箇中細節請參閱第12章P181

上面這段話專門有我的book子目錄下armcm3專案資料子目錄裡的Cortex M3核心版本和堆疊8位元組對齊對uT-Kernel核心移植的影響資料,可以看一下。

ut-kernel中也有在建立任務時,或者

knl_setup_context強制將棧8位元組對齊。

       ssp = tcb->isstack;

       /* 8 Byte align ( stack ) */

       if ( ((UW)ssp & 0x7) != 0 ) {

              ssp = (SStackFrame*)((UW)(ssp)-0x4);

       }

因為之前棧已經是4位元組對齊了,所以這個地方做這個操作就可以保證它是8位元組對齊了。

 為什麼ut-kernel要在建立新任務時保持任務棧的8位元組對齊啊?因為如果我們保證了棧初始的時候是8位元組對齊的,那麼編譯器可以保證以後呼叫浮點庫時堆疊仍是8位元組對齊的。而呼叫浮點庫函式如在程式中執行以下語句:

sprintf(buf,"%.3f\n\r",fff);前,棧沒八位元組對齊的話,螢幕上顯示列印的浮點資料不正確。

R13MSP,PSP的使用:R13總是32位的。但是在

CM3中,末2位被強制為0。因此,如果偶爾遇到使用R13作為基址的場合(強烈反對使用),必須更改程式碼,因為末2位的資訊已經丟失了。 P251

還有個對ARM對齊思想的認識:

在這個例子裡,我們使用了.ascii和.byte指示字來建立一個零結尾的字串。在定義了字串之後,我們又使用了.align來確保下一條指令會以正確的位置開始。如果不使用.align,彙編器則可能把下一條指令放到未對齊的地址P259

雙字堆疊對齊方式與異常堆疊幀 P241

在預設情況下,異常堆疊幀會自動對齊到雙字儲存器位置(修訂版2。早期為修訂版0/1寫的彙編程式,如果要通過堆疊來把資料傳送給異常服務程式,可能會受到影響。為了準確判定堆疊幀的起始位置是否往下挪移了一個字,異常服務例程要先讀取入棧PSR的位元9如果不想動舊的程式,也可以手工把STKALIGN位元清除這樣就與以前的一樣了。與EABI標準相容的應用程式不會受影響。這些程式通常是C程式,並且使用與EABI相容的編譯器編譯