01.寄存器
寄存器是什么
CPU除了有控制器、运算器还有寄存器。其中寄存器的作用是进行数据的临时存储
CPU的运算速度非常快,为了性能CPU在内部开辟一小块零食存储区域,并在进行运算时先将数据从内存复制到这一小块临时区域中,运算时就在这一小块临时存储区域内进行。
高速缓存
CPU每执行一条指令前都要从内存中将指令读取到CPU内执行。而寄存器的运行速度相比内存读写要快很多,为了性能,CPU还集成了一个高速缓存存储区域当程序在运行时,先将需要执行的指令代码以及数据复制到高速缓存中去(由操作系统完成),CPU直接从高速缓存中依次读取指令来执行。
ARM64一个寄存器64位,8个字节
一:几种寄存器
浮点寄存器
因为浮点数的存储以及运算的特殊性,CPU中专门提供浮点寄存器来处理浮点数
浮点寄存器64位:D0-D31 32位:S0-S31
向量寄存器
先在很多CPU支持向量运算(图形处理用的很多),为了支持向量计算而提供
向量寄存器:128位 V0-V31
异常状态寄存器
通用寄存器(数据地址寄存器)
ARM64拥有32个64位的通用寄存器X0-X30以及XZR(零寄存器)
为了兼容32位,所以ARM64拥有W0-W30和WZR30个32位寄存器
32位寄存器并不是独立存在的。如:W0是X0的低32位
PC寄存器:指令指针寄存器
PC寄存器里面的值就是保存的CPU接下来需要执行的指令地址
改变PC寄存器的值可以改变程序执行的流程
1.1 通用寄存器
x0-x7: 用于子程序调用时的参数传递,X0还用于返回值传递
x0 - x30
是31个通用整形寄存器。每个寄存器可以存取一个64位大小的数。 当使用 r0 - r30访问时,它就是一个64位的数。当使用 w0 - w30访问时,访问的是这些寄存器的低32位,如图:
1.2 CPSR 状态寄存器
Current Program State Register
状态寄存器是32位的
CPSR的低8位(包括I、F、T和M[4:0])称为控制位,程序无法修改,除非CPU运行于
特权模式
下,程序才能修改控制位N、Z、C、V
均为条件码标志位
。它们的内容可被算术或逻辑运算
的结果所改变,并且可以决定某条指令是否被执行,意义重大NZCV是状态寄存器的条件标志位,分别代表运算过程中产生的状态,其中:
N,
negative condition flag
,一般代表运算结果是负数1 代表结果为负数
0 代表结果为非负数
Z,
zero condition flag
, 指令结果为0时Z=1,否则Z=0C,
carry condition flag
, 一般情况下进行无符号数的运算加法运算
当运算结果产生了进位(无符号溢出)C=1否则C=0
减法运算(包括CMP)
当运算是产生了借位时(无符号溢出)则C=0,否则C=1
对于位数为N的无符号数来说其对应的二进制的最高位,即第N-1位就是他的最高有效位,而假想存在的第N位就是相对于最高有效位的更高位。
进位
我们知道,当两个数相加的时候,有可能从最高有效位向更高位进位。比如两个32位数据:
0xaaaaaaaa
+0xaaaaaaaa
,将会产生进位。但由于进位值在32位中无法保存,我们就只是简单的说这个进位值丢失了。其实CPU在运算的时候并不会丢弃这个进位值,而是记录在一个特殊的寄存器的某一位上。ARM上就用C为来记录这个进位值。
借位
当两个数据做减法的时候,有可能向更高位。比如:
0x00000000
-0x000000ff
,将产生借位,借位后相当于计算0x100000000
-0x000000ff
=0xffffff01
,由于借了一位,所以C位用来标记借位。
V,
oVerflow condition flag
有符号运算有溢出时,V=1正数 + 正数 = 负数 则 溢出
负数 + 负数 = 正数 则 溢出
正数 + 负数 不可能溢出
二:栈
后进先出 ARM64栈开口向底地址,即开辟的地址是朝底地址方向的
2.01 SP 和 FP寄存器
SP寄存器在任意时刻会保存栈顶的地址
FP寄存器也称为X29寄存器属于通用寄存器,但是在某些时候我们利用它保存栈底的地址
注意:ARM64开始,取消了32位的LDM、STM、PUSH、POP指令,取而代之的是:ldr、ldp、str、stp。在ARM64中对栈的操作是16字节对齐的
2.02 编译器会根据编译情况开辟固定的栈空间
2.03 函数调用栈
常见函数调用开辟和恢复栈空间
sub sp, sp, #0x40
拉伸0x40(64字节)空间
即sp寄存器地址减0x40
开辟了64字节空间
stp x29, x30, [sp, #0x30]
x29、x30寄存器入栈保护
add x29, sp, #0x30
x29指向栈帧的底部
ldp x29, x30, [sp, #0x30]
恢复x29、x30寄存器的值
add sp, sp, #0x40
栈平衡,用完了要归位
ret
2.03 内存读写指令
读写:数据都是往高地址读写的 即:一段数据一个字节无法完整保存的话,连续的多个地址进行保存,地址递增
str 指令 store register
将数据从寄存器中读出来,存到内存中
ldr 指令 load register
将数据冲内存中读出来,存到寄存器中
ldp stp 可以一次性操作两个寄存器
2.04 bl 和 ret 指令
bl
将下一条指令的地址放入
lr(x30)
寄存器转到标号处执行指令
ret
默认使用
lr(x30)
寄存器的值,通过底层指令提示CPU此处作为下条指令地址
lr(x30)
寄存器存放的是函数的返回地址,当
ret
指令执行时,回去寻找lr(x30)
寄存器保存的地址在嵌套调用函数的时候需要将 x30 入栈
2.05 函数的参数和返回值
ARM64
下,函数的参数是放在x0 ~ x7
(w0 ~ w7
)这8个寄存器中。如果超过八个参数就会入栈。函数的返回值会放在
X0
寄存器中的。函数的局部变量是放在栈里面的
Last updated