ARMv8-A 提供了 31 个 64 位的通用寄存器,始终可以访问,并且可以在所有异常级别访问. 在 AArch64 执行状态下,每个寄存器(X0-X30)都是 64 位宽度. 宽度增加有助于减少大部分应用程序中的寄存器压力.
每个 64 位通用寄存器(X0 - X30)也有一个 32 位的格式(W0 - W30).
64bit_register.png
32 位 W 寄存器构成相应的 64 位 X 寄存器的下半部分. 即 W0 形成 X0 的低位字,W1 形成 X1 的低位字.
从 W 寄存器中读取时,忽略对应的 X 寄存器的高 32 位并且保持他们不变. 写入 W 寄存器将 X 寄存器的高 32 位设置为零. 因此,将 0xFFFFFFFF 写入 W0 会将 X0 设置为 0x00000000FFFFFFFF.
注意
有时 Rn 用来指定一个 ARMv8-A 寄存器. 这意味着寄存器可以是 Xn 或 Wn.
特殊寄存器
除了 31 个(X0 到 X30)个 ARMv8-A 核心寄存器之外,还有几个特殊的寄存器.
special_registers.png
注意
没有名为 X31 或 W31 的寄存器. 一些指令被编码了,以使数字 31 代表零寄存器 ZR(WZR / XZR). 还有一组受限制的指令,其中一个或多个参数被编码,以使数字 31 代表堆栈指针(SP).
名字 | 大小 | 描述 |
---|---|---|
WZR | 32 bits | 零寄存器 |
XZR | 64 bits | 零寄存器 |
WSP | 32 bits | 当前栈指针 |
SP | 64 bits | 当前栈指针 |
PC | 64 bits | 程序计数器 |
注意
64 位格式的堆栈指针不使用 X 前缀.
在 AArch64 中执行时,对于每个异常级别,异常返回状态将保存在以下专用寄存器中:
异常链接寄存器(ELR).
保存的处理器状态寄存器(SPSR).
下表按异常级别标识特殊寄存器:
EL0 | EL1 | EL2 | EL3 | |
---|---|---|---|---|
栈指针 (SP) | SP_EL0 | SP_EL1 | SP_EL2 | SP_EL3 |
异常链接寄存器 (ELR) | - | ELR_EL1 | ELR_EL2 | ELR_EL3 |
保存的处理器状态寄存器 (SPSR) | - | SPSR_EL1 | SPSR_EL2 | SPSR_EL3 |
异常级别的特殊寄存器
程序调用标准(PCS)还定义了一个专用的帧指针(FP),通过可靠地展开堆栈,它使调试和调用关系图分析变得更加容易.
零寄存器
零寄存器的名字暗示着什么.
零寄存器忽略所有对它的写操作,并且所有对它的读操作都返回 0. 您可以在大多数(但不是全部)指令中使用零寄存器.
堆栈指针
堆栈指针(SP)是一个指向堆栈顶部的寄存器. 选择使用的堆栈指针在某种程度上与 "异常" 级别是分开的. 默认情况下,发生异常时会为目标异常级别选择堆栈指针(SP_ELn). 例如,发生 EL1 异常时选择 SP_EL1. 每个异常级别都有自己的堆栈指针.
但是,当在 AArch64 中,异常级别的不是 E0 时,处理器可以使用下面中的任何一种:
与该异常级别(SP_ELn)关联的 64 位堆栈指针,或者,
与 EL0(SP_EL0)关联的堆栈指针. EL0 只能访问 SP_EL0.
SP 不能被大多数指令引用. 但是,一些算术指令,例如 ADD 指令,可以读写当前的堆栈指针来调整函数中的堆栈指针. 例如:
ADD SP, SP, #0x10 // 将SP调整为当前值之前的0x10字节
ADD SP, SP, #256 // SP = SP + 256
程序计数器
程序计数器(PC)保存当前的程序地址. 它不能被数字引用(就像通用寄存器文件的一部分一样),因此不能用作算术指令的源或目的地,或作为加载和存储指令的基址,索引或转移寄存器.
那些可以读取 PC 的指令是那些具有计算 PC 相对地址功能的指令(ADR,ADRP,字面加载和直接分支),以及在链接寄存器中存储返回地址的 "分支并链接" 指令(BL 和 BLR). 修改程序计数器的唯一方法是使用分支,异常生成和异常返回指令.
使用计算 PC 相对地址的指令读取 PC 时,读取的 PC 值是该指令的地址. 与 ARMv7-A 不同,不存在 4 或 8 字节的隐含偏移量.
异常链接寄存器(ELR)
异常链接寄存器保存要在异常后返回的地址.
原文
https://developer.arm.com/products/architecture/a-profile/docs/100878/latest/registers
来源: http://www.jianshu.com/p/b29bb8f2e727