OC逆向02:函数本质(下)
前言
本文主要是讲解函数的 参数、返回值、局部变量 在汇编中是如何存储的,以及 CPSR 标志寄存器
函数的参数和返回值
arm64下,函数的 参数 是存放在 x0-x7(w0-w7) 这8个寄存器里面的,如果超过 8 个参数,就会入栈
如果自定义函数时,参数最好不要超过6个(因为有两个隐藏参数 self,_cmd)
如果函数需要多个参数,可以传入数组、结构体、指针等类型
函数的 返回值 放在 x0寄存器 中
- 如果返回值 大于8个 字节,就会 利用内存传递
查看系统的参数汇编
下面通过系统中对函数的汇编来查看系统对参数、返回值是如何操作的
1 | int sum(int a, int b){ |
- 查看汇编,在跳转到sum函数之前,已经将参数存入 w0、w1
- 在sum函数中,读取w0、w1,放入w8、w9。然后将相加后的结果放入w0(即返回值在w0寄存器)
自己优化实现sum
运行发现,其结果与sum函数是一致的,结果都是30
1 | <!--asm.s--> |
编译器优化
来看一下代码的汇编
1 | int test(int a, int b, int c, int d, int e, int f, int g, int h, int i){ |
- test函数断住,查看汇编
以下是 viewDidLoad
栈空间的存入分析过程
- 以下是
test
函数的汇编分析
编译器优化
- 将debug模式改成release模式,此时再来查看汇编代码,发现没有test函数,被优化掉了
- 如果非要执行 test,可以这样写
1 | - (void)viewDidLoad{ |
汇编代码如下,发现优化后的test函数在汇编中,其本质是一个 数
,也就是 test函数的返回值(相当于将 printf("%d", test(1, 2, 3, 4, 5, 6, 7, 8, 9));
直接优化成了 printf("%d", 45);
)
通过汇编实现函数
- 定义函数声明及调用
1 | int funcA(int a, int b); |
- 汇编实现 funcA
1 | <!--sam中--> |
运行结果如下
1 | 30 |
【说明】:
关于b指令:只是跳转,不改变lr寄存器
拉伸空间和参数个数有没有关系?
- 有关系,参数越多时,如果寄存器放不下,就需要用到内存。就会将栈空间放大,影响栈空间的不仅仅是参数个数,还有局部变量
函数的返回值
如果返回值是 一个结构体,一个寄存器放不下,这是什么情况?
有以下代码,运行查看其汇编:
1 | struct str { |
- 断点运行,以下是
viewDidLoad
函数的汇编
- Post title:OC逆向02:函数本质(下)
- Post author:张建
- Create time:2022-04-20 15:51:43
- Post link:https://redefine.ohevan.com/2022/04/20/OC逆向/OC逆向02:函数本质(下)/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.