Comment on page
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寄存器的值可以改变程序执行的流程
- x0-x7: 用于子程序调用时的参数传递,X0还用于返回值传递
x0 - x30
是31个通用整形寄存器。每个寄存器可以存取一个64位大小的数。 当使用 r0 - r30访问时,它就是一个64位的数。当使用 w0 - w30访问时,访问的是这些寄存器的低32位,如图:

通用寄存器
Current Program State Register状态寄存器是32位的

CPSR
- 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=0 - C,
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位用来标记借位。

Carry
- V,
oVerflow condition flag
有符号运算有溢出时,V=1- 正数 + 正数 = 负数 则 溢出
- 负数 + 负数 = 正数 则 溢出
- 正数 + 负数 不可能溢出
后进先出 ARM64栈开口向底地址,即开辟的地址是朝底地址方向的
- SP寄存器在任意时刻会保存栈顶的地址
- FP寄存器也称为X29寄存器属于通用寄存器,但是在某些时候我们利用它保存栈底的地址
注意:ARM64开始,取消了32位的LDM、STM、PUSH、POP指令,取而代之的是:ldr、ldp、str、stp。在ARM64中对栈的操作是16字节对齐的
常见函数调用开辟和恢复栈空间
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
读写:数据都是往高地址读写的 即:一段数据一个字节无法完整保存的话,连续的多个地址进行保存,地址递增
- str 指令 store register
- 将数据从寄存器中读出来,存到内存中
- ldr 指令 load register
- 将数据冲内存中读出来,存到寄存器中
- ldp stp 可以一次性操作两个寄存器
bl
- 将下一条指令的地址放入
lr(x30)
寄存器 - 转到标号处执行指令
ret
- 默认使用
lr(x30)
寄存器的值,通过底层指令提示CPU此处作为下条指令地址
lr(x30)
寄存器- 存放的是函数的返回地址,当
ret
指令执行时,回去寻找lr(x30)
寄存器保存的地址 在嵌套调用函数的时候需要将 x30 入栈
ARM64
下,函数的参数是放在x0 ~ x7
(w0 ~ w7
)这8个寄存器中。如果超过八个参数就会入栈。- 函数的返回值会放在
X0
寄存器中的。 - 函数的局部变量是放在栈里面的
Last modified 2yr ago