ARM V8共有31个通用寄存器和2个特殊寄存器,都是64位。31个通用寄存器用X0到X30来表示,两个特殊寄存器是SP和ZR。
SP是栈指针,其内容是栈底的地址,必须满足16字节对齐的条件,否则无法使用。例如:
ADD SP, SP, #8
这种用法是错误的,因为所得到的SP不满足16字节对齐的条件,造成之后的SP不可用。
ZR是0寄存器。当用作源寄存器的时候,其值恒为0,当用作目的寄存器的时候,值被抛弃,不能保存任何值。
向量和浮点寄存器。32个寄存器,向量和浮点共用,每个128位,用V0到V31来表示。不同的记号可以表示不同的长度,B表示字节,H表示半字,S表示单字,D表示双字,Q表示四字,如图1所示。
图1 不同长度数值的描述方式
系统寄存器。系统寄存器定义了处理器的上下文,通常带有后缀_ELx,表示能访问该寄存器的最低异常级别。分别对应有读(MRS)和写(MSR)系统寄存器的指令。
MRS X0, SCTLR_EL1
MSR SCTLR_EL1, X0
LDR和STR分别从地址中读入内容到寄存器和向地址中写入寄存器的内容。默认情况下,内容的大小由寄存器的名字决定,也可以使用后缀来指定读写较小的内容。后缀B表示字节,H表示半字,W表示单字。当写入较小的内容时,默认情况下,会对内容进行0扩展,也可以使用S来进行符号位扩展。图2中,第一条指令是把内容为8A的一个字节装入X4(64位)中,并进行符号位的扩展。第二条指令是把内容为8A的一个字节装入W4(32位)中,并进行0扩展。
图2 load指令示例
按照从简单到复杂的分类方法,可以通过以下方式来指定访存指令的地址:从寄存器中获取地址;通过寄存器内容再加上偏移来获取地址;对偏移进行扩展、移位等运算之后,再与寄存器内容相加,获得地址。
LDR X0, [X1] ; 直接从寄存器X1的内容中获取地址。
LDR X0, [X1, #-8] ; X1的内容加上-8的偏移,得到地址。
LDR X0, [X1, X2] ; X!的内容和X2的内容相加得到地址。
LDR X0, [X1, W2, SXTW] ; 对W2的内容做符号扩展,再与X1的内容相加,作为地址。
LDR X0, [X1, X2, LSL #2] ; 把X2的内容左移2位,再与X1的内容相加,作为地址。
简单模式:X1的内容不会被改变,例如。
LDR X0, [X1]
LDR X0, [X1, #4]
前变址模式,X1的内容在load之前变化,例如。
LDR X0, [X1, #4]!
等价于
ADD X1, X1, #4
LDR X0, [X1]
后变址模式,X1的内容在load之后变化,例如。
LDR X0, [X1], #4
等价于
LDR X0, [X1]
ADD X1, X1, #4
浮点寄存器的Load/Store操作,通过寄存器的名称来指定写入寄存器内容的大小。B、H、S、D和Q分别代表字节、半字、单字、双字和四字。指令中不再有大小和符号扩展之类的内容,例如。
LDR D1, [X0] ; 从地址[X0]中取64位数值到D1寄存器中。
STR Q0, [X0, X1] ; 存128位的内容到地址[X0 + X1]。
支持对整型、浮点标量和向量,要求源寄存器和目的寄存器必须具有相同的宽度,例如。
LDP W3, W7, [X0] ; [X0] => W3, [X0 + 4 bytes] =>W7
STP Q0, Q1, [X4] ; Q0 => [X4], Q1=>[X4 + 16 bytes]
ARM V8之前为32位寄存器:
ARM处理器包含多少寄存器?每种模式下又有那些寄存器?这些寄存器的作用又是什么?带着这些问题我们来学习ARM寄存器吧!相信看完这篇文章后你会有所收获。
ARM处理器共有37个寄存器。
它包含31个通用寄存器和6个状态寄存器。
=======================================================================================
Usr System Supervisor Abort Undefined IRQ FIQ
----------------------------------------------------------------------------------------------------------------
R0 R0 R0 R0 R0 R0 R0
R1 R1 R1 R1 R1 R1 R1
R2 R2 R2 R2 R2 R2 R2
R3 R3 R3 R3 R3 R3 R3
R4 R4 R4 R4 R4 R4 R4
R5 R5 R5 R5 R5 R5 R5
R6 R6 R6 R6 R6 R6 R6
R7 R7 R7 R7 R7 R7 R7
R8 R8 R8 R8 R8 R8 R8_fiq
R9 R9 R9 R9 R9 R9 R9_fiq
R10 R10 R10 R10 R10 R10 R10_fiq
R11 R11 R11 R11 R11 R11 R11_fiq
R12 R12 R12 R12 R12 R12 R12_fiq
R13 R13 R13_svc R13_abt R13_und R13_irq R13_fiq
R14 R14 R14_svc R14_abt R14_und R14_irq R14_fiq
PC PC PC PC PC PC PC
CPSR CPSR CPSR CPSR CPSR CPSR CPSR
SPSR_svc SPSR_abt SPSR_und SPSR_irq SPSR_fiq
=======================================================================================
1.通用寄存器的分类:
a.未备份寄存器,包括R0-R7
对每个未备份寄存器来说,在所有的模式下都是指同一个物理寄存器(例如:Usr下的R0与FIQ下的R0是同一个寄存器)。在异常程序中断造成模式切换时,由于不同模式使用的是相同的物理寄存器。这可能导致数据遭到破坏。未备份寄存器没有被系统作为别的用途,任何场合均可采用未备份寄存器。
b.备份寄存器,包括R8-R14
对于备份寄存器R8-R12来说,除FIQ模式下其它模式均使用相同的物理寄存器。在FIQ模式下R8_fiq,R9_fiq,
R10_fiq,R11_fiq,R12_fiq。它有自己的物理寄存器。
对于R13和R14寄存器每种模式都有自己的物理寄存器(System与Usr的寄存器相同)当异常中断发生时,系统使用相应模式下的物理寄存器,从而可以避免数据遭到破坏。
R13也称为SP堆栈指针。
R14也称为LR寄存器
c.程序计数器,PC
PC寄存器存储指令地址,由于ARM采用流水机制执行指令,故PC寄存器总是存储下一条指令的地址。
由于ARM是按照字对齐故PC被读取后的值的bit[1:0]总是0b00(thumb的bit[0]是0b0)。
2.程序状态寄存器
程序状态寄存器包含当前程序状态寄存器和备份状态寄存器。
a.CPSR(程序状态寄存器)
CPSR在任何处理器模式下都可以被访问。其结构如下:
31 30 29 28 --- 7 6 - 4 3 2 1 0
N Z C V I F M4 M3 M2 M1 M0
N(Negative)、Z(Zero)、C(Carry)以及V(oVerflow)称为条件标志位。ARM指令根据CPSR的条件标志位来选择地执行。
CPSR条件标志位
=======================================================================================
条件标志位 含义
----------------------------------------------------------------------------------------------------------------
N N=1 表示运算结果为负数,N=0 表示运算结果为正数。
Z Z=1 表示运算结果为0, Z=0 表示运算结果为非零。
C C=1 表示运算结果产生了进位。
V V=1 运算结果的符号位发生了溢出。
Q 在ARMv5 E系列版本中Q=1 表示DSP指令溢出。
在ARMv5以前的版本中没有Q标志位。
=======================================================================================
以下指令会影响CPSR的条件标志位
(1)比较指令,如: CMP、CMN、TEQ、TST等。
(2)当一些算术逻辑运算的目标寄存器不是PC时,这些指令会影响CPSR的条件标志位。
(3)MSR与MRS指令可以对CPSR/SPSR进行操作。
(4)LDM指令可以将SPSR复制到CPSR中。
CPSR的控制位
=======================================================================================
控制位 含义
----------------------------------------------------------------------------------------------------------------
I I=1 禁用IRO中断
F F=1 禁用FIQ中断
T ARMv4以上T版本T=0 执行ARM指令,T=1执行Thumb指令。
ARMv5以上非T版本T=0 执行ARM指令,T=1表示下一条指令产生未定义指令中断。M[4:0] 控制处理器模式
0b10000 User
0b10001 FIQ
0b10010 IRQ
0b10011 Supervisor
0b10111 Abort
0b11011 Undefined
0b11111 System
=======================================================================================
b.SPSR(备份状态寄存器)
SPSR的结构与CPSR的结构相同,SPSR是用来备份CPSR的。
ARM V8共有31个通用寄存器和2个特殊寄存器,都是64位。31个通用寄存器用X0到X30来表示,两个特殊寄存器是SP和ZR。
SP是栈指针,其内容是栈底的地址,必须满足16字节对齐的条件,否则无法使用。例如:
ADD SP, SP, #8
这种用法是错误的,因为所得到的SP不满足16字节对齐的条件,造成之后的SP不可用。
ZR是0寄存器。当用作源寄存器的时候,其值恒为0,当用作目的寄存器的时候,值被抛弃,不能保存任何值。
向量和浮点寄存器。32个寄存器,向量和浮点共用,每个128位,用V0到V31来表示。不同的记号可以表示不同的长度,B表示字节,H表示半字,S表示单字,D表示双字,Q表示四字,如图1所示。
图1 不同长度数值的描述方式
系统寄存器。系统寄存器定义了处理器的上下文,通常带有后缀_ELx,表示能访问该寄存器的最低异常级别。分别对应有读(MRS)和写(MSR)系统寄存器的指令。
MRS X0, SCTLR_EL1
MSR SCTLR_EL1, X0
LDR和STR分别从地址中读入内容到寄存器和向地址中写入寄存器的内容。默认情况下,内容的大小由寄存器的名字决定,也可以使用后缀来指定读写较小的内容。后缀B表示字节,H表示半字,W表示单字。当写入较小的内容时,默认情况下,会对内容进行0扩展,也可以使用S来进行符号位扩展。图2中,第一条指令是把内容为8A的一个字节装入X4(64位)中,并进行符号位的扩展。第二条指令是把内容为8A的一个字节装入W4(32位)中,并进行0扩展。
图2 load指令示例
按照从简单到复杂的分类方法,可以通过以下方式来指定访存指令的地址:从寄存器中获取地址;通过寄存器内容再加上偏移来获取地址;对偏移进行扩展、移位等运算之后,再与寄存器内容相加,获得地址。
LDR X0, [X1] ; 直接从寄存器X1的内容中获取地址。
LDR X0, [X1, #-8] ; X1的内容加上-8的偏移,得到地址。
LDR X0, [X1, X2] ; X!的内容和X2的内容相加得到地址。
LDR X0, [X1, W2, SXTW] ; 对W2的内容做符号扩展,再与X1的内容相加,作为地址。
LDR X0, [X1, X2, LSL #2] ; 把X2的内容左移2位,再与X1的内容相加,作为地址。
简单模式:X1的内容不会被改变,例如。
LDR X0, [X1]
LDR X0, [X1, #4]
前变址模式,X1的内容在load之前变化,例如。
LDR X0, [X1, #4]!
等价于
ADD X1, X1, #4
LDR X0, [X1]
后变址模式,X1的内容在load之后变化,例如。
LDR X0, [X1], #4
等价于
LDR X0, [X1]
ADD X1, X1, #4
浮点寄存器的Load/Store操作,通过寄存器的名称来指定写入寄存器内容的大小。B、H、S、D和Q分别代表字节、半字、单字、双字和四字。指令中不再有大小和符号扩展之类的内容,例如。
LDR D1, [X0] ; 从地址[X0]中取64位数值到D1寄存器中。
STR Q0, [X0, X1] ; 存128位的内容到地址[X0 + X1]。
支持对整型、浮点标量和向量,要求源寄存器和目的寄存器必须具有相同的宽度,例如。
LDP W3, W7, [X0] ; [X0] => W3, [X0 + 4 bytes] =>W7
STP Q0, Q1, [X4] ; Q0 => [X4], Q1=>[X4 + 16 bytes]