个人原创,转帖请注明来源:cnblogs.com/jailbreaker
在这[iOS逆向实战 之一]中讲到函数调用的参数传递通过r0-r3来实现,这篇帖子我们来验证下。先看一个4个参数的函数代码:
main方法简单调用compute方法,先看main的汇编代码:
明显可以看出,参数值1,2,3,4分别传递给r0-r3,然后通过b调用函数 compute,接着看下compute的汇编代码:
最后一行 是返回到 调用者的下一行,之前帖子已经学过了,前面面3条代注释如下:
add r0, r1 //r0 = r0+r1
add r0,r2 //r0 = r0+r2
subs r0,r0,r3 //r0 = r0 - r3
比较下汇编代码和源代码,就能理解r0-r3的功能,这里的被调用函数是4个参数,正好对应r0-r3 4个寄存器,如果参数是多个,又会怎么样,修改源代码如下:
还是看main汇编代码:
目前汇编的main方法 和之前的版本差异还是比较大的,行数36 - 38 ,这里可以看出开创了一个新的栈帧,而大小是12个字节,其实就是函数最后3个参数需要保存的位置,行数50 - 51,做的是针对36 - 38 开创空间的清理工作。
行数39 - 41,把实参5,7,6赋予r2,r0和r1,这里顺序其实无所谓了,因为者3个寄存器作为临时保存,后面42,43,45行的功能将这个值分别保存到[sp+0],[sp+4],[sp+8]内存位置,剩余的mov代码都能看懂了,之后调用compute,再来看下compute内部的汇编代码:
重点看下 20 ,22,24行 ldr 指令,ldr lr,[r7,#8] 的含义是将r7+8地址上的值 保存到lr里,这里为啥是+8,而不是+0,因为在16行,先后push了lr和r7(27行pop出来),正好是8字节,所以r7+8就是前面栈帧分配的参数。