3.2 ARM 寄存器组织


 

3.2.1 寄存器概述

ARM微处理器有37个32位长的寄存器,其中包括30个通用寄存器,6个状态寄存器和一个程序计数器寄存器(PC)。
如图3.2所示,ARM微处理器中将这37个寄存器分成不同的组,在ARM微处理器的每种工作模式下只能使用其中一组寄存器。我们知道,ARM微处理器共有7种模式,其中用户模式和系统模式拥有物理空间上完全相同的寄存器,而其它5种异常模式都有一些自己独立的寄存器。从图上可以看出,在用户和系统模式下可以使用R0-R15和CPSR共17个寄存器;在FIQ模式下可以使用R0-R15,CPSR,CPSR共18个寄存器,其中R8-R14以及SPSR寄存器是FIQ模式专有寄存器,其它寄存器和用户模式共用相同的物理寄存器;在IRQ、SVC、Undef、Abort模式下可以使用的寄存器都是18个(R0-R15,CPSR,SPSR),其中R13,R14,CPSR是各个模式专有的,其它和用户模式共用相同的物理寄存器。
可见,ARM内核中一共有37个物理上独立的寄存器,在每一种处理器模式中只能访问一组相应的寄存器。在每组寄存器中:
R13通常用作栈指针寄存器(SP),每一种模式有自己的R13,所以允许每一种异常都有自己的栈指针。
R14用作连接或返回地址寄存器(LR),每一种模式有自己的 R14。
R15用作程序计数器(PC),用来保存读取指令的地址。
CPSR (Current Program Status Register) 存储ARM微处理器当前的状态和模式标志。
SPSR (Saved Program Status Register)异常模式下的CPSR的备份寄存器,当一个异常发生时保存当前的CPSR值。结合连接寄存器可使处理器返回先前的状态。
ARM微处理器这样组织寄存器的好处在于当各种异常发生的时候,每种异常模式都可以保存一些重要的数据,使异常处理程序完成之后返回异常前的程序时不会破坏原有的寄存器或状态。

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状态。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值