電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>嵌入式開發(fā)>Cortex-M3 棧的8字節(jié)對(duì)齊資料下載

Cortex-M3 棧的8字節(jié)對(duì)齊資料下載

2021-04-11 | pdf | 118.22KB | 次下載 | 2積分

資料介紹

一、什么是棧對(duì)齊? 棧的字節(jié)對(duì)齊,實(shí)際是指棧頂指針須是某字節(jié)的整數(shù)倍。因此下邊對(duì)系統(tǒng)棧與MSP,任務(wù)棧與PSP,棧對(duì)齊與SP對(duì)齊 這三對(duì)概念不做區(qū)分。另外下文提到編譯器的時(shí)候,實(shí)際上是對(duì)編譯器匯編連接器的統(tǒng)稱。 之前對(duì)棧的8字節(jié)對(duì)齊理解的不透,就在網(wǎng)上查了好多有關(guān)棧字節(jié)對(duì)齊、還有一些ARM對(duì)齊偽指令的資料信息,又做了一些實(shí)驗(yàn),把這些零碎的信息拼接在一起,總覺得理解透這個(gè)問題的話得長(zhǎng)篇大論了。結(jié)果昨天看了AAPCS手冊(cè)、然后查到了沒有使用PRESERVE8偽指令出現(xiàn)錯(cuò)誤的實(shí)例,突然覺得長(zhǎng)篇大論不存在了,半篇小論這問題就能理順了。 二、AAPCS棧使用規(guī)約 在ARM上編程,但凡涉及到調(diào)用,就需要遵循一套規(guī)約AAPCS:《Procedure Call Standard for the ARM Architecture》。這套規(guī)約里面對(duì)棧使用的約定如下: 5.2.1.1 Universal stack constraints At all times the following basic constraints must hold: Stack-limit SP mod 4 = 0. The stack must at all times be aligned to a word boundary. A process may only access (for reading or writing) the closed interval of the entire stack delimited by [SP, stack-base – 1] (where SP is the value of register r13). Note This implies that instructions of the following form can fail to satisfy the stack discipline constraints, even when reg points within the extent of the stack. ldmxx reg, {..., sp, ...} // reg != sp If execution of the instruction is interrupted after sp has been loaded, the stack extent will not be restored, so restarting the instruction might violate the third constraint. 5.2.1.2 Stack constraints at a public interface The stack must also conform to the following constraint at a public interface: SP mod 8 = 0. The stack must be double-word aligned. 可以看到,規(guī)約規(guī)定,棧任何時(shí)候都得4字節(jié)對(duì)齊,在調(diào)用入口得8字節(jié)對(duì)齊。 在這個(gè)約定里,棧的4字節(jié)對(duì)齊確實(shí)得任何時(shí)候都遵守,而且你想不遵守都難,因?yàn)镾P的最后兩位是硬件上保持0的。而對(duì)于8字節(jié)對(duì)齊,這就需要碼農(nóng)和編譯器配合著來。需要說明的一點(diǎn)是,8字節(jié)對(duì)齊即使不遵守,一些情況下也沒問題,只要主調(diào)和被調(diào)用例程兩邊把堆棧使用,傳參,返回等處理好就行,也就是說兩邊有自己的一套約定就行。但是有時(shí)候,主調(diào)這邊在調(diào)用嚴(yán)格遵守AAPCS的函數(shù)時(shí),沒有將棧保持在8字節(jié)對(duì)齊上,那就會(huì)出問題。 三、如何編程? 在Cortex-M3上編程時(shí),對(duì)于AAPCS棧使用約定的遵守,總的來說就兩條: 1. 匯編文件中需要我們親自動(dòng)手來保證遵守AAPCS棧使用約定。 (特別注意每次從匯編進(jìn)入C的世界時(shí),要保證匯編部分的編碼在調(diào)用c接口時(shí)棧是8字節(jié)對(duì)齊的,不要疏忽了,因?yàn)閏編譯器可不負(fù)責(zé)調(diào)整。c編譯器說你得送給我的SP就是8字節(jié)對(duì)齊的,我才能保證接下來的C部分沒有結(jié)束之前,遵守AAPCS棧使用約定) 2. 在C文件中,由編譯器來處理。 四、補(bǔ)充: 1. 由于程序的入口點(diǎn)為復(fù)位中斷響應(yīng)函數(shù),一般我們都寫在啟動(dòng)代碼里,通常是一個(gè)匯編文件,然后經(jīng)由匯編進(jìn)入到C程序的main入口處,在調(diào)用main的時(shí)刻,為遵循AAPCS,就得在此時(shí)保持8字節(jié)對(duì)齊。 2. 對(duì)于MSP,Keil MDK為我們提供了一個(gè)用來初始化C運(yùn)行庫環(huán)境的函數(shù)_main,這個(gè)函數(shù)會(huì)調(diào)用_user_setup_stackheap函數(shù),該函數(shù)將MSP的低三位清零,然后在進(jìn)入main之前不對(duì)其進(jìn)行更改,這樣在進(jìn)入main的時(shí)刻,MSP保證為8字節(jié)對(duì)齊的。 3. 對(duì)于PSP,一般在上多任務(wù)OS時(shí)會(huì)用它,對(duì)于PSP我們要比MSP更為操心點(diǎn),因?yàn)镸SP起碼還可以通過調(diào)用_main來跳進(jìn)main的方式保證進(jìn)入C世界的時(shí)候是遵守約定的。而PSP全靠自己來保證每次進(jìn)入C世界時(shí)是8字節(jié)對(duì)齊。 4. 另外只要是匯編文件,可配合使用匯編命令armasm --diag_warning 1546,這樣匯編器就會(huì)對(duì)一些SP沒有8字節(jié)對(duì)齊的地方給出警告,但是我發(fā)現(xiàn)匯編器并不能保證檢測(cè)到所有對(duì)SP造成8字節(jié)不對(duì)齊的操作,例如直接給SP載入一個(gè)立即數(shù)這種,匯編器就發(fā)現(xiàn)不了。我并沒有對(duì)所有會(huì)影響SP的指令進(jìn)行測(cè)試(原因是不熟悉。。。),不知道1546這個(gè)警告能覆蓋多少指令,所以總的來講,對(duì)匯編文件就是睜大自己的鈦合金眼,爭(zhēng)取大部分工作都放到C中去。 五. Cortex-M3 中斷控制器的棧對(duì)齊調(diào)整功能(該功能在r2p0版本以后的內(nèi)核中均默認(rèn)開啟,STKALIGN位默認(rèn)為1) Cortex M3 NVIC CCR寄存器(控制與配置寄存器)的STKALIGN位置1,那么在發(fā)生中斷時(shí),進(jìn)入中斷響應(yīng)函數(shù)前,內(nèi)核會(huì)首先檢查當(dāng)前正在使用的棧指針是否8字節(jié)對(duì)齊,如果是,則正常將xPSR,PC,LR,SP,R0-R3入棧,如果不是,則先把SP-4,調(diào)整為8字節(jié)對(duì)齊,然后將xPSR第九位置1,接著把xPSR,PC,LR,SP,R0-R3入棧,再然后才進(jìn)入中斷響應(yīng)函數(shù)。這樣可以保證程序在運(yùn)行過程中,如果在棧沒有發(fā)生4字節(jié)對(duì)齊的地方發(fā)生中斷了,進(jìn)入到中斷響應(yīng)函數(shù)的時(shí)候也是遵守AAPCS棧使用約定的。如果中斷服務(wù)程序是做任務(wù)切換的,那么前面的情況就是將任務(wù)棧調(diào)整為對(duì)齊,然后進(jìn)入異常服務(wù)程序后使用系統(tǒng)棧,那如果系統(tǒng)棧本來就是不對(duì)齊的呢?通過中斷來做任務(wù)切換的情況下,中斷控制器并不會(huì)對(duì)系統(tǒng)棧進(jìn)行調(diào)整,怎么辦?其實(shí)這也不用擔(dān)心,以μC/OS-II為例,在cortex-m3上通常使用PendSV異常來做任務(wù)切換,即將OSCtxSw以及OSIntCtxSw都設(shè)為僅完成PendSV異常觸發(fā)功能,然后在PendSV異常服務(wù)程序中進(jìn)行任務(wù)切換。由于上電時(shí)刻系統(tǒng)處于特權(quán)級(jí)模式,只要我們保證從上電開始到第一次系統(tǒng)調(diào)用,使用的棧都是系統(tǒng)棧MSP就可以了,這樣即使第一次要進(jìn)入任務(wù)切換時(shí)MSP不對(duì)齊,中斷向量控制器也會(huì)給調(diào)整為8字節(jié)對(duì)齊狀態(tài),雖然這個(gè)第一次任務(wù)切換后除了中斷再也不會(huì)使用MSP,但只要我們同時(shí)保證所有匯編部分都不會(huì)破壞8字節(jié)對(duì)齊規(guī)約,那么從此以后MSP都會(huì)是8字節(jié)對(duì)齊的。 六、關(guān)于ALIGN屬性 與 PRESERVE8偽指令 在CORTEX M3芯片的啟動(dòng)代碼中,這兩個(gè)偽指令并非必不可少,可以不要這兩個(gè)偽指令。但是有了這兩個(gè)偽指令,可以在確保遵守AAPCS的道路上加一道保險(xiǎn),使得AAPCS棧使用約定的遵守在實(shí)際編程時(shí)變得稍微容易點(diǎn)。 當(dāng)在段定義頭(即AREA偽指令的相關(guān)代碼)當(dāng)中使用ALIGN=?時(shí),ALIGN屬性的作用為設(shè)定該代碼段或數(shù)據(jù)段的首址的對(duì)齊位置,例如ALIGN=3就表示,該段首址將被安排在2^3=8字節(jié)對(duì)齊處。需要注意的是,除了AREA的ALIGN屬性,還有一個(gè)同名的ALIGN指令,ALIGN指令使用在段內(nèi)部的,用來調(diào)整ALIGN指令下一條命令或數(shù)據(jù)的對(duì)齊位置。 而PRESERVE8偽指令并不會(huì)對(duì)棧進(jìn)行任何修改。PRESERVE8偽指令的使用有四種方法,分別如下,其中1、2的用法是等價(jià)的: 1. PRESERVE8 2. PRESERVE8 {TRUE} 3. PRESERVE8 {FALSE} 如果不寫,那么由編譯器來決定在編譯過程中將匯編文件標(biāo)識(shí)為PRES8屬性還是~PRES8屬性(也即加還是不加該偽指令),但經(jīng)過實(shí)驗(yàn),發(fā)現(xiàn)編譯器在加不加這條偽指令上表現(xiàn)的并不完全可靠。。。所以最好明確的加上是 PRESERVE8 {TRUE}還是PRESERVE8 {FALSE}。那么這條偽指令起什么作用呢? 如果你想要告訴匯編器說:“在我這個(gè)匯編文件中保證棧的8字節(jié)對(duì)齊,我這個(gè)文件對(duì)棧的任何時(shí)刻的任何操作都是8字節(jié)對(duì)齊的”,那么你就把PRESERVE8偽指令用在匯編文件中,用以向匯編器通知前面你的保證內(nèi)容。匯編器就知道你這個(gè)匯編文件是8字節(jié)對(duì)齊靠譜選手,將該文件標(biāo)識(shí)為PRES8屬性,然后如果在你這個(gè)匯編中調(diào)用了標(biāo)示了需要8字節(jié)對(duì)齊屬性的文件中的函數(shù),連接的時(shí)候就不會(huì)報(bào)錯(cuò)。但是假如你把這個(gè)匯編文件標(biāo)示為PRESERVE8 {FALSE},然后你又在這個(gè)文件中調(diào)用了標(biāo)示了需要8字節(jié)對(duì)齊屬性的文件中的函數(shù),連接時(shí)就會(huì)給出錯(cuò)誤信息。 那么什么是標(biāo)示了需要8字節(jié)對(duì)齊屬性的文件呢?如果你的某個(gè)匯編文件,某些操作一定要棧8字節(jié)對(duì)齊才行,那么你就需要使用REQUIRE8偽指令來通知匯編器將該文件標(biāo)識(shí)為REQ8屬性,然后這個(gè)文件就是所謂的“標(biāo)示了需要8字節(jié)對(duì)齊屬性的文件”。 在文件較多,文件之間調(diào)用由繁多的情況下,通過PRESERVE8和REQUIRE8的配合,就能夠在連接期間由編譯器檢查出我們寫代碼時(shí)不小心造成的破壞8字節(jié)對(duì)齊模塊對(duì)需要8字節(jié)對(duì)齊模塊的調(diào)用(經(jīng)過實(shí)驗(yàn)發(fā)現(xiàn),匯編之間是給出警告,匯編調(diào)用C則是給出錯(cuò)誤,由于C文件中并不能直接用REQUIRE8,所以我猜編譯器將C文件都通通標(biāo)識(shí)為REQ8屬性了,所以才會(huì)出錯(cuò))。 REQUIRE8的用法同PRESERVE8。 文章來源:(mbbeetchina)
下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評(píng)論

查看更多

下載排行

本周

  1. 1TC358743XBG評(píng)估板參考手冊(cè)
  2. 1.36 MB  |  330次下載  |  免費(fèi)
  3. 2開關(guān)電源基礎(chǔ)知識(shí)
  4. 5.73 MB  |  6次下載  |  免費(fèi)
  5. 3100W短波放大電路圖
  6. 0.05 MB  |  4次下載  |  3 積分
  7. 4嵌入式linux-聊天程序設(shè)計(jì)
  8. 0.60 MB  |  3次下載  |  免費(fèi)
  9. 5基于FPGA的光纖通信系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
  10. 0.61 MB  |  2次下載  |  免費(fèi)
  11. 6基于FPGA的C8051F單片機(jī)開發(fā)板設(shè)計(jì)
  12. 0.70 MB  |  2次下載  |  免費(fèi)
  13. 751單片機(jī)窗簾控制器仿真程序
  14. 1.93 MB  |  2次下載  |  免費(fèi)
  15. 8基于51單片機(jī)的RGB調(diào)色燈程序仿真
  16. 0.86 MB  |  2次下載  |  免費(fèi)

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費(fèi)
  3. 2555集成電路應(yīng)用800例(新編版)
  4. 0.00 MB  |  33564次下載  |  免費(fèi)
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費(fèi)
  7. 4開關(guān)電源設(shè)計(jì)實(shí)例指南
  8. 未知  |  21548次下載  |  免費(fèi)
  9. 5電氣工程師手冊(cè)免費(fèi)下載(新編第二版pdf電子書)
  10. 0.00 MB  |  15349次下載  |  免費(fèi)
  11. 6數(shù)字電路基礎(chǔ)pdf(下載)
  12. 未知  |  13750次下載  |  免費(fèi)
  13. 7電子制作實(shí)例集錦 下載
  14. 未知  |  8113次下載  |  免費(fèi)
  15. 8《LED驅(qū)動(dòng)電路設(shè)計(jì)》 溫德爾著
  16. 0.00 MB  |  6653次下載  |  免費(fèi)

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費(fèi)
  3. 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
  4. 78.1 MB  |  537796次下載  |  免費(fèi)
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420026次下載  |  免費(fèi)
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費(fèi)
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費(fèi)
  11. 6電路仿真軟件multisim 10.0免費(fèi)下載
  12. 340992  |  191185次下載  |  免費(fèi)
  13. 7十天學(xué)會(huì)AVR單片機(jī)與C語言視頻教程 下載
  14. 158M  |  183278次下載  |  免費(fèi)
  15. 8proe5.0野火版下載(中文版免費(fèi)下載)
  16. 未知  |  138040次下載  |  免費(fèi)