前言
本篇文章是在VS2013环境下调试的
在研究函数栈帧的创建和销毁时,建议不要使用太高级的编译器,越高级的编译器,越不容易观察函数的栈帧创建和销毁的过程。
同时,函数栈帧创建和销毁的过程在不同编译器下是有略微差异的,但大体上是一致的,具体细节取决于编译器的实现。
那么什么是函数栈帧呢?
每一个函数调用,都会在栈上创建一个空间,而这个在栈区上为函数创建的空间就叫做函数栈帧。
接下来就开始关于函数栈帧的创建和销毁的学习吧!
寄存器
首先,让我们先了解有哪些寄存器,有eax,ebx,ecx,edx……
我们在这里的重点是ebp和esp这两个寄存器
ebp、esp这两个寄存器中存放的是地址,这两个地址就是用来维护函数栈帧的。
ebp指向当前栈帧的底部(高地址)
esp指向当前栈帧的顶部(低地址)
具体代码详解
这里咱用个简单的加法函数来展示
c语言
int Add(int x, int y)
{
int z = x + y;
return z;
}
int main()
{
int a = 10;
int b = 20;
int c = 0;
c = Add(a, b);
printf("%d\n", c);
return 0;
}
反汇编
#include<stdio.h>
int Add(int x, int y)
{
003113C0 55 push ebp
003113C1 8B EC mov ebp,esp
003113C3 81 EC CC 00 00 00 sub esp,0CCh
003113C9 53 push ebx
003113CA 56 push esi
003113CB 57 push edi
003113CC 8D BD 34 FF FF FF lea edi,[ebp+FFFFFF34h]
003113D2 B9 33 00 00 00 mov ecx,33h
003113D7 B8 CC CC CC CC mov eax,0CCCCCCCCh
003113DC F3 AB rep stos dword ptr es:[edi]
int z = 0;
003113DE C7 45 F8 00 00 00 00 mov dword ptr [ebp-8],0
z = x + y;
003113E5 8B 45 08 mov eax,dword ptr [ebp+8]
003113E8 03 45 0C add eax,dword ptr [ebp+0Ch]
003113EB 89 45 F8 mov dword ptr [ebp-8],eax
return z;
003113EE 8B 45 F8 mov eax,dword ptr [ebp-8]
}
003113F1 5F pop edi
003113F2 5E pop esi
003113F3 5B pop ebx
003113F4 8B E5 mov esp,ebp
003113F6 5D pop ebp
003113F