美文网首页
汇编基础-探索函数本质

汇编基础-探索函数本质

作者: spyn_n | 来源:发表于2021-03-26 16:35 被阅读0次

初探

我们先看一下一个无参数无返回值的空函数,系统都干了啥。

void emptFun(){

}

函数汇编

0x100be9f20<+64>:  bl    0x100be9cec              ; emptFun at ViewController.m:18:1

001--Demo`emptFun:

->  0x100be9cec<+0>: ret   

可以发现,emptyFun函数在viewController的位置,通过bl跳转指令跳到0x100be9cec函数入口地址执行,从汇编可以看出,emptyFun函数就只有一个ret返回指令。那它是怎么返回viewController并继续执行后面的代码的呢:

可以看到在执行bl跳转指令的时候,系统会把下一条指令的地址放入lr(X30寄存器),当emptyFun函数执行完执行ret指令的时候,系统从lr寄存器中读取地址,并继续执行相关的指令。

带参数、带返回值函数

我们把函数参数个数放得多一点

int test(int a, int b, int c, int d, int e, int f, int g, int h, int I, int j, int k){

    returna + b + c + d + e + f + g + h + i + j + k;

}

运行调试我们看一下汇编:

 0x1005d9f24<+64>:  orr    w0, wzr,#0x1

    0x1005d9f28<+68>:  orr    w1, wzr,#0x2

    0x1005d9f2c<+72>:  orr    w2, wzr,#0x3

    0x1005d9f30<+76>:  orr    w3, wzr,#0x4

    0x1005d9f34<+80>:  mov    w4,#0x5

    0x1005d9f38<+84>:  orr    w5, wzr,#0x6

    0x1005d9f3c<+88>:  orr    w6, wzr,#0x7

    0x1005d9f40<+92>:  orr    w7, wzr,#0x8

    0x1005d9f44<+96>:  mov    w10,#0x9

    0x1005d9f48<+100>: str    w10, [sp]

    0x1005d9f4c<+104>: mov    w10,#0xa

    0x1005d9f50<+108>: str    w10, [sp,#0x4]

    0x1005d9f54<+112>: mov    w10,#0xb

    0x1005d9f58<+116>: str    w10, [sp,#0x8]

    0x1005d9f5c<+120>: bl    0x1005d9d20              ; test at ViewController.m:24

    0x1005d9f60<+124>: str    w0, [sp,#0xc]

    0x1005d9f64<+128>: ldp    x29, x30, [sp,#0x30]

常数#0x1,#0x2,#0x3,#0x4,#0x5,#0x6,#0x7,#0x8,都是放入通用寄存器的低32位W0~W7,但是#0x9、#0xa、#0xb,会从栈顶sp开始每隔4个字节依次入栈。然后bl跳转到test函数

0x1005d9f5c<+120>: bl    0x1005d9d20              ; test at ViewController.m:24

进入test函数的汇编代码:

如图,调用函数开辟(拉伸)了24个字节的栈空间,但是我们发现,框框起来的汇编代码,好像操作的是这个函数开辟的栈外面的空间,很明显,[sp, #0x38]大于0x30大小,是上一个函数的栈,原来,在上一个函数,系统将超过8个的参数,放入了栈顶提供给test函数,也就是说:函数参数超过8个的时候,超过的部分就会通过函数栈来传递值。 没有超过8个的参数1、2、 3、4、5、6、7、8是从寄存器中读取。 

后面的就简单了,通过栈顶sp指针以及偏移取一个相加放到X0寄存器。

最后add    sp, sp,#0x30 栈平衡,ret

返回控制器中,我们可以打印w0的值就是函数返回结果;

这里特别说明一下,基本上一个函数的调用汇编里面,在ret指令之前基本都会有:

 0x1005d9f64<+128>: ldp    x29, x30, [sp,#0x30]

    0x1005d9f68 <+132>: add    sp, sp,#0x40            ; =0x40  栈平衡,开辟多少就释放所少

    0x1005d9f6c <+136>: ret 

ldp    x29, x30, [sp,#0x30],这句就是现场还原/恢复,因为前面进行了stp    x29, x30, [sp,#0x30]这一句,空了8个字节保护X29,X30寄存器,为的是在函数嵌套调用里面能够找到回去的路,不至于死循环。当然也不是所有的函数调用都需要现场保护,如叶子函数。

所以如果从效率的方向考虑,函数的参数,最好不要超过8个,除去两个隐式参数,剩下6个。因为从上面的阐述可以知道,如果超过8个,需要处理到2个栈的操作。

相关文章

  • 汇编基础-探索函数本质

    初探 我们先看一下一个无参数无返回值的空函数,系统都干了啥。 void emptFun(){} 函数汇编 0x10...

  • 汇编-----函数的本质

    通过汇编代码我们可以探索函数的本质 1: 如果函数内部没有调用其他函数, 那么sp不会进行偏移, 编译器会通过mo...

  • 汇编基础(二)函数的本质

    关于CPU 寄存器 CPU除了有控制器、运算器还有寄存器。其中寄存器的作用就是进行数据的临时存储。 CPU的运算速...

  • 02-汇编基础(2)

    前言 本篇文章主要以汇编的角度,分析函数的本质,在分析函数的过程中,就会解决上篇文章最后的死循环问题。 一、基础知...

  • 汇编-函数本质

    栈 栈:是一种具有特殊的访问方式的存储空间(后进先出, Last In Out Firt,LIFO)image.p...

  • c语言逆向分析之函数1

    从汇编的角度去理解函数会让你更加的深刻。。。。。。 看这篇文章需要一定的c语言基础和汇编基础(能基本看懂简单的汇编...

  • 【8086汇编】-- 函数的本质

    一、函数的入参和返回值 上面展示了一个函数入参的方式有哪些,一般的cpu都是少量参数通过寄存器传参,当参数大于一定...

  • 【汇编】二、 函数本质

    002--函数本质 关于CPU的补充 寄存器 CPU除了有控制器、运算器还有寄存器。其中寄存器的作用就是进行数据的...

  • ARM64汇编入门 - 汇编基础

    ARM64汇编入门 - 汇编基础ARM64汇编入门 - 汇编基础

  • <安全攻防之汇编基础>

    &关于汇编基础请点击 <汇编一> <汇编二> <汇编三> <汇编四> <汇编五> <汇编六> <汇编七> <汇编八...

网友评论

      本文标题:汇编基础-探索函数本质

      本文链接:https://www.haomeiwen.com/subject/eahhhltx.html