注册

ARM汇编基础(一)----寄存器篇

AArch64寄存器

Arm处理器提供通用寄存器和专用寄存器以及一些在特定模式下可用的额外寄存器。

在 AArch64状态下,有以下寄存器是可用的:
  • 31个64位通用寄存器(X0-X30),通用寄存器的低32位可用W0-W30访问。

  • 4个栈指针寄存器:SP_EL0、SP_EL1、SP_EL2、SP_EL3。

  • 3个异常链接寄存器:ELR_EL1、ELR_EL2、ELR_EL3。

  • 3个程序状态寄存器:SPSR_EL1、SPSR_EL2、SPSR_EL3。

  • 1个程序计数器。

除了状态寄存器SPSR_EL1、SPSR_EL2、SPSR_EL3是32bit,所有的寄存器均为64bit。

大多数的指令都可以操作32bit和64bit寄存器。寄存器宽度由寄存器标识符决定,W表示32bit,X表示64bit。Wn和Xn(0-30)是指同一个寄存器。当使用32位指令时,源寄存器的高32bit会被忽略,而目的寄存器的高32bit则会被置0。

没有W31或者X31寄存器,根据指令,寄存器31会被用作栈指针寄存器或者零寄存器。当用作栈指针寄存器时,可以用SP表示;当用作零寄存器时,用WZR和XZR分别表示32bit和64bit的零寄存器。

异常等级

Armv8架构定义了4个异常等级(EL0-EL3),EL3代表拥有最多执行特权的最高异常级别。当接受异常时,异常等级可以上升或者保持不变,当从异常处理中返回时,异常等级可以降低或者保持不变。

以下为常用的异常等级模式:

  • EL0

应用程序。

  • EL1

系统内核以及特殊函数。

  • EL2

虚拟机监视器(virtual machine monitor)。

  • EL3

Secure monitor.

当将异常带到更高的异常级别时,执行状态可以保持不变,或者从AArch32变到AArch64。

当返回到较低的异常级别时,执行状态可以保持不变,也可以从AArch64变更为AArch32。

执行状态的改变的唯一方式是从异常中获取或返回。在执行状态之间进行更改不可能与在AArch32状态下在A32和T32指令之间进行更改相同。

在powerup和reset上,处理器进入最高的实现异常级别。此异常级别的执行状态是实现的属性,可能由配置输入信号决定。

对于EL0以外的异常级别,执行状态由一个或多个控制寄存器配置位决定。这些位只能在更高的异常级别上设置。

对于EL0,执行状态被确定为异常返回EL0的一部分,由执行返回的异常级别控制。

LR寄存器

在AArch64状态下,当进行子函数调用时,LR寄存器保存返回地址。如果返回地址呗保存在栈上,LR寄存器也可以用作通用寄存器。LR寄存器对应的是寄存器30,与AArch32不同的是,LR寄存器和异常链接寄存器(ELRs)是不同的,因此,LR是未存储的。(ps:Unlike in AArch32 state, the LR is distinct from the Exception Link Registers (ELRs) and is therefore unbanked.【unbanked 确实不知道怎么翻译】)

异常链接寄存器有三个:ELR_EL1、ELR_EL2、ELR_EL3,与异常等级相对应。当发生异常时,目标异常级别的异常链接寄存器将存储异常处理完后要跳转到的返回地址。如果异常来自AArch32,ELR寄存器的高32bit全部置0。异常级别内的子函数调用用LR来存储子函数的返回地址。

例如,当异常等级从EL0变为EL1,返回地址将存储在ELR_EL1寄存器中。

在异常时,如果要启用用相同级别的中断,必须将ELR中的数据存储到栈中,因为在发生中断时ELR寄存器将被新的返回地址覆盖。

栈指针寄存器

在AArch64状态下,SP表示64位栈指针,SP_EL0是SP的别名。不要讲SP用作通用寄存器。

SP只能用作以下指令的操作寄存器:

  • 作为装载和存在的基本寄存器。在这种情况下,再添加任何偏移量之前,它必须是4字节对齐的,否则会发生堆栈对齐异常。

  • 作为算术指令的源寄存器或者目标寄存器,但是它不能被用作设置了条件标志的指令的目标寄存器。

  • 逻辑指令,例如为了使其地址对齐。

对于三个异常级别,都有一个单独的栈指针。在异常级别中,可以使用该异常级别下的专用栈指针,也可以使用与之相应的栈寄存器。可以使用SPSel寄存器来选择要在异常级别使用的栈指针。

栈指针的选择由附加到异常级别名称的字母t或h表示,例如EL0t或EL3h。t后缀表示异常级别使用SP_EL0, h后缀表示使用SP_ELx,其中x是当前异常级别号。EL0总是使用SP_EL0,所以不能有h后缀。

AArch64状态下预声明的核心寄存器名字

在AArch64状态中,预先声明的核心寄存器与AArch32状态中的不同。

下表显示AArch64状态下预声明的核心寄存器:

寄存器名称含义
W0-W3032-bit 通用寄存器。
X0-X3064-bit 通用寄存器。
WZR32-bit RAZ/WI寄存器,在32位指令下,寄存器31用作零寄存器时的名称。
XZR64-bit RAZ/WI寄存器,在64位指令下,寄存器31用作零寄存器时的名称。
WSP32-bit 栈指针,在32位指令下,寄存器31用作栈指针时的名称。
SP64-bit 栈指针,在64位指令下,寄存器31用作栈指针时的名称。
LR链接寄存器。和X30是同一个寄存器。

可以将寄存器名全部写成大写或小写。

请注意:

在AArch64状态下,PC寄存器不是一个通用寄存器,不能通过名称来访问他。

在AArch64下预声明的扩展寄存器

您可以将高级SIMD和浮点寄存器的名称写成大写或小写。

下表显示了AArch64状态下预先声明的扩展寄存器名:

寄存器名称含义
V0-V31128-bit矢量寄存器。
Q0-Q31128-bit标量寄存器。
D0-D3164-bit标量寄存器、双精度浮点寄存器。
S0-S3132-bit标量寄存器、单精度浮点寄存器。
H0-H3116-bit标量寄存器、半精度浮点寄存器。
B0-B318-bit标量寄存器。

AArch64状态下的PC寄存器

在AArch64状态下,PC寄存器存储的事当前执行的指令的地址。

它是由执行的指令的大小增加的,总是四个字节。

在AArch64状态下,PC寄存器不是一个通用寄存器,所以不能显式地访问它。以下类型的指令,可以隐式地读取它的值:

  • 计算PC相对地址的指令。

  • PC相关的加载指令。

  • 直接指向PC相关的标签。

  • 分支和链接指令,会将PC值存储在LR寄存器中。

唯一可以写入PC寄存器的指令类型:

  • 条件分支和无条件分支。

  • 异常产生和异常返回。

分支指令将目的地址加载到PC寄存器中。

在AArch64状态下的条件执行

在AArch64状态下,NZCV寄存器保存着N、Z、C、V标志位的值,处理器用这些标志位来决定是否执行条件指令。这些标志位被保存在NZCV寄存器的【31:28】位上。

条件标志位在任何异常等级下都可以使用MSR和MRS指令进行访问。

与A32相比,A64对条件的利用更少。例如在A64中:

  • 只有少数的指令可以set或test条件标志位。

  • 没有等效的T32 IT指令。

  • 唯一有条件执行的指令是条件分支指令B.cond,如果条件判定不成立(false),B.cond指令就像NOP指令一样。

在AArch64状态下的Q标志位

在AArch64状态下,不能对Q标识位进行读写,因为在A64中没有在通用寄存器上操作的饱和算术指令。(in A64 there are no saturating arithmetic instructions that operate on the general purpose registers.)

先进的SIMD饱和算法指令将浮点状态寄存器(FPSR)中的QC位设置为表示已经发生饱和。您可以通过Q助记符修饰符(例如SQADD)来识别这些指令。

流程状态

在AArch64状态下,没有CPSR寄存器。但是可以通过访问CPSR中不同的部分作为流程状态字段。

流程状态字段:

  • N、Z、C、V条件标识位(NZCV)。

  • 当前寄存器位宽(nRW)。

  • 栈指针选择位(SPSel)。

  • 禁止中断位(DAIF)。

  • 当前异常等级(EL)。

  • 单步处理位(SS)。

  • 非法异常返回状态位(IL)。

可以使用MSR指令写:

  • NZCV寄存器中的N、Z、C、V标识位。

  • DAIF寄存器中的禁止中断标识位。

  • 在异常等级为EL1或更高的情况下,SPSel寄存器的SP选择位。

可以使用MRS指令读:

  • NZCV寄存器中的N、Z、C、V标识位。

  • DAIF寄存器中的禁止中断标识位。

  • 在异常等级为EL1或更高的情况下,CEL寄存器的异常等级位。

  • 在异常等级为EL1或更高的情况下,SPSel寄存器的SP选择位。

当发生异常时,与当前异常级别关联的所有流程状态字段都存储在与目标异常级别关联的单个SPSR寄存器中。只能从SPSR访问SS、IL和nRW位。

AArch64下的SPSRs

保存的程序状态寄存器(SPSRs)是32位寄存器,当将异常带到使用AArch64状态的异常级别时,它存储当前异常级别的进程状态。这允许在处理异常之后恢复进程状态。

在AArch64状态下,每个异常等级都有自己的SPSR寄存器:

  • SPSR_EL1.

  • SPSR_EL2.

  • SPSR_EL3.

当发生异常时,当前异常等级的进程状态会被写入当前异常等级对应的SPSR寄存器中。当从一个异常中返回时,异常处理程序使用正在返回的异常级别的SPSR来恢复正在返回的异常级别的流程状态。

请注意

从异常返回时,首选返回地址将从与正在返回的异常级别关联的ELR恢复。

SPSRs存储了以下信息:

  • N、Z、C、V标识位。

  • D、A、I、F禁止中断位。

  • 寄存器位宽。

  • 执行模式。

  • IL和SS位。

0 个评论

要回复文章请先登录注册