3.2.2
通用寄存器通用寄存器包括:未分组寄存器(R0-R7)、分组寄存器(R8-R14)、程序计数器PC(R15)。(1)未分组寄存器(R0-R7)在ARM微处理器中寄存器R0-R7是未分组的,在图3.2中我们也看到,R0-R7在物理上只有一组,任何模式下使用R0-R7寄存器指的都是同一个R0-R7物理寄存器。未分组寄存器没有被系统用于特殊的用途,任何可使用通用寄存器的应用场合都可以使用未分组寄存器。在异常中断所引起的处理器模式切换时,要对未分组寄存器加以保护(入栈)以防止破坏寄存器中的数据。R0-R7在Thumb状态下也称为低组寄存器,R8-R15在Thumb状态下也称为高组寄存器。(2)分组寄存器(R8-R14)R8-R14是分组寄存器,具体访问哪个物理寄存器取决于当前的处理器模式。R8-R12这组寄存器物理上有两组,FIQ模式下使用自己专有的R8-R12,而其他模式使用同一组R8-R12寄存器。这样的结构设计有利于加快FIQ的处理速度。在ARM体系结构中,R8-R12没有任何指定的其他的用途,所以当FIQ中断到达时,可以不保存这些通用寄存器,也就是说FIQ处理程序在保存和恢复现场时可以少保存和恢复几个寄存器(R8-R12),从而提高中断处理迅速。因此FIQ模式常被用来处理一些时间紧急的任务。分组寄存器R13和R14,分别对应6个不同的物理寄存器。其中用户模式和系统模式共用一个,5中异常模式中分别有自己的R13和R14。也就是IRQ下的R13、R14与用户模式或其他4种异常模式下的R13、R14是不同的物理寄存器。R13寄存器在ARM中常用作栈指针,称为SP。因为ARM状态下没有专门的入栈和出栈指令,所以这只是一种习惯用法。也就是,并没有任何ARM指令强制使用R13作为栈指针,用户可以使用其他寄存器作为栈指针。每一种异常模式都有自己的R13,在使用是要分别对其进行初始化,以保证在相应模式下能正确的进行入栈和出栈操作。另外需要注意,在Thumb指令集中,有一些指令强制使用R13作为栈指针,如栈操作指令。R13也可以作为通用寄存器使用。R14寄存器又被称为连接寄存器(Link Register,LR),在ARM体系结构中R14的特殊用途有两种:一是用来保存子程序返回地址;二是当异常发生时,R14中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据R14的值返回到异常发生前的相应位置继续执行。当通过BL或BLX指令调用子程序时,硬件自动将子程序返回地址保存在R14寄存器中。在子程序返回时,把R14的值复制到程序计数器PC即可实现子程序返回。如,可以使用MOV
PC, LR或者BX
LR来完成子程序返回。另外,也可以在在子程序入口处使用下面的指令将LR保存到栈中。STMFD
SP!, {,LR}在子程序返回时,使用如下相应的指令做出栈操作,实现从子程序返回。LDMFD
SP!, {,PC}R14还用于从异常返回。当异常发生时,该异常模式的寄存器R14被设置成该异常模式的返回地址(R14等于异常放生时PC的值减4(或者减2))。在不同异常模式下,R14保存的值并不是异常返回的真正地址,而是有一个常数的偏移量。例如:FIQ异常可以使用SUBS
PC, LR, #4实现异常返回。R14也可以作为通用寄存器使用。(3)程序计数器(R15)ARM的寄存器R15被用为程序计算器PC。R15可以作为通用寄存器使用,但很多特殊的指令在使用R15时有些限制。当违反了这些指令的使用限制时,指令的执行结果是不可预知的。R15保存微处理器取指的地址,改变R15的值会引起程序执行顺序的改变。在ARM状态下,ARM指令是32位的、是按字对齐的,所以R15[1:0]=0;在Thumb状态下,Thumb指令是16位的、按2字节对齐的,所以R15[0]=0。由于ARM的流水线机制,指令读取的R15的值是当前正在执行的指令地址加上8个字节。读PC主要用于快速地对临近的指令或数据进行位置无关寻址,包括程序中的位置无关分支。需要注意的是,当使用指令STR或STM对R15进行保存时,保存的可能是当前指令地址加8或当前指令地址加12。到底是哪种方式,取决于芯片的具体设计方式。当然,在同一个芯片中,只能采用一种方式。要么保存当前指令地址加8,要么保存当前指令地址加12。程序开发人员应尽量避免使用STR或STM指令来对R15进行操作。当不可避免要使用这种方式时,可以先通过一小段程序来确定所使用的芯片是使用哪种方式实现的。例如:SUB
R1,PC, #4
;R1中存放STR指令地址STR
PC,[R0]
;用STR指令将PC保存到R0指向的地址单元中,
;PC=STR指令地址+偏移量(偏移量为8或者12)。LDR
R0,[R0]
;读取STR指令地址+偏移量的值SUB
R0,R0,R1
; STR指令地址+偏移量的值减去STR指令的地址,
;得到偏移量值(8或者12)。当用指令修改R15的值时,如果修改成功,它将使程序跳转到该地址执行。因为ARM指令是字对齐的,所以写入R15的地址值应满足BIT[1:0]=0b00,具体的规则根据ARM版本的不同也有所不同:l
对于ARM版本3以及更低的版本,写入R15的地址值bit[1:0]被忽略,即写入R15的地址值将与0xFFFFFFFC做与操作。l
对于ARM版本4以及更高的版本,程序必须保证写入R15寄存器的地址值的bit[1:0]为0b00,否则将会产生不可预知的结果。l
对于Thumb指令集来说,指令是半字对齐的。处理器将忽略R15[0],即写入R15寄存器的值在写入前要先和0XFFFFFFFE做与操作。有些指令对R15的操作有特殊的要求。比如,指令BX利用寄存器BIT[0]来确定需要跳转到的子程序是ARM状态还是Thumb状态。 3.2.3
程序状态寄存器当前程序状态寄存器CPSR(Current Program Status Register)可以在任何微处理器模式下被访问,它包含条件码标志、中断控制、当前处理器模式以及其他状态和控制信息。图3.3显示CPSR的各个位含义。

图3.3
程序状态寄存器
|