数据传送指令之:多寄存器Load/Store内存访问指令
5.4.4 数据传送指令应用
LDM/STM批量加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDM为加载多个寄存器,STM为存储多个寄存器。允许一条指令传送16个寄存器的任何子集或所有寄存器。指令格式如下:
LDM{cond}模式> Rn{!},regist{ˆ}
STM{cond}模式> Rn{!},regist{ˆ}
LDM/STM的主要用途有现场保护、数据复制和参数传递等。其模式有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},寄存器排列由小到大排列;“ˆ”后缀不允许在用户模式下,只能在系统模式下使用。若在LDM指令用寄存器列表中包含有PC时使用,那么除了正常的多寄存器传送外,将SPSR拷贝到CPSR中,这可用于异常处理返回;使用“ˆ”后缀进行数据传送且寄存器列表不包含PC时,加载/存储的是用户模式寄存器,而不是当前模式寄存器。
注意 | 地址对齐问题,在这些指令中,忽略地址位[1:0]。 批量加载/存储指令举例如下。 |
LDMIA r0!,{r3~r9} ;加载r0指向的地址上的多字数据,保存到r3~r9中,r0值更新
STMIA r1!,{r3~r9} ;将r3~r9的数据存储到r1指向的地址上,r1值更新
STMFD SP!,{r0~r7,LR} ;现场保存,将r0~r7、LR入栈
LDMFD SP!,{r0~r7,PC}ˆ ;恢复现场,异常处理返回
在进行数据复制时,先设置好源数据指针,然后使用块拷贝寻址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB进行读取和存储。而进行堆栈操作时,则要先设置堆栈指针,一般使用SP然后使用堆栈寻址指令STMFD/LDMFD、STMED/LDMED、STMEA/LDMEA实现堆栈操作。
多寄存器传送指令如例5.3所示。其中r1为指令执行前的基址寄存器,r1’则为指令执行后的基址寄存器。
【例5.3】多寄存器传送指令示意。
(1)STMIA r1,{r5~r7}
(2)STMIB r1!,{r5~r7}
(3)STMDA r1!,{r5~r7}
(4)STMDB r1!,{r5~r7}
数据是存储在基址寄存器的地址之上还是之下,地址是存储第一个值之前还是之后、增加还是减少,如表5.3所示。
表5.3 多寄存器Load/Store内存访问指令映射
向 上 生 长 | 向 下 生 长 | ||||
满 | 空 | 满 | 空 | ||
增加 | 之前 | STMIB | LDMIB | ||
STMFA | LDMED | ||||
之后 | STMIA | LDMIA | |||
STMEA | LDMFD | ||||
增加 | 之前 | LDMDB | STMDB | ||
LDMEA | STMFD | ||||
之后 | LDMDA | STMDA | |||
LDMFA | STMED |
【例5.4】使用LDM/STM进行数据复制。
LDR r0,=SrcData ;设置源数据地址
LDR r1,=DstData ;设置目标地址
LDMIA r0,{r2~r9} ;加载8字数据到寄存器r2~r9
STMIA r1,{r2~r9} ;存储寄存器r2~r9到目标地址
【例5.5】使用LDM/STM进行现场寄存器保护,常在子程序或异常处理使用。
SENDBYTE
STMFD SP!,{r0~r7,LR} ;寄存器压栈保护
…….
BL DELAY ;调用DELAY子程序
…….
LDMFD SP!,{r0~r7,PC} ;恢复寄存器,并返回
评论