ARM寄存器结构小记

部分内容摘自Failwest大牛的《0day安全》,侵删

ARM处理器共有37个寄存器,被分为若干个组,这些寄存器包括:

  • 31个通用寄存器,包括未分组寄存器R0-R7、分组寄存器R8-R14和程序计数器( PC 指针),均为32位的寄存器。
  • 6个状态寄存器,包括程序状态寄存器 CPSR 和5个物理状态寄存器 SPSR (用以异常发生时保存 CPSR 的值,异常退出时恢复 CPSR )。 这些状态寄存器用以标识 CPU 的工作状态及程序的运行状态,均为32位。

具体如下表所示:

用户模式 usr系统模式 sys特权模式 svc中止模式 abt未定义指令模式 und外部中断模式 irq快速中断模式 fiq
R0R0R0R0R0R0R0
R1R1R1R1R1R1R1
R2R2R2R2R2R2R2
R3R3R3R3R3R3R3
R4R4R4R4R4R4R4
R5R5R5R5R5R5R5
R6R6R6R6R6R6R6
R8R8R8R8R8R8R8_fiq
R9R9R9R9R9R9R9_fiq
R10R10R10R10R10R10R10_fiq
R11R11R11R11R11R11R11_fiq
R12R12R12R12R12R12R12_fiq
R13(SP)R13R13_svcR13_abtR13_undR13_inqR13_fiq
R14(LR)R14R14_svcR14_abtR14_undR14_inqR14_fiq
PC(R15)PCPCPCPCPCPC
CPSRCPSRCPSRCPSRCPSRCPSRCPSR
SPSR_svcSPSR_abtSPSR_undSPSR_inqSPSR_fiq

未分组寄存器 R0 - R7:

对于未分组寄存器,它们没有被系统用于特别的用途,因此任何可采用通用寄存器的应用场合都可以使用未分组寄存器。
但需要注意一点,未分组寄存器不会因为处理器模式的改变而更改指向的寄存器,因此在所有的处理器模式下未分组寄存器都指向同一个寄存器,当中断或异常处理造成处理器模式转换的时候,由于不同的处理器模式使用了相同的物理寄存器,这就有可能造成寄存器中的数据被破坏。
(关于工作模式和状态可以移步至我做的另一个总结小记: http://blog.youkuaiyun.com/qq_19550513/article/details/62038580

分组寄存器 R8 - R14

对于分组寄存器,它们每一次所访问的物理寄存器和处理器当前的运行模式有关。例如在快速中断模式 fiq下R8-R12访问寄存器 R8_fiq-R12_fiq ;而在其他模式下又访问 R8_usr-R12_usr 。因此它们每个对应着两个不同的寄存器。

对于R13(SP)、R14(LR)来说,每个寄存器对应着6个不同的物理寄存器,其中的一个是用户模式与系统模式共用,另外5个物理寄存器对应于其他5种不同的运行模式。采用以下的记号来区分不同的物理寄存器:
R13_< mode >
R14_< mode >
其中,mode为以下几种模式之一:usr、fiq、irq、svc、abt、und。

R13(SP)

寄存器 R13 在 ARM 指令还有着一个非常重要的作用,通常他被用作堆栈指针,当然这只是一种习惯用法,用户也可以使用其他的寄存器作为堆栈指针,但在Thumb指令集中,某些指令强制性地要求使用R13作为堆栈指针。

由于处理器的每种运行模式均有自己福利的物理寄存器R13,使其指向该运行模式下的栈空间,这样,当程序的运行进入异常模式时,可以将需要保护的寄存器放入R13所指向的堆栈,而当程序从异常模式返回时,则从对应的堆栈恢复,采用这种方式可以保证异常发生后程序的正常执行。

R14(LR)

R14 也称作子程序连接寄存器(Subroutine Link Register)或连接寄存器 LR 。当执行 BL 子程序调用指令时,R14 中得到 R15 (程序计数器PC)的备份。

   0x00008d68 <+44>:    bl  0x8cd4 <func>
   0x00008d6c <+48>:    ...
   0x00008d70 <+52>:    ...

通常情况下,在汇编代码中不会出现 R14 中产生 PC 备份的指令语句。可以简单的理解为在执行调用的同时,将当前 PC 的指向的值 0x00008d70 减去一条指令的长度,这里是ARM工作状态,指令长度为 0x00000004,并交由R14保存。减去一条指令的原因很简单,不减的话返回的时候中间 0x00008d6c 处的那条指令就被跳过了。:-p

(当前执行的是 0x00008d68 处的指令,0x00008d6c 处的指令处于译码阶段,0x00008d70 的指令处于取指阶段,PC总是指向取指阶段的指令。关于 ARM 处理器的流水线机制和 PC 指向的值 详见下文。)
其他情况下,R14 也可以用作通用寄存器。与之类似,当发生中断或异常时,对应的分组寄存器 R14_svc、R14_irq、R14_fiq、R14_abt 和 R14_und 用来保存 R15 的返回值。

每一种处理器模式在自己的物理 R14 中存放当前子程序的返回地址。当通过BL、BX 等指令调用子程序时,R14就被设置成该子程序的返回地址。例如有汇编指令如下:

  • 执行以下任意一条指令:
MOV PC,LR
BX LR
  • 在子程序入口处使用以下指令将R14存入堆栈:
STMFD SP!,{<Regs>,LR}
  • 对应的,使用以下指令可以完成子程序返回:
LDMFD SP!,{<Regs>,PC}

当发生异常中断的时候,该模式下的特定物理R14被设置成该异常模式将要返回的地址。

R15(PC)

介绍R15之前先简单了解一下 ARM 处理器的是流水线机制。 ARM7 处理器采用3级流水线来增加处理器指令流的速度,能提供 0.9MIPS/MHz 的指令处理速度。

ARM7 的流水线有3个阶段,因此指令分3个阶段执行。
⑴ 取指从存储器装载一条指令
⑵ 译码识别将要被执行的指令
⑶ 执行处理指令并将结果写会寄存器

对于x86处理器来说,只有完成一条指令的读取和执行后,才会执行下一条指令。这样, PC 始终指向的正在“执行”的指令。
而对于 ARM7 来说因为是3级流水线,所以把指令的处理分为了上面所述的3个阶段。所以处理时实际是这样的: ARM 正在执行第1条指令的同时对第2条指令进行译码,并将第3条指令从存储器中取出。因此 ARM7 流水线只有在取第4条指令时,第1条指令才算完成执行。继而 ARM 的 PC 寄存器永远指向当前执行的指令后的第二条指令,即处于取指阶段的指令。

另外,在ARM状态下,最低的两位[1:0]为0,其他位[31:2]用于保存PC;在Thumb状态下,最低位[0]为0,其他位 [31:1]用于保存PC;所以 R15(PC)虽然可以用作通用寄存器,但是有一些指令在使用R15时有一些特殊限制,当违反了这些限制时,程序的执行结果是未知的。

R16(CPSR)

寄存器R16用作当前程序状态寄存器 CPSR (Current Program Status Register),可在任何运行模式下被访问,它包括条件标志位、中断禁止位、当前处理器模式标志位,以及其他一些相关的控制和状态位。

每一种运行模式下又都有一个专用的物理状态寄存器,称为备份的程序状态寄存器 SPSR (Saved Program Status Register),当异常发生时, SPSR 用于保存 CPSR 的当前值,从异常退出时则可由 SPSR 来恢复 CPSR 。

由于用户模式和系统模式不属于异常模式,他们没有 SPSR ,当在这两种模式下访问 SPSR ,结果是未知的。

执行条件标志位

ARM 的执行条件与 x86 下面的标志位有些类似,系统通过对这些标志位的判断来确定是否满足执行条件。几乎所有的 ARM 指令都包含一个4位的条件码,位于指令的最高4位。条件码共有16种,每种条件码可用两个字符表示,这两个字符可以添加在指令助记符的后面和指令同时使用。

例如,跳转指令 B 可以加上后缀 EQ 变成 BEQ 表示“相同则跳转”,即当 CPSR 中的Z标志置位时发生跳转。在16种条件标志码中,只有15种可以使用,如下表所示。第十六种(1111)为系统保留,暂时不能使用。

编 码条件助记符标志位含 义
0000EQZ=1相等
0001NEZ=0不相等
0010CSC=1无符号大于或等于
0011CCC=0无符号小于
0100MIN=1负值
0101PLN=0正值或 0
0110VSV=1溢出
0111VCV=0无溢出
1000HIC=1 且 Z=0无符号大于
1001LSC=0 且 Z=1无符号小于或等于
1010GEN 和 V 相同有符号大于或等于
1011LTN 和 V 不相同有符号小于
1100GTZ=0 且 N 等于 V有符号大于
1101LEZ=1 且 N 不等于 V有符号小于或等于
1110AL任意无条件执行(不推荐使用)
1111NV任意从不执行(不要使用)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值