当需要存取大量的数据时,希望能同时存取多个寄存器。多寄存器传送指令可用一条指令将16个可见寄存器(R0~R15)的任意子集合存储到存储器或从存储器中读取数据到该寄存器集合中。此外,这种指令还有两个特殊用法:一是指令的一种形式可允许操作系统加载或存储用户模式寄存器来恢复或保存用户处理状态;二是它的另一种形式可作为从异常处理返回的一部分,完成从SPSR中恢复CPSR。例如,可将寄存器列表保存到堆栈,也可将寄存器列表从堆栈中恢复。
但是与单寄存器存取指令相比,多寄存器存取指令可用的寻址模式更加有限。
二进制编码
多寄存器数据存取指令的二进制编码见图
<ignore_js_op>
说明
图中,指令的二进制编码的低16位为寄存器列表,每一位对应一个可见寄存器,例如,第0位控制是否传送R0,第1位控制R1,以此类推。P、U、W和L位的作用与前面单寄存器数据存取指令的相同。
寄存器从寄存器读取连续字或连续的字块存入存储器中可通过基址寄存器和寻址模式的定义来实现。在传送每一个字之前或之后基址将增加或减少。如果W=1,即支持自动变址,则当指令完成时,基址寄存器将增加或减少所传送的字节数。
S位用于该指令的特殊用法。如果PC在读取多寄存器的寄存器列表中且S位置位,则当前模式的SPSR将被拷贝到CPSR,成为一个原子的返回和恢复状态的指令。但是注意这种形式不能在用户模式的代码中使用,因为在用户模式下没有SPSR。如果PC不在寄存器列表中且S位置位,在非用户模式执行读取和存入多寄存器指令将传送用户模式下寄存器。这使得操作系统可保存和恢复用户处理状态。
汇编格式
指令的一般形式为:
LDM/STM{<cond>}<addmode> Rn{!},<registers >
其中<addmode>指定一种寻址模式,表明地址的变化是操作执行前还是执行后,是在基址的基础上增加还是减少。“!”表示是自动变址(W=1)。<registers>是寄存器列表,用打括弧将寄存器组括起来,例如:{R0,R3-R7,PC}。寄存器列表可包含16个可见寄存器的任意集合或全部寄存器。列表中寄存器的次序是不重要的,它不影响存取的次序和指令执行后寄存器中的值,因为在这里有一个约定:编号低的寄存器在存储数据或者加载数据时对应存储器的低地址。也就是说,编号最低的寄存器保存到存储器的最低地址或从最低地址取数;其次是其他寄存器按照寄存器编号的次序保存到第一个地址后面的相邻地址或从中取数。但是一般的习惯是在列表中按递增的次序设定寄存器。
注意,如果在列表中含有R15将引起控制流的变化,因为R15是PC。
在非用户模式下,而且寄存器列表包含PC时,CPSR可由下式恢复:
LDM/STM{<cond>}<addmode> Rn{!},<registers+PC >
在非用户模式下,并且寄存器列表不得包含PC,不允许回写,则用户寄存器可通过下式保存和恢复:
LDM/STM{<cond>}<addmode> Rn,<registers-PC>
举例
LDMIA R1,{R0,R2,R5} ;R0<-mem32[R1]
;R2<-mem32[R1+4]
;R5<-mem32[R1+4]
STMDB R1!,{R3-R6,R11,R12} ;mem32[R1-4]<-R3
;mem32[R1-8]<-R4
;mem32[R1-12]<-R5
;mem32[R1-16]<-R6
;mem32[R1-20]<-R11
;mem32[R1-24]<-R12
STMED SP!{R0-R7,LR} ;现场保存,将R0-R7、LR入栈
;mem32[R13]<-R0
;mem32[R13-4]<-R1
;…
;mem32[R13-36]<-R14
;R13<-R13-36
因为存取数据项总是32位,基址地址应是字对齐的。
这类指令的一般特征是:最低的寄存器保存到最低地址或从最低地址取数;其他寄存器按照寄存器号的次序保存到第一个地址后面的相邻地址或从中取数。然而依第一个地址形成的方式会产生几种变形,而且还可以使用自动变址。
在进入子程序前,保存3个工作寄存器和返回地址:
SRMFD R13!,{R0-R2,R14}
这里假设R13已被初始化用作堆栈指针。恢复工作寄存器和返回:
LDMFD R13!{R0-R2,PC}
注意事项
如果在保存多寄存器指令的寄存器列表里指定了PC,则保存的值与体系结构实现方式有关,因此一般应避免在STM指令中指定PC。
如果在读取或存入多寄存器指令的传送列表中包含基址寄存器,则在该指令中不能使用回写模式,因为这样做的结果是不可预测的。
如果基址寄存器包含的地址不是字对齐的,则忽略最低2位。一些ARM系统可能产生异常。一些ARM系统可能产生异常。只有在V5T体系结构中,读取到PC的最低位才会更新Thumb位。
3.存储器和寄存器交换指令SWP
J交换指令把字或无符号字的读取和存入组合在一条指令中。通常都把这2个传送结合成为一个不能被外部存储器的访问分隔开的基本的存储器操作,因此本指令一般用于处理器之间或处理器与DMA控制器之间的信号量、数据结构进行互斥的访问。
二进制编码
存储器与寄存器交换指令的二进制编码见图:
说明
本指令将存储器中地址为寄存器Rn处的字或无符号字节读入寄存器Rd,又将Rm中同样类型的数据存入存储器中同样的地址。Rd和Rm可以是同一寄存器,但两者应与Rn不同。在这种情况下,寄存器和存储器中的值交换。ARM对存储器的读/写周期是分开的,但应产生一个“锁”信号,向存储器系统指明2个周期不应分离。
汇编格式
SWP{<cond>}{B} Rd,Rm,[Rn]
举例
ADR R0,SEMAPHORE
SWPB R1,R1,[R0] ;交换字节,将存储器单元[R0]中的字节数据读取到R1中,
;同时将R1中的数据写入存储器单元[R3]中
SWP R1,R2,[R3] ;交换字数据,将存储单元[R3]中的字数据读取到R1中,
;同时将R2中的数据写入到存储器单元[R3]中
注意事项
PC不能用作指令中的任何寄存器。
基址寄存器不应与源寄存器或目的寄存器相同,但是Rd和Rm可以相同。