AArch64
AArch64 是定长指令集架构,其所有的指令在二进制层面长度都是 32 位。
Registers
在 AArch64 架构下,有 31 个通用寄存器。这些通用寄存器可以作为大部分指令的操作数参与运算。
有三套记号用于指代这 31 个通用寄存器:
r0
至r30
一般用这套记号来指代这些寄存器本身。这些记号通常用于描述汇编指令行为,不会参与到汇编指令中。x0
至x30
一般用这套记号表示这些寄存器的 64 位部分。例如,x3
表示r3
寄存器的 64 位部分。由于 AArch64 架构下的通用寄存器都是 64 位的,所以这套记号其实就代表这些寄存器的所有位。w0
至w30
一般用这套记号表示这些寄存器的低 32 位部分。例如,w3
表示r3
寄存器的低 32 位部分。
零寄存器
寄存器 xzr
和 wzr
被称为零寄存器。所谓零寄存器,就是指读取该寄存器的值,永远为 0;向该寄存器写入数值将无效,也就是说无法向该寄存器写入数值。其中 xzr
为 64 位的零寄存器,wzr
为 32 位的零寄存器。
LR寄存器
怎么实现在哪里调用就能返回到哪里
事实上,这里用到了一个特殊的通用寄存器:r30
。相应的 x30
也被称作 LR 寄存器,即 Link Register。当我们使用 bl
调用函数的时候,LR 寄存器会被写入该函数的返回地址。因此,当我们在被调用函数内部使用 ret
指令时,实际上就是将 PC 设置为 LR 寄存器的值而已。
帧指针FP寄存器
刚刚我们提到,AArch64 调用约定规定,在函数栈上,除了 LR 寄存器之外,我们还需要存储 FP 寄存器。FP 寄存器,实际上就是 r29
寄存器。
- 在函数开始的时候,同 LR 寄存器一样,我们需要把当前的 FP 寄存器的值存在栈上。随后,将当前栈顶指针
sp
的值赋给 FP。也就是说,此时 FP 寄存器的值,指向的就是之前 FP 寄存器值存储在栈上的地址。 - 在函数返回的时候,将栈上 FP 的值再写回 FP 寄存器。
通过这种做法,FP 可以帮助我们做以下的工作:
- 访问栈上变量
- 回溯函数调用栈
- 当我们分析程序,或者其他特殊情况的过程中,可以根据 FP 来回溯函数调用栈。这是什么意思呢?我们可以用一个 C 语言的结构体来解释,通过 FP,函数的栈帧可以粗略地理解成这样一个结构体:
- 存储在栈上的 FP 的值可以看作指向前一个函数栈帧的指针,从而函数的栈帧成了一个链表。我们可以通过这个链表,回溯函数的调用栈。
PSTATE
-
Process State
-
如果我们需要使用可以影响 PSTATE 的指令,则需要在后面加上一个
s
。- 例如,
adds
是add
的一个变种,可以影响 PSTATE。当结果相加为 0,则会设立 Z 位。
- 例如,
-
N 位
- 1 表示结果为负,0 表示结果非负
-
Z 位
- 1 表示结果为零,0 表示结果非零
-
C 位
- 1 表示结果有进位,0 表示结果无进位
-
V 位
- 1 表示结果有溢出,0 表示结果无溢出
Instructions
ldr
Conditionally Executed Instructions
eq
、ne
- 表示是否相等。
eq
表示相等,判断 Z 位是否为 1:Z == 1
ne
表示不等,判断 Z 位是否为 0:Z == 0
hi
、hs
、ls
、lo
- 表示无符号整数的比较。
hi
表示大于,判断是否 C 位为 1 且 Z 位为 0:C == 1 && Z == 0
hs
表示大于等于,判断 C 位是否为 1:C == 1
ls
表示小于等于,判断是否 C 位为 0 或 Z 位为 1:!(C == 1 && Z == 0)
lo
表示小于,判断是否 C 位为 0:C == 0
gt
、ge
、le
、lt
- 表示有符号整数的比较。
gt
表示大于,判断是否 Z 位为 0 且 N 位与 V 位相等:Z == 0 && N == V
ge
表示大于等于,判断 N 位是否与 V 位相等:N == V
le
表示小于等于,判断是否 Z 位为 1 或者 N 位与 V 位不等:!(Z == 0 && N == V)
lt
表示小于,判断 N 位是否与 V 位不等:N != V
这条语句的意思就是,如果当前 PSTATE 满足 eq
的条件(也就是 Z == 1
),那么就将 w1
赋值给 w0
,否则将 w2
赋值给 w0
。
Addressing
- 第一种写法被称为前索引寻址,将
x0
的值加 4 赋值给x0
后,将对应内存取值赋值给w1
- 第二种写法被称为后索引寻址,将
x0
对应的内存取值赋值给w1
后,将x0
自身值加 4 赋值给自身
Function
Prologue
在函数开头执行的操作被称为Prologue
Epilogue
在函数返回前执行的操作被称为Epilogue。