arm寄存器介绍

寄存器介绍

      首先,寄存器是什么?如果你从事过嵌入式开发,写过单片机程序、写过linux内核驱动、焊过电路板画过PCB,那么你肯定对寄存器不陌生,因为在单片机程序和内核驱动程序中,你需要经常与寄存器直接打交道(当然排除只用固件库开发的模式,比如stm32就提供了寄存器开发和固件库开发两种模式)。如果你是上层开发人员,寄存器对你而言可能仅仅是一个概念。

      程序在被编译为机器码执行时,实际上是一个状态机状态状态转移的过程,这个过程中会有很多中间状态和结果,那么寄存器就是用来暂存这些中间状态的,或者说是用来暂存程序运行过程中的指令和数据。那么寄存器位于哪里呢?内存中吗?不是,寄存器是一个实实在在的物理硬件,它位于处理器内部,因此不同处理器架构,它们的寄存器数量和功能是不尽相同的。内存也可以用来暂存指令和数据,那么寄存器和内存有什么区别呢?那就是速度,虽然内存的读写速度比磁盘快很多,但是它和cpu的运行速度相比还是相差甚远(不是一个数量级),因此为了重发发挥cpu的运算潜力,cpu核心都是直接与寄存打交道,而不是与内存。下面这张图是一个简单arm系列单片机内核架构图(说起简单是因为它没有mmu而且主频较低,无法运行像linux之类的操作系统)。

                     

                                                       图 1  ARM Cortext M3/M4 架构图

ARM寄存器

                    

                                                             图2  ARM寄存器

     在ARM处理器的7种模式下都有一组对应的寄存器组。在任意时刻,可见的寄存器组包括15个通用寄存器R0~R14、一个或两个状态寄存器和PC。在所有的寄存器中,有些是各种模式下共用的同一个物理寄存器,有些是各种模式自己独立拥有的物理寄存器。详细如图2所示。
     通用寄存器通常又可以分为下面3类。
      未备份寄存器:包括R0~R7。
      备份寄存器:包括R8~R14。
      程序计数器PC:即R15。

未备份寄存器R0~R7

      对于每个未备份寄存器来说,在所有的处理器模式下指的都是同一个物理寄存器,在异常中断造成处理器模式切换时,由于不同的处理器模式使用相同的物理寄存器,可能造成寄存器中数据被破坏。未备份寄存器没有被系统用于特别的用途,任何可采用通用寄存器的应用场合都可以使用未备份寄存器。
 

备份寄存器R8~R14

      备份寄存器中的每个寄存器对应于两个不同的物理寄存器。例如,当使用快速中断模式下的寄存器时,寄存器R8和寄存器R9分别记做R8_fiq和R9_fiq,当使用用户模式下的寄存器时,寄存器R8和寄存器R9分别记做R8_usr和R9_usr等。在这两种情况下使用的是不同的物理寄存器,系统没有将这几个寄存器用于任何的特殊用途。中断处理非常简单,仅仅使用R8~R14寄存器时,FIQ处理程序可以不必执行保存和恢复中断现场的指令,从而可以使中断处理过程很迅速。
      对于备份寄存器R13、R14来说,每个寄存器对应于6个不同的物理寄存器,其中的一个是用户模式和系统模式共用的,另外的5个则对应于其他5种处理器模式,采用下面的方法来标识。
      R13_mode,其中mode是usr、svc、abt、und、irq和fiq的一种。
      R13通常用做堆栈指针每一种模式都拥有自己的物理R13。程序初始化R13,使其指向该模式专用的栈地址。当进入该模式时,可以将需要使用的寄存器保存在R13所指的栈中,当退出该模式时,将保存在R13所指的栈中的寄存器值弹出。这样就实现了程序的现场保护
     寄存器R14又被称为连接寄存器(LR),在ARM中有下面两种特殊用途。
      ① 每一种处理器模式在自己的物理R14中存放当前子程序的返回地址。当通过BL或者BLX指令调用子程序时R14被设置成该子程序的返回地址。在子程序中,当把R14的值复制到程序计数器PC中时,就实现了子程序返回。具体的汇编调用方式是:MOV PC,LR或BX LR。
      ② 当发生异常中断的时候,该模式下的特定物理R14被设置成该异常模式将要返回的地址
      3)程序计数器PC→R15
      由于ARM处理器采用的是流水线机制,当正确地读取了PC值时,该值为当前指令地址值加8字节。也就是说对于ARM指令来说,PC指向当前指令的下两条指令的地址,由于ARM指令是字对齐的,PC值的第0位和第1位总是为0。
      当成功地向PC写入一个地址数值时,程序将跳转到该地址执行。
      在ARM系统进行代码级调试时对于R13、R14及PC的跟踪很重要,可以用来分析系统堆栈及PC指针值的变化等。

 

程序状态寄存器

      CPSR(当前程序状态寄存器)可以在任何处理器模式下被访问每一种模式下都有一个专用的物理状态寄存器,称为SPSR(备份程序状态寄存器)。当特定的异常中断发生时,这个寄存器用于存放当前程序状态寄存器的内容。在异常退出时,可以用SPSR中保存的值来恢复CPSR。CPSR的具体格式如下。

31

30

29

28

27

26

7

6

5

4

3

21

0

N

Z

C

V

Q

DNMLRAZ

I

F

I

M4

M3

M

M0

1)条件标志位
      N(Negative)、Z(Zero)、C(Carry)及V(oVerflow)统称为条件标志位。大部分的ARM指令可以依据CPSR中的这些标志位来选择性地执行。各条件标志位的具体含义,如表1-4所示。
     表1 4  CPSR标志位含义

标  志  位

含    义

N

本位设置成当前指令运算结果的bit[31]的值

当两个补码表示的有符号整数运算时,N=1表示运算的结果为负数,N=0 表示结果为正数或零

Z

Z=1表示运算结果是0,Z=0表示运算结果不是零

对于CMP指令,Z=1表示进行比较的两个数大小相等

C

在加法指令中(包括比较指令CMN),结果产生进位了,则C=1,表示无符号数运算发生上溢出,其他情况下C=0

在减法指令中(包括比较指令CMP),结果产生借位了,则C=0,表示无符号数运算发生下溢出,其他情况下C=1

对于包含移位操作的非加/减法运算指令,C中包含最后一次被溢出的位的数值,对于其他非加/减法运算指令,C位的值通常不受影响

V

对于加/减法运算指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1表示符号位溢出

其他的指令通常不影响V位

2)Q标志位
      在ARM v5的E系列处理器中,CPSR的bit[27]称为Q标志位,主要用于指示增强的DSP指令是否发生了溢出,同样的,SPSR的bit[27]也称为Q标志位,用于在异常中断发生时保存和恢复CPSR中的Q标志位。
3)CPSR中的控制位
      CPSR的低8位I、F、T及M[4:0]统称为控制位,当异常中断发生时这些位发生变化。在特权级的处理器模式下,软件可以修改这些控制位。
① I中断禁止位
    当I=1时禁止IRQ中断。
    当F=1时禁止FIQ中断。
    通常一旦进入中断服务程序可以通过置位I和F来禁止中断,但是在本中断服务程序退出前必须恢复原来I、F位的值
② T控制位

      用来控制指令执行的状态,即说明本指令是ARM指令还是Thumb指令。对于不同版本的ARM处理器,T控制位的含义是有些不同的。
      对于ARM v3及更低的版本和ARM v4的非T系列版本的处理器,没有ARM和Thumb指令的切换,所以T始终为0。
      对于ARM v4及更高版本的T系列处理器,T控制位含义如下。
      当T=0,表示执行ARM指令。
      当T=1,表示执行Thumb指令。
      对于ARM v5及更高的版本的非T系列处理器,T控制位的含义如下。
      当T=0表示执行ARM指令。
      当T=1表示强制下一条执行的指令产生为定义指令中断。
③ M 控制位
      控制位M[4:0]称为处理器模式标识位,具体说明如表1-5所示。
表1 5   CPSR 处理器模式位

M[4:0]

处理器模式

可访问的寄存器

0b10000

User

PC,R14~R0,CPSR

0b10001

FIQ

PC,R14_fiq~R8_fiq,R7~R0,CPSR,SPSR_fiq

0b10010

IRQ

PC,R14_irq~R13_irq,R12~R0,CPSR,SPSR_irq

0b10011

Supervisor

PC,R14_svc~R13_svc,R12~R0,CPSR,SPSR_svc

0b10111

Abort

PC,R14_abt~R13_abt,R12~R0,CPSR,SPSR_abt

0b11011

Undefined

PC,R14_und~R13_und,R12~R0,CPSR,SPSR_und

0b11111

System

PC,R14~R0,CPSR(ARM v4及更高版本)

     CPSR的其他位用于将来ARM版本的扩展,程序可以先不操作这些位。

为什么要懂寄存器

      不懂寄存器依然可以写出很好的程序,但是懂寄存器有助于你写出更好的程序,为什么呢?因为寄存器经常被各种编译器拿来做性能优化,比如参数传递等。同时,glibc库和linux内核启动代码中有着大量的汇编代码来操作寄存器,因此要想研究系统调用原理和linux内核,寄存器绝对是少不了的必备知识。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值