> 文章列表 > 汇编指令角度掌握函数调用堆栈详细过程

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

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

函数参数从右向左依次压栈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   // 压入栈顶之上,并且移动栈顶指针espmov eax, dword ptr[ebp-4] // 将a数据放入寄存器eax中push eax

此时栈帧如下图:

在这里插入图片描述

然后会执行

call sum // 进入sum函数了

下面两行汇编暂时不执行

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

在这里插入图片描述

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

土地资源文秘网