根據調用規則ATPCS,程序一般都使用FD(FullDescending)類型的數據棧(滿棧),那么對立的就由空棧類型的數據棧。空棧是指SP操作完后指向的地址空間是未使用的,反之滿棧就是SP指向的地址已經使用了。所以對應到壓棧出站時的操作就有一點點不一樣。如果是滿棧模型則會先執行棧指針的操作后在向棧指針指向的位置寫入,反之就是先寫入在移動棧指針。這里先要明確數據傳輸語法的基本語法格式。
數據傳輸指令語法格式:
CMD{cond} Rn{!}, reglist{^}
CMD 為命令有LDM*/STM*
cond 為條件碼(可選)
Rn 為基址寄存器
{!} 可選后綴,選用后綴后表示請求回寫,即當數據傳輸完成后將最后的地址寫入到基址寄存器Rn中,不選用則基址寄存器內容不改變
{^} 該后綴表示后面的寄存器都是用戶模式下的寄存器;其次當CMD為LDM且寄存器列表中包含R5(PC)時,除正常傳輸數據還需要將SPSR復制到CPSR
LDM和STM還分為兩種情況,一種是普通數據傳送,還有一個是用於堆棧的操作時。
普通數據傳輸過程中使用IA IB DA DB區別基址的移動方向,其中A和B分別表示befor和after,I和D分別表示Increment和Decrement。
xxxIA 傳送后地址增加4
xxxIB 傳送前地址增加4
xxxDA 傳送后地址減少4
xxxDB 傳送前地址減少4
用於堆棧時用FD,ED,FA,EA來區別棧操作的方式其實就是區別一下方式是相同的。F表示Full (滿棧)而E表示Empty(空棧)。A表示Ascenging(遞增),D表示Descending(遞減)。組合起來就是:
xxxFD 滿棧遞減棧(ARM核通常時這種)
xxxFA 滿棧遞增棧
xxxED 滿棧遞減棧
xxxEA 空棧遞增棧
總結一下就是如下:
LD : load 加載,出棧操作 ST : store 存儲,入棧操作 M : multi 多次 F: full 滿棧,SP指向最后一個數據 E: empty 空棧,SP指向與最后一個數據相鄰的下一個可寫入存儲單元 D: descending 遞減,代表棧的增長方向 A: ascending 遞增,代表棧的增長方向
STMFD/LDMFD指令詳解
STMFD SP,{R0-R3} ;執行偽指令大致是: ;SP-4 = R3 ;SP-8 = R2 ;SP-12 = R1 ;SP-16 = R0 ;SP 的值未修改。 LDMFD SP,{R0-R3} ;執行偽指令大致是: ;R3 = SP-4 ;R2 = SP-8 ;R1 = SP-12 ;R0 = SP-16 ;SP 的值未修改。 STMFD SP!,{R0-R3} ;執行偽指令大致是: ;SP-=4 ;SP = R3 ;SP-=4 ;SP= R2 ;SP-=4 ;SP= R1 ;SP-=4 ;SP = R0 ;SP-=4 ;SP 的值已修改。 STMED SP!,{R0-R3} ;執行偽指令大致是: ;SP = R3 ;SP-=4 ;SP= R2 ;SP-=4 ;SP= R1 ;SP-=4 ;SP = R0 ;SP-=4 ;SP 的值已修改。
參考:
http://blog.chinaunix.net/uid-28458801-id-3791987.html
https://blog.csdn.net/stephenbruce/article/details/51151147
https://www.jianshu.com/p/aa4695b6bc26
https://blog.csdn.net/weiwei_xiaoyu/article/details/20563479