1. 栈
1.1 栈的概念
栈是一种具有特殊访问方式的存储空间(后进先出)。
1.2 栈中最重要的两个寄存器
SP寄存器:栈顶寄存器,在任意时刻都会保存栈顶的地址。
FP寄存器:栈底寄存器(也称为x29寄存器,属于通用寄存器,在某些时刻利用它来保存栈底的地址)
注意:ARM64中对栈的操作是16字节对齐的,寄存器存储空间是8字节大小的,也就是128bit
1.3 栈的读写指令
- 读指令:ldr(load register)、LDR 、LDP,将内容读取到寄存器中。
- 写指令:str(store register)、STR、STP,将寄存器其中的值存储到内存中
1.4 汇编练习
- 指令
1. sub sp, sp, #0x10 ;拉伸16个字节大小的栈空间
2. stp x29, x30, [sp, #0x10] ;往sp所在位置向高地址方向分别存储x29以及x30的值 - 简写形式:stp x29, x30, [sp, #-0x10]! (不需要额外的栈空间的时候可以这么写,!的意思是将[]中运算的结果保存到sp寄存器中)。(这句汇编应该是先写入,再拉伸栈空间)
注意:在ARM64中栈的开口方向是由高地址向低地址的,保存寄存器的值是从栈底开始存储的。
2. bl指令
- bl指令:跳转指令,表示程序执行到标号处,会将下一条指令的地址保存到lr寄存器中。b代表跳转,l代表lr(x30寄存器)。
3. ret指令
ret指令:返回指令,类似函数中的return,让cpu执行lr寄存器所指向的指令。
** 注意:函数内部调用函数的时候就需要保护现场,在ret指令调用之前,将之前存在栈中的lr寄存器的值取出来赋值给lr寄存器 **
4. 函数的参数
在ARM64中,参数是存放在x0到x7这8个寄存器中的。
注意:如果是浮点数,就会用浮点寄存器,如果超过8个参数,就会使用栈传递参数
5. 函数的返回值
在ARM64中,一般函数的返回值是使用x0寄存器保存的。
注意:如果返回值大于8个字节,就会利用内存传递返回值。
在函数的编写过程中,参数一般都不应超过8个,返回值的字节大小也不应大于8字节,因为会降低效率