iOS 方案之本(Essence of Workaround in iOS) 是我写的一个专题。在大厂的各路优化方案中,只是告诉了我们为了达到目的怎么去做,但是并没有说这个方案的本质原因是什么。这个专栏就是为了格物致知,从原理层面来讲述方案背后的原理。
背景
在方法的启动耗时中,需要去 Hook
objc_msgSend
来达到监控所有 ObjC 方法的目的。对应的文章在这里「App 启动速度怎么做优化与监控?」。在二进制重排启动优化中,我们需要通过 Hook 所有在启动时期运行的方法,才能找到方法的执行顺序,从而确定 order file 中的符号要如何排序。在确定 ObjC 方法的顺序时,我们也需要对
objc_msgSend
方法进行 Hook,其原理也和背景 1 是相同。对应的方案在这里「抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超 15%」
在这两个方案中,我们都使用了内联汇编的方式。我们分成两篇文章来讲述这个方法的所有细节以及设计到的各个基础知识。当然这一切要求你有 ARM64 汇编的基础知识,所以这篇文章,会从汇编基础开始讲起。
“零基础”入门 ARM64 汇编基础
当然这里的零基础其实是加引号的,文章前提是你已经对 iOS 的内存分区有了简单了解,并且已经知道方法调用是栈特性的。
iOS 内存分区及栈区
在了解汇编基础之前,我们先来复习一下 iOS 的内存分区,并且从中拉出我们需要和汇编一起研究的栈(Stack) 区:
![](https://i-blog.csdnimg.cn/blog_migrate/97cb70b5a072926c99714ea950fc5a0d.png)
上图中,我们将栈区当中对于 func X
这个方法的存储区域单独拿出来研究,在这个区域里存储着 func X
这个方法的局部变量。那么右图中的 FP
、SP
又是什么?
向低地址增长的特性
有一个很重要的地方,iOS 内存的栈空间是向低地址生长的!换句话说,在图示中靠下的位置是栈顶,靠上方的位置是栈底:
![](https://i-blog.csdnimg.cn/blog_migrate/803a64e830aaea8d03fccfcb6ed46b15.png)
通用寄存器、 SP 寄存器
当然除了这两种寄存器以外,还有 PC 寄存器、浮点寄存器以及状态寄存器。在 Hook
objc_msgSend
方法时,其实也要预先记录浮点寄存器以保证数据完整性。这个问题我们后续在源码分析时会做详细讲解。
为了了解栈区中的