ARM指令中STM和LDM的理解误区
STM和LDM的主要用途是現場保護、數據復制、參數傳遞等。
其模式有8種,如下:(前面4種用于數據塊的傳輸,后面4種用于堆棧操作)
(1)IA??每次傳送后地址加4
(2)IB??每次傳送前地址加4
(3)DA??每次傳送后地址減4
(4)DB??每次傳送前地址減4
(5)FD??滿遞減堆棧
(6)FA??滿遞增堆棧
(7)ED??空遞減堆棧
(8)EA??空遞增堆棧
???下面的講述對于空遞減堆棧和空遞增堆棧同樣適用.
???在堆棧操作時,經常錯誤以為使用STMFD滿遞減將寄存器壓入堆棧后,在彈出數據的時候應該使用LDMFA。
但是FD和FA僅用于指示目前操作的堆棧是何種模式(堆棧共有四種模式),FD指明目前的堆棧是滿遞減堆棧,
則數據入棧時的指令為STMFD,那么數據出棧時的指令對應的為LDMFD,而不是LDMFA。
???我們可以這樣認為STMFD等價于STMDB,LDMFD等價于STMIA
???那么,數據傳輸的順序和數據入棧的順序又是如何呢
???先來看STMFD SP!,{R1-R3}??執行的結果圖(操作之后SP指向SP')
?????????????????SP------->
???????????????????????????|R3|
???????????????????????????|R2|
?????????????????SP'------>|R1|
那么STMFD SP!,{R3,R2,R1}執行后的堆棧順序是不是剛好和上面的堆棧順序相反,實際情況時這兩個指令執行后的堆棧數據順序一樣,因為ARM編譯器會自動將STMFD SP!,{R3,R2,R1}轉換為STMFD SP!,{R0-R3}指令,也就是說,ARM編譯器默認高寄存器優先存入堆棧。即便你在指令STMFD SP!,{R3,R2,R1}中刻意“安排”了寄存器入棧順序,而在編譯時編譯器又重新做了處理,打亂了你期望的數據入棧順序。
???同理STMDB R0!,{R1-R3}和STMDB R0!,{R3,R2,R1}指令執行后數據在堆棧中的順序完全一致。
???STMFD SP!,{R1-R3}指令對應的出棧指令是LDMFD SP!,{R1-R3}(R1,R2,R3的順序任意)
****************************************************************************************************************
STMFD SP!,{R0-R7,LR} 的偽代碼如下 SP = SP - 9×4;
address = SP;?
for i = 0 to 7
Memory[address] = Ri;
address? = address + 4; Memory[address] = LR; 注意:ARM規定,sp始終是指向棧頂位置的,STM指令把寄存器列表中索引最小的寄存器存在最低地址,所以R0在最低地址,向上依次是R1,R2,...R7,LR。完成后SP指向保存R0的地址。 詳解:對于大多數的設計來說都是把棧底設置在高地址,棧頂設置在低地址,即是說上面所說的首先要sp=sp-9×4,這里理解了之后就好理解了,那么執行這條指令后,棧中的數據順序從棧底到棧頂為lr ,r7,r6,r5,r4,r3,r2,r1,r0,此時sp-->r0,即棧頂,這和堆棧的定義沒有沖突,如果sp指向的是lr的話棧就沒有用了哦,其實這里stmfd有兩種方法處理的,第一種先計算總共壓入的數據個數,直接一次更改指針sp=sp-4*(number)并從低地址向高地址存入數據,第二種就是每壓入一次就把sp=sp-1*4,同時一個一個的把數據從高地址向低地址壓入。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ****************************************************************************************************************
總結
以上是生活随笔為你收集整理的ARM指令中STM和LDM的理解误区的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: arm--ldm、stm指令解析
- 下一篇: 启动代码和Bootloader的区别和关