iOS arm64汇编中堆栈问题

即函数调用如何分配内存
堆栈指针寄存器(存储着堆栈中某一个内存的地址)
sp(Stack Pointer)
fp(Frame Pointer) 也就是x29

main函数中调用中基本上前面的汇编指令是在做堆栈相关的操作比如分配存储空间给局部变量用,最后面的汇编指令是在回收堆栈内存(前面分配栈空间给局部变量,函数执行完回收栈空间)

函数的堆栈
函数的类型:
叶子函数,叶子上面没有分支,是最顶端最深层的函数,函数中不存在其他函数,内部不再调用其他函数的函数
非叶子函数

在xcode中新建C语言文件用c语言代码转变为汇编, show in finder直接点击go to shell进入终端
xcrun -sdk iphoneos clang -arch arm64 -S CTest.c

叶子函数:
栈空间都是给函数用的,一旦调用了函数,就是把栈空间的某一段内存空出来,这段空间就给这个函数用,将来吧函数中的局部变量放在这段空间中就可以了,通过sp寄存器,这是堆栈指针,是存储着堆栈中某一个内存的地址
这里写图片描述
给两个变量分配存储空间,在函数调用之前先有一段内存出来给这个函数存放局部变量
这里写图片描述
这里写图片描述
栈空间的释放仅仅是sp指针的挪用而已,函数的栈空间回收变量销毁变量意思就是将sp指针挪用,没有必要清0原来地址的值,因为新的值会直接覆盖掉旧的值.
堆栈平衡是指一个函数调用之前sp是在36行的位置,函数调用完之后sp还是在36这个位置,说明堆栈是平衡的
这里写图片描述
首先减了一段内存空间,则这段内存空间就给了这个函数的局部变量存储数值,函数调用完sp又加上减去的那段回到原来的地方这个就是叶子函数的堆栈平衡

非叶子函数的堆栈平衡
这里写图片描述

这里写图片描述
fp指针也是堆栈指针,x29
sub sp, sp, #32
// 分配32个字节
stp x299, x39, [sp, #16]
// 将x29,x30的值存到[sp, #16]内存中去
空间的前面8个字节放fp,后面8个字节放lr
这里写图片描述
这里写图片描述

sp与fp指针两个指针的作用是sp与fp中间的空间才是栈空间,才是存储函数局部变量的栈空间,sp与fp指针两个指针是用来确定一段函数的栈空间
fp里面可能存储的是以前别人的其他函数的东西,是其他函数的就不能破坏别人的东西,所以add x29, sp, #16在拿fp来用之前(改变它的值之前)要把fp先存起来即stp x29, x30, [sp, #16]
在存储lr,lr是函数的返回地址,即bl指令 bl _haha,修改lr
ldp x29, x30,[sp, #16]将指定的内存地址[sp, #16]赋值给lr当做bl _haha的返回地址,一旦执行bl _haha ,然后lr就被改掉了
这里写图片描述
这里写图片描述

ldp x29, x30, [sp, #16]
从[sp,#16]的内存中读取数据前8个字节到fp,后8个字节赋值给lr,恢复现场.

非叶子函数,内部还要调用其他函数,调用其他函数内部返回值就会变,所以非叶子函数在提示空间的时候,不仅仅要提升16个字节出来给局部变量用,还要提升另外16个字节用来存储fp,lr保护现场.sp到fp之间就是给局部变量用的.
sp一般叫做栈顶指针
fp一般叫做栈底指针

猜你喜欢

转载自blog.csdn.net/u012581760/article/details/80183351