初始栈空间如下(可以拿来训练):
代码执行之后:
代码:
#include <iostream>
int sum(int a, int b)
{
/*
00601800 push ebp
00601801 mov ebp,esp
006018A7 sub esp,4Ch
006018A7 reo stos
*/
int temp = 0;
/*
00471825 mov dword ptr[ebp - 8], 0
*/
temp = a + b;
/*
00B1182C mov eax,dword ptr [ebp+8]
00B1182F add eax,dword ptr [ebp+0Ch]
00B11832 mov dword ptr [ebp-4],eax
*/
return temp;
/*
00B11835 mov eax,dword ptr [ebp-4]
*/
}
/*
00B11838 mov esp, ebp
00B11839 pop epb
00B1183A ret
*/
int main()
{
int a = 10;
/*
00421895 mov dword ptr [ebp-4],0Ah
*/
int b = 20;
/*
0042189C mov dword ptr [ebp-8],14h
*/
int ret = sum(a, b);
/*
004218A3 mov eax ,dword ptr [ebp-8]
004218A6 push eax
004218A7 mov eax ,dword ptr [ebp-4]
004218AA push eax
002E18AB call sum
002E18B0 add esp,8
002E18B3 mov dword ptr [ebp-0Ch],eax
*/
std::cout << ret;
}
汇编基本命令:
mov dword ptr [ebp-4],0Ah :将值0Ah复制到栈空间[ebp-4]处空间存储
push eax :将eax的值入栈
call: 先把下一行指令地址入栈,跳转到调用函数
sub esp,4Ch :esp的值减4Ch
add eax,dword ptr [ebp+0Ch] :eax = eax + [epb+0Ch]位置的值
reo stos: 类似for循环,将栈帧初始化成0xCCCCCCCC
pop epb: 出栈,并把出栈的值赋值给ebp
ret: 出栈,把出栈的内容放入CPU的PC寄存器里面
所以函数调用过程总结为以下几点:
遇到函数调用:
将实参从右向左压栈
将下一行指令执行地址压栈
跳转到调用函数
遇到函数左括号:
调用方函数栈底地址入栈
将栈低指针ebp指到栈顶esp
给函数开辟栈帧
给栈帧初始化为0xCCCCCCCC
遇到函数右括号
释放栈帧
将栈低指针回退到函数调用前位置
让CPU继续执行函数调用位置的下一条指令