色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > ARM程序由于字節(jié)對齊引起的問題深入分析

          ARM程序由于字節(jié)對齊引起的問題深入分析

          作者: 時間:2016-11-09 來源:網(wǎng)絡(luò) 收藏
          首先說說,什么叫對齊。如果一個數(shù)據(jù)是從偶地址開始的連續(xù)存儲,那么它就是半字對齊,否則就是非半字對齊;半字對齊的特征是bit0=0,其他位為任意 值。字對齊的特征是bit1=0,bit0=1,其他位為任意值。如果一個數(shù)據(jù)是以能被4 整除的地址開始的連續(xù)存儲,那么它就是字對齊,否則就是非字對齊。舉例說明四字節(jié)對齊: 對內(nèi)存進(jìn)行操作時,被訪問的地址必須為4的倍數(shù)。如果分配到的地址的地址不是4的倍數(shù)時,CPU實(shí)際訪問的地址還是按照字對齊的方式來操作。也就是自動屏蔽bit1和bit0.
          用ADS的ARMC Complier下Optimization Level可能引起問題,其中的一個問題就是字節(jié)對齊的問題。下面講講問題的現(xiàn)象及實(shí)質(zhì)。
          當(dāng)時問題的現(xiàn)象是:程序使 用一公共變量Buf創(chuàng)建隊列,如果ADS編譯優(yōu)化選項采用Minium則軟件工作正常;源碼不變,如果采用ALL優(yōu)化,則不正常,數(shù)據(jù)紊亂且無法工作。為 了發(fā)現(xiàn)問題,我們分別用Minium和ALL編譯,在反匯編條件下單步跟蹤程序,觀察CPU寄存器和內(nèi)存變量的變化情況。發(fā)現(xiàn)在Minium模式下,編譯 器把隊列內(nèi)存塊Uart0TxBuf分配到的地址是0x400015cc,這個地址是一個4字節(jié)對齊的地址,而在ALL模式下,編譯器把Buf分配的地址 是0x400015c2,這個地址是一個非4字節(jié)對齊的地址。正是由于這個非4字節(jié)對齊的地址導(dǎo)致了問題的發(fā)生。
          問題發(fā)生在QueueCreate(void *Buf, uint32 SizeOfBuf, uint8 (* ReadEmpty)(), uint8 (* WriteFull)())這個函數(shù)里,問題是如何發(fā)生的,
          在了解問題發(fā)生的機(jī)理前,先了解QueueCreate這個函數(shù)的工作原理。QueueCreate工作原理是,首先把buf指向的內(nèi)存初始化為DataQueue格式的結(jié)構(gòu)體。DataQueue的結(jié)構(gòu)體格式如下:
          typedef struct {
          QUEUE_DATA_TYPE *Out; /* 指向數(shù)據(jù)輸出位置 */
          QUEUE_DATA_TYPE *In; /* 指向數(shù)據(jù)輸入位置 */
          QUEUE_DATA_TYPE *End; /* 指向Buf的結(jié)束位置 */
          uint16 NData; /* 隊列中數(shù)據(jù)個數(shù) */
          uint16 MaxData; /* 隊列中允許存儲的數(shù)據(jù)個數(shù) */

          uint8 (* ReadEmpty)(); /* 讀空處理函數(shù) */
          uint8 (* WriteFull)(); /* 寫滿處理函數(shù) */
          QUEUE_DATA_TYPE *Buf; /* 存儲數(shù)據(jù)的空間 */
          } DataQueue;
          從結(jié)構(gòu)體可以看出,結(jié)構(gòu)體字節(jié)類型在內(nèi)存分配為: 4字節(jié)指針變量(*Out)、4字節(jié)指針變量(*In)、4字節(jié)指針變量(*End)、2字節(jié)變量NData、2字節(jié)變量MaxData、4字節(jié)函數(shù)指針 變量ReadEmpty()、4字節(jié)函數(shù)指針變量 WriteFull()。
          觀察結(jié)構(gòu)體起始地址放在非對齊時會出現(xiàn)什么情況。
          起始地址為0x400015c2時的由編譯器分配得到的地址 實(shí)際操作地址
          *Out 0x400015c2~0x400015c5 0x40015c0~0x400015c3
          *In 0x400014c6~0x400015c9 0x400014c4~0x400015c7
          *End 0x400015ca~0x400015cd 0x400015c8~0x400015cb
          從表中可以看出,實(shí)際操作的地址按照4字節(jié)對齊格式得到。例如,當(dāng)執(zhí)行*Out進(jìn)行操作時,自動屏蔽bit1和bit0,因此實(shí)際發(fā)生變化的是 0x40015c0~0x400015c3,而不是0x400015c2~0x400015c5,由于實(shí)際操作地址和編譯器分配地址互相覆蓋,當(dāng)對*In 操作時,會導(dǎo)致*Out一起變化,對*End操作時,*In也跟著變化。正是由于非對齊的原因?qū)е聞?chuàng)建隊列和對列操作完全錯誤。
          當(dāng)內(nèi)存起始地址為4字節(jié)對齊地址的情況時,編譯器分配地址和實(shí)際地址一致,因此不存在上述問題。
          結(jié) 論:
          在ARM嵌入式系統(tǒng)中,當(dāng)把一個內(nèi)存區(qū)域初始化為某個結(jié)構(gòu)體時,必須注意字節(jié)對齊的情況。如果該內(nèi)存起始地址為非對齊地址,不僅得不到預(yù)期的結(jié)果,還可能 導(dǎo)致一些很奇怪的讓人無法理解表面問題。在C層面上不太容易觀察到這些問題的實(shí)質(zhì),只有深入到匯編一層去分析程序,才可能理解這些現(xiàn)象的深層原因。


          關(guān)鍵詞: ARM程序字節(jié)對

          評論


          技術(shù)專區(qū)

          關(guān)閉