78-C++函数调用过程

2021/11/15 17:10:10

本文主要是介绍78-C++函数调用过程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

当前演示的函数调用过程是依赖于C语言默认的调用约定——_cdecl

其他的调用约定还有__stdcall和__fastcall,三种都是C、C++使用的调用规则,三种调用约定的差异并不大,只是负责的事情有所不同

一:参数入栈

1.4字节参数入栈,顺序:从右向左入栈(先入最后一个参数),方式:使用寄存器push带入

在这里插入图片描述

先将b入栈,同时esp往上走,再将a入栈(从右向左入栈)

在这里插入图片描述

2.8字节参数入栈,顺序:从右向左,方式:使用寄存器push带入

在这里插入图片描述

先将b._2入栈,然后esp往上移(向低地址移动),然后将b._1入栈,然后esp往上移(向低地址移动),然后将a._2入栈,然后esp往上移(向低地址移动),然后将a._1入栈,然后esp往上移(向低地址移动),方式仍然是从右向左

在这里插入图片描述

3.12字节参数入栈,顺序:从右向左,方式:现在栈顶开辟足够该参数的空间,之后将数据复制进去

在这里插入图片描述

先开辟12个字节的空间(第一行表示esp=esp-0c,高地址往低地址增长,所以用减),然后先后存入b._1,b._2,b._3,然后再开辟12个字节的空间然后先后存入a._1,a._2,a._3在这里插入图片描述

4.C语言中,大于8字节以后,都是采用3的方式,小于8字节,采用1 2方式

5.在C++中,只要是自定义类型, 无论多大字节,都采用3的方式

6.寄存器:CPU中的变量

7.esp寄存器:栈顶寄存器(低地址)

8.ebp寄存去:栈底寄存器(高地址)

9.唯一标志一段空间就需要有一个头有一个尾

10.mov是取值(把后面的值赋值给前面),push是入栈,sub是减,call是调用函数

二:函数栈帧开辟

在这里插入图片描述

1.在参数入栈之后,调用函数的时候,esp往上(往低地址)移动了4个字节,保存的是下一行指令的地址(就是函数调用完成之后,main函数要从那里继续执行)

2.然后把main函数的ebp(栈底寄存器)入栈

3.然后让ebp=esp

4.然后开辟整个fun函数的栈帧(esp=esp-0cc)

5.然后将其他使用的寄存器入栈

6.然后循环初始化成0xcccc cccc

7.然后进行校验

在这里插入图片描述

三:返回值返回

4字节的返回值:

方式:将返回值放入寄存器带回

8字节返回值:

方式:将放回值放入两个寄存器带回

大于8字节返回值:

方式:首先在函数参数入栈之后,入栈一个调用方栈帧上的地址(靠近栈顶位置)在返回值返回的时候将返回数据写入到之前入栈的调用方地址上,返回之后将从该地址上将数据取出

注意:在C++中,自定义类型都按照入栈调用方地址的方式(即大于8字节返回值的方式)

四:函数栈退出

在这里插入图片描述
在这里插入图片描述

1.在之前现场保护入的三个寄存器吐出

2.进行当前函数栈帧的校验

3.将现场保护的寄存器吐出(出栈)

4.让esp=ebp

5.ebp=Pop(把先前入栈的main函数的ebp还原回来)

6.将下一行指令的地址还原

7.清除参数



这篇关于78-C++函数调用过程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程