理解函数的调用过程

梦工厂 · · 446 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一、函数的范围
二、函数的调用
      2.1 函数的进入
      2.2 函数的退出
      2.3. 函数返回值的传递 (不同编译器、不同平台是不一样的)
      2.4. Go为什么可以返回多个值?

一、函数的范围

ebp寄存器指向函数的栈底,esp寄存器指向函数的栈顶,共同划分了函数的活动范围。
减小esp的值相当于在栈上开辟空间,而增大esp的值相当于在栈上回收空间;

二、函数的调用

2.1 函数的进入
  • 参数入栈,从右到左,有的通过寄存器传递;
  • call function(1将当前指令的下一个指令地址压入栈中.2跳转到函数体执行)
  • push ebp: 把ebp压入栈中(old ebp);
  • mov ebp,esp: ebp=esp
  • [可选] sub esp,XXX: 在栈上分配XXX字节的临时空间;
  • [可选] push XXX:保存寄存器的值,可以保证寄存器在函数调用前后保持不变;
    栈的变化
函数的标准开头
2.2 函数的退出
  • [可选] pop XXX:如有必要,恢复保存过的寄存器;
  • mov esp,ebp: 恢复esp同时回收局部的变量空间;
  • pop ebp: 从栈中恢复保存的ebp的值;
  • ret: 从栈中取得返回地址,并跳转到该位置;
2.3. 函数返回值的传递 (不同编译器、不同平台是不一样的)
  • 函数将返回值存储到eax寄存器中,返回后函数的调用方再去读取eax;
  • eax本身只有4个字节,对于5~8个字节对象的情况,惯例是通过eax和edx联合返回. eax储存返回值低4字节,而edx存储返回值高1~4字节;
  • 对于更大的对象:
    1. 调用方函数A额外开辟一片空间,称为temp;
    2. 将temp的地址作为隐藏函数传递给函数B;
    3. 函数B将数据拷贝给temp对象,并将temp对象的地址用eax传出;
    4. 函数B返回后,函数A将eax指向的temp对象的内容拷贝给相应变量;
2.4. Go为什么可以返回多个值?

不同平台对于函数有不同的调用规范.

  • 例如32位通过栈传递参数, 通过eax寄存器传递返回值.
  • 64位windows通过rcx, rdx, r8, r9传递前4个参数, 通过栈传递第5个开始的参数, 通过eax寄存器传递返回值.
  • 64位linux, unix通过rdi, rsi, rdx, rcx, r8, r9传递前6个参数, 通过栈传递第7个开始的参数, 通过eax寄存器传递返回值.
  • go并不使用这些调用规范(除非涉及到与原生代码交互), go有一套独自的调用规范. 所有参数都通过栈传递, 返回值也通过栈传递。go函数可以有多个返回值的原因也在于此. 因为返回值都通过栈传递了。
    汇编分析Go语言函数的调用

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:梦工厂

查看原文:理解函数的调用过程

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

446 次点击  
加入收藏 微博
下一篇:倒排索引
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传