函数参数从右向左依次压栈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

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



















