总是被问及函数调用过程中堆栈的变化以及栈回溯的原理,最近好好的研究了一下函数调用过程中各个寄存器和堆栈状态的变化,在这边分享一下,如果有不对的地方,希望得到指正,本文使用VS2008工具运行下面这段代码执行,并将各个过程中堆栈数据的变化记下。
代码如下:
int _cdecl FunD(int a, int b)
{
int d;
d = a + b;
return d;
}
int _cdecl main(int argc, char* argv[])
{
int r;
r = FunD(2, 3);
return 0;
}
寄存器相关知识,这边只列举了几个使用了的寄存器:
寄存器名称 | 功能 |
EAX | 存放函数返回值 |
ECX | 存放循环次数 |
ESP | 堆栈指针 |
EBP | 基址指针 |
EIP | 存放下一条指令的地址 |
汇编指令相关知识:
Call: 将下一条指令位置push进堆栈,并跳转到对应函数位置;
Rep: 重复执行直到ECX = 0;
Stos: 将EAX中数据拷贝到目标位置,如果方向标志位为1,则目标位置-1,否则+1。
// 主函数
int _cdecl main(int argc, char* argv[])
{
/***********************************
000217F0 push ebp
000217F1 mov ebp,esp
000217F3 sub esp,0CCh
000217F9 push ebx
000217FA push esi
000217FB push