ARM程式由於位元組對齊引起的問題深入分析

2021-09-30 07:13:42 字數 1861 閱讀 5577

首先說說,什麼叫對齊。如果乙個資料是從偶位址開始的連續儲存,那麼它就是半字對齊,否則就是非半字對齊;半字對齊的特徵是bit0=0,其他位 為任意值。字對齊的特徵是bit1=0,bit0=1,其他位為任意值。如果乙個資料是以能被4 整除的位址開始的連續儲存,那麼它就是字對齊,否則就是非字對齊。舉例說明四位元組對齊: 對記憶體進行操作時,被訪問的位址必須為4的倍數。如果分配到的位址的位址不是4的倍數時,cpu實際訪問的位址還是按照字對齊的方式來操作。也就是自動屏 蔽bit1和bit0.   

用ads的arm c complier下optimization level可能引起問題,其中的乙個問題就是位元組對齊的問題。下面講講問題的現象及實質。

當時問題的現象是:程式使用一公共變數buf建立佇列,如果ads編譯優化選項採用minium則軟體工作正常;原始碼不變,如果採用all優化,則不正 常,資料紊亂且無法工作。為了發現問題,我們分別用minium和all編譯,在反彙編條件下單步跟蹤程式,觀察cpu暫存器和記憶體變數的變化情況。發現 在minium模式下,編譯器把佇列記憶體塊uart0txbuf分配到的位址是0x400015cc,這個位址是乙個4位元組對齊的位址,而在all模式 下,編譯器把buf分配的位址是0x400015c2,這個位址是乙個非4位元組對齊的位址。正是由於這個非4位元組對齊的位址導致了問題的發生。

問題發生在queuecreate(void *buf, uint32 sizeofbuf, uint8 (* readempty)(), uint8 (* writefull)())這個函式裡,問題是如何發生的,

在了解問題發生的機理前,先了解queuecreate這個函式的工作原理。queuecreate工作原理是,首先把buf指向的記憶體初始化為dataqueue格式的結構體。  dataqueue的結構體格式如下:

typedef struct dataqueue;

從 結構體可以看出,結構體位元組型別在記憶體分配為: 4位元組指標變數(*out)、4位元組指標變數(*in)、4位元組指標變數(*end)、2位元組變數ndata、2位元組變數maxdata、4位元組函式指標 變數readempty()、4位元組函式指標變數(writefull())

觀察結構體起始位址放在非對齊時會出現什麼情況。

起始位址為0x400015c2時的由編譯器分配得到的位址         實際操作位址

*out       0x400015c2~0x400015c5                                                0x40015c0~0x400015c3

*in         0x400014c6~0x400015c9                                                 x400014c4~0x400015c7

*end      0x400015ca~0x400015cd                                               0x400015c8~0x400015cb

從 表中可以看出,實際操作的位址按照4位元組對齊格式得到。例如,當執行*out進行操作時,自動遮蔽bit1和bit0,因此實際發生變化的是 0x40015c0~0x400015c3,而不是0x400015c2~0x400015c5,由於實際操作位址和編譯器分配位址互相覆蓋,當對*in 操作時,會導致*out一起變化,對*end操作時,*in也跟著變化。正是由於非對齊的原因導致建立佇列和對列操作完全錯誤。

當記憶體起始位址為4位元組對齊位址的情況時,編譯器分配位址和實際位址一致,因此不存在上述問題。

結 論:

在arm嵌入式系統中,當把乙個記憶體區域初始化為某個結構體時,必須注意位元組對齊的情況。如果該記憶體起始位址為非對齊位址,不僅得不到預期的結果,還可能 導致一些很奇怪的讓人無法理解表面問題。在c層面上不太容易觀察到這些問題的實質,只有深入到彙編一層去分析程式,才可能理解這些現象的深層原因。

ARM程式由於位元組對齊引起的問題深入分析

首先說說,什麼叫對齊。如果乙個資料是從偶位址開始的連續儲存,那麼它就是半字對齊,否則就是非半字對齊 半字對齊的特徵是bit0 0,其他位為任意值。字對齊的特徵是bit1 0,bit0 1,其他位為任意值。如果乙個資料是以能被4 整除的位址開始的連續儲存,那麼它就是字對齊,否則就是非字對齊。舉例說明四...

由於記憶體位元組對齊導致的硬體錯誤

最近在除錯stm32程式的時候,經常進到hardfault handler這個中斷裡。產生這個中斷的原因一般和記憶體有關係,像是陣列越界 堆疊溢位之類的。檢查了好幾天終於發現了問題的所在,產生問題的原因是程式在執行函式指標所指向的時候,由於指標指向的位址不對而引發hardfault handler中...

解決由於意外斷電引起的活動目錄服務停止問題

背景 位於集團b座的機房已經使用多年,很多硬體條件開始制約公司it的發展。6月中旬一天,由於機房空調進行維修,工人師傅冒然拉斷了電源總閘,導致機房內部分伺服器意外斷電。集團總部的兩台用活動目錄域控制器也不幸遇難。現象 負責機房的工程師在第一時間進行了及時的處理。恢復供電之後馬上啟動因斷電而停止的伺服...