嵌入式:ARM多寄存器存取指令详解

时间:2022-12-22 10:56:14

多寄存器传送指令可以用一条指令将16个可见寄存器(R0~R15)的任意子集合(或全部)存储到存储器或从存储器中读取数据到该寄存器集合中。如:可将寄存器列表保存到堆栈,也可将寄存器列表从堆栈中恢复。 这种指令有两个特殊用法: (1)允许操作系统加载或存储用户模式寄存器来保护或恢复用户处理状态。 (2)作为异常处理返回的一部分,完成从SPSR中恢复CPSR。 这种指令与单寄存器存取指令相比,多寄存器数据存取可用的寻址模式更加有限。

多寄存器存取指令的二进制编码

嵌入式:ARM多寄存器存取指令详解

二进制编码的低16位对应R15~R0的寄存器列表。

存储器地址可以通过基址寄存器Rn和寻址模式的定义来实现,在传送一个字前或后基址将增加或减少。如果W=1,则支持自动变址,则当指令完成时,基址寄存器将增加或减少所传送的字节数。

S位是该指令的特殊用法。如果PC在读取多寄存器的寄存器列表中,且S位置位,则当前模式的SPSR将被拷贝到CPSR。但这种指令不能用在用户模式下,因为用户模式下没有SPSR。如果PC不在寄存器列表中且S位置位,在非用户模式下,执行读取和存入多寄存器指令将传送用户模式下寄存器(虽然使用的是当前模式的基址寄存器),这使得操作系统可以保存和恢复用户处理状态。

指令汇编格式

LDM/STM{<cond>}<add mode>  Rn{!},  <registers>

这里​​<add mode>​​指定一种寻址模式,表明地址的变化是操作前还是执行后,是在基址基础上增加还是减少。 “!”表示是自动变址(W=1)。

​<registers>​​是寄存器列表,用大括号将寄存器组括起来。列表中的寄存器的次序是不重要的,它不影响存取的次序和指令执行后寄存器的值,因为这里有个约定:编号低的寄存器在存储数据或者加载数据时,对应于存储器的低地址。也就是说,编号最低的寄存器保存到最低地址,或从最低地址取数。其他依次递增。

举例

LDMIA  R1,{R0,R2,R5};R0←mem32[R1]
;R2←mem32[R1+4]
;R5←mem32[R1+8]
STMDB R1!,{R3-R6,R11,R12} ;R12→mem32[R1-4]
;R11→mem32[R1-8]
;R6→mem32[R1-12]
;R5→mem32[R1-16]
;R4→mem32[R1-20]
;R3→mem32[R1-24]
;R1 ← R1-24
STMED SP!,{R0-R7,LR} ;现场保存,将R0~R7、LR入栈
;R14→mem32[R13]
;R7→mem32[R13-4]
;……
;R0→mem32[R13-32]
;R13 ← R13-36

注意事项

  • 如果在保存多寄存器指令的寄存器列表中指定了PC ,则保存的值与体系结构实现方式有关,因此,一般应避免在STM指令中指定PC。
  • 如果在读取或存入多寄存器指令的传送列表中包含基址寄存器,则在该指令中不能使用回写模式,因为这样做的结果是不可预测的。
  • 如果基址寄存器包含的地址不是字对齐的,则忽略最低2位。一些ARM系统则可能产生异常。

参考文献:

孟祥莲.嵌入式系统原理及应用教程(第2版)[M].北京:清华大学出版社,2017.