C语言默认函数调用过程

18 篇文章 1 订阅

在这里插入图片描述

参数入栈

寄存器:cpu中的变量

  • esp:栈顶寄存器
  • ebp:栈底寄存器

在这里插入图片描述

4字节整型参数入栈

顺序:从右往左,依次入栈
方式:使用寄存器push带入
在这里插入图片描述

在这里插入图片描述

8字节结构体参数入栈

顺序:从右往左,依次入栈
方式:使用寄存器push带入

struct Node
{
	int _1;
	int _2;
};

int fun1(struct Node a,struct Node b)
{
	int c = 30;
	return c;
}

int main()
{
	struct Node a = { 10,20 };
	struct Node b = { 20,30 };
	fun1(a, b);

	return 0;
 }

在这里插入图片描述

12字节结构体参数

顺序:从右往左,依次入栈
方式:先在栈顶开辟足够该参数的空间,之后将数据复制进去。
注:C语言中只有参数字节数大于8字节才会采用此方式;C++中只要是自定义类型,无论多大字节都采用此方法

struct Node
{
	int _1;
	int _2;
	int _3;
};

int fun1(struct Node a,struct Node b)
{
	int c = 30;
	return c;
}

int main()
{
	struct Node a = { 10,20,30};
	struct Node b = { 20,30,40};
	fun1(a, b);

	return 0;
 }

在这里插入图片描述

函数栈帧开辟

  • 1.将调用方函数下一行指令地址入栈
  • 2.将调用方函数的栈底寄存器入栈
  • 3.让ebp=esp:相当于将栈底上升到栈顶位置
  • 4.让esp=esp - 0CC
  • 5.将需要使用的寄存器入栈
  • 6.循环将新开辟栈帧置为 cccc cccc

在这里插入图片描述

返回值返回

4字节返回值

方式:将返回值放入eax寄存器带回
在这里插入图片描述

8字节返回值

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

struct Node
{
	int _1;
	int _2;
};

struct Node fun1(struct Node a,struct Node b)
{
	struct Node c = { 45,50 };
	return c;
}

在这里插入图片描述

在这里插入图片描述

12字节返回值

C语言中返回值大于8字节都会以如下方式返回
C++中自定义类型都按如下方式返回
方式:

  • 首先在函数参数入栈之后再入栈一个调用方栈帧上的地址(靠近栈顶的位置)
  • 在返回值返回的时候,将返回数据写入到之前入栈的调用方栈帧地址上
  • 返回后将从该地址上将数据取出
struct Node
{
	int _1;
	int _2;
	int _3;
};

struct Node fun1(int a,int b)
{
	struct Node c = { 45,50 ,60};
	return c;
}

int main()
{
	int a = 10;
	int b = 20;

	struct Node c = fun1(a, b);

	return 0;
 }

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

函数栈退出

  • 进行当前函数栈帧的校验
  • 将进行线程保护的寄存器出栈
  • 让esp寄存器回到ebp寄存器的位置。即栈顶指向原栈底
  • ebp=pop();栈底指针还原
  • 将下一行指令的地址出栈
  • 清除参数

fun函数栈帧回退
在这里插入图片描述

主函数栈帧回退
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值