在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

  • <dfn id="79stg"></dfn>
    <object id="79stg"><div id="79stg"><label id="79stg"></label></div></object>
    <ruby id="79stg"><dl id="79stg"><noscript id="79stg"></noscript></dl></ruby>

      新聞中心

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

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

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

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


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

      評(píng)論


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

      關(guān)閉