LDM批量加載/STM批量存儲指令可以實現一組寄存器和一塊連續的內存單元之間傳輸數據。
允許一條指令傳送16個寄存器的任意子集和所有寄存器,指令格式如下:
LDM{cond} mode Rn{!}, reglist{^}
ST
M{cond} mode Rn{!}, reglist{^}
主要用途:現場保護、數據復制、參數傳送等,共有8中模式(
前面4種用於數據塊的傳輸,后面4種是堆棧操作)如下:
(1)IA:每次傳送后地址加4
(2)IB:
每次傳送前地址加4
(3)DA:
每次傳送后地址減4
(4)DB:
每次傳送前地址減4
(5)FD:滿遞減堆棧
(6)ED:空遞減堆棧
(7)FA:
滿遞增堆棧
(8)EA:空遞增
堆棧
其中:
Rn:基址寄存器,裝有傳送數據的起始地址,Rn不允許為R15;
!:表示最后的地址寫回到Rn中;
reglist:可包含多於一個寄存器范圍,用“,”隔開,如{R1,R2,R6-R9},寄存器由小到大順序排列;
^:不允許在用戶模式和系統模式下運行
根據ATPCS規則,我們一般使用FD(
Full Descending)類型的數據棧!所以經常使用的指令就有STMFD和LDMFD,
通過ARM對於棧操作和批量Load/Store指令尋址方式,可以知道指令STMFD和LDMFD的地址計算方法:
STMFD指令的尋址方式為事前遞減方式(DB)
而DB尋址方式實際內存地址為:
start_address = Rn - (Number_Of_Set_Bits_In(register_list)*4)
end_address = Rn - 4
STM指令操作的偽代碼:
if ConditionPassed(cond) then
address = start_address
for i = 0 to 15
if register_list[i] == 1
Memory[address] = Ri
address = address + 4
有上面兩個偽代碼可以得出 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即是棧頂。因為處理器是32位的ARM,所以每次壓一次棧SP就會移動4個字節(32位)。
藍色標注的SP為執行指令前的SP地址,
紅色標注的SP是執行指令后的SP地址,由此看出STMFD指令是向下壓棧的。
LDMFD指令的尋址方式為事后遞增方式(IA)
IA內存的實際地址的偽代碼
start_address = Rn
end_address = Rn + (Number_of_set_bits_in(register_list)*4) - 4
LDM指令操作的偽代碼(未考慮PC寄存器):
if ConditionPassed(cond) then
address = start_address
for i = 0 to 15
if register_list[i] == 1
Ri = Memory[address,4]
address = address + 4
所以LDMFD SP!,{R0-R7,PC}^ (;恢復現場,異常處理返回)偽代碼是:
address = SP;
for i = 0 to 7
Ri = Memory[address ,4]
address = address + 4;
SP = address;

藍色標注的SP為執行指令前的SP地址,
紅色標注的SP是執行指令后的SP地址。