0
前述
在日常編寫Bug的時候,不知是否經過這樣一種情況,我明明只是在函數中多加了一個臨時變量,結果程序執行就異常了。我屮艸芔茻...
我碰到的一次情況是該函數程序訪問數組本來就越界了,但是還能正常工作,就因為加了一個臨時變量,棧內容發生了變化,就因為一個變量的偏移,在對數組操作時剛好設置給了LR寄存器,導致子程序返回有誤,程序執行邏輯異常。
上述的這種問題,常規調試是無法發現的,甚至問題出現在那個地方都定位不到。
都說彙編代碼時程序員的最後一根救命稻草。接下來就來介紹一下彙編中最常用的STM/LDM指令。
LDM翻譯為Load Multiple registers.
STM翻譯為Store Multiple registers.
語法格式如下:
LDM{addr_mode}{cond} Rn{!}, reglist{^}
STM{addr_mode}{cond} Rn{!}, reglist{^}1
addr_mode
LDM 和 STM 指令提供了四種不同的尋址方式。尋址模式決定基址寄存器的行為,並在下表中說明。
- I為Increment(遞增)
- D為Decrement (遞減)
- B為Before
- A為After
模式決定了基址寄存器是在執行指令前地址增減還是指令執行後增減。
LDM 和 STM 指令也可用於從堆棧中壓入或彈出寄存器。
- D為Descending(降序)。
- A是Ascending (升序)單詞首字母。
- F是單詞Full 首字母,意思為當前的棧指針指向是最後一個入棧的元素。
- E是單詞Empty單詞首字母,意思是當前的棧指針指向的是下一個空閑空間。
這四組描述的是棧的生長方向是降序還是升序,以及當前棧指針指向是棧中最後一項元素還是空閑空間。
2
Cond
條件指令僅在程序狀態寄存器中的條件標誌匹配時執行。例如,BEQ(帶有 EQ 條件的 B 指令)僅在設置 Z 標誌時分支。如果 {cond} 字段為空,則始終執行指令。
3
Rn
Rn是基址寄存器,ARM 寄存器保存傳輸的初始地址。Rn 不能是 PC。
4
!
是一個可選的後綴。如果 !存在時,將最終地址寫回 Rn。
5
reglist
是要加載的一個或多個寄存器的列表,用大括號括起來。它可以包含寄存器範圍。如果它包含多個寄存器或寄存器範圍,則必須用逗號分隔。寄存器 R0 到 R15 (PC) 的任意組合都可以在 ARM 狀態下傳輸,但在 Thumb 狀態下有一些限制。
6
^
是可選後綴,僅在 ARM 狀態下可用。您不得在用戶模式或系統模式下使用它。數據被傳入或傳出用戶模式寄存器,而不是當前模式寄存器。
7
示例
最後看一個示例,如下圖,在右上角有一個行彙編指令。
STMDB R13!,{R4-R6,R14}注意,當執行到這一行代碼時,棧指針(SP)的地址是0x3FFFC00,上圖已經為執行後的結果。
逐步分析,STM為存貯指令,DB解釋為當前棧地址是降序的且當前的棧指針指向棧中的最後一個元素。所以指令執行之前一定要讓SP指向下一個空閑地址,執行完之後再將SP地址遞減。
因為有!所以該指令執行完之後需要將最後的地址寫回給Rn(即SP)。所以最後SP的地址為0x3fffbf0
注意,因為棧地址是遞減的,所以最先入棧的是R14,從右往左。如果棧是遞增的則反之。
你 學廢了嗎?
END
嵌入式物聯網需要學的東西真的非常多,千萬不要學錯了路線和內容,導致工資要不上去!
無償分享大家一個資料包,差不多150多G。裡面學習內容、面經、項目都比較新也比較全!某魚上買估計至少要好幾十。
點擊這裡找小助理0元領取:
轉載自:typedef
文章來源於ARM彙編STM&LDM知多少
原文鏈接:https://mp.weixin.qq.com/s/FZaBy_HAkRlg-TlGicWJuw