汇编指令角度掌握函数调用堆栈详细过程

本文通过分析C++代码和汇编指令,详细解释了函数调用时参数如何从右向左压栈,以及在sum函数执行完毕后如何返回到main函数的正确位置继续执行。在main函数中,变量a和b入栈,随后调用sum函数,sum函数内部创建自己的栈帧,执行完后通过调整esp和ebp恢复main函数的栈帧,并通过ret指令返回到main函数的下一条指令继续执行。
摘要由CSDN通过智能技术生成

函数参数从右向左依次压栈push,call 要先把下一行指令 压栈,

根据如下代码思考两个问题:

问题一:main函数调用sum,sum执行完以后,怎么知道回到哪个函数中?

问题二:sum函数执行完,回到main以后,怎么知道从哪一行指令继续运行的?

#include <iostream>
using namespace std;


int sum(int a, int b)
{
	int temp = 0;
	temp = a + b;
	return temp;
}

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

	int ret = sum(a, b);
	cout << "ret:" << ret << endl;

	return 0;
}

ebp是栈帧的栈底(高地址),esp是永远指向栈顶(低地址)

首先程序进入main函数要在虚拟地址空间开展栈帧,下面两句代码将数据入栈(放入栈底),ret先压入栈中,注释为汇编代码

int a = 10;  // mov dword ptr[ebp-4], 0Ah
int b = 20;  // mov dword ptr[ebp-4], 014h

函数调用时,按参数列表从右往左压栈(栈顶esp进入)。int ret = sum(a, b); 需要执行的汇编如下

mov eax, dword ptr[ebp-8] // 将b数据放入寄存器eax中

push eax   // 压入栈顶之上,并且移动栈顶指针esp

mov eax, dword ptr[ebp-4] // 将a数据放入寄存器eax中

push eax

此时栈帧如下图:

在这里插入图片描述

然后会执行

call sum // 进入sum函数了

下面两行汇编暂时不执行

add esp, 8  # 栈顶压入 int ret = sum(a, b);的下一行指令地址,假设地址为0x08124458,回答问题2

mov dword ptr[ebp-0Ch], eax

在这里插入图片描述

此时进入sum函数了,在进入函数内第一条指令前(int temp = 0;)还有几条汇编需要执行,用于分配栈空间

push ebp # 压入main函数栈帧的栈底指针

mov ebp, esp # ebp = esp 

在这里插入图片描述

紧接着执行 sub esp, 4Ch,即esp -= 4Ch功能为给sum函数开辟栈空间,随后若是vs则汇编使用循环初始化栈空间数据都为0xCCCCCCCC,若是gcc或g++则不会初始化。

在这里插入图片描述

注:

int a;

cout<<a<<endl; // 输出-858993460 也就是0xCCCCCCCC

然后是执行sum函数内三行代码

int temp = 0; // mov eax, dword ptr[ebp+0Ch]

temp = a + b;  // 执行如下两条汇编,完成了a+b运算存入寄存器eax中

// mov eax, dword ptr[ebp+0Ch]

// add eax, dword ptr[ebp+8] 

// mov dword ptr[ebp-4], eax // 将a+b存入temp
return temp; // mov eax, dword ptr[ebp-4]  将值存入eax带出函数返回,eax = 30

然后sum函数右括号之前也会执行一系列汇编

mov esp, ebp // esp = ebp,即回退栈帧

在这里插入图片描述

pop ebp 栈顶出栈,栈顶指针esp下移,并把值给ebp,即上图的0x0018ff40,ebp又回到main函数栈帧底

在这里插入图片描述

随后执行 ret指令 出栈,把栈顶值(main需要执行的下一条指令地址)存入CPU的PC寄存器

在这里插入图片描述

然后开始执行

add esp, 8  // 假设地址为0x08124458,作用是传入函数的参数出栈

mov dword ptr[ebp-0Ch], eax

在这里插入图片描述

最终就得到了计算的结果啦!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值