栈的数据是从高地址往低地址增长的
每当函数调用的时候会有ebp esp去维护所在的栈帧(函数调用都会在栈帧上创建空间)
例如:在调用main函数前会调用一个__tmainCRTstartup函数
以下拿反汇编代码进行分析
int Add(int x, int y)
{
int z = 0;
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;
}
//rbp和rsp与esp和ebp的区别为64位机器和32位机器
00007FF7FC3118E0 push rbp
00007FF7FC3118E2 push rdi
00007FF7FC3118E3 sub rsp,148h
00007FF7FC3118EA lea rbp,[rsp+20h]
00007FF7FC3118EF lea rcx,[00007FF7FC321008h]
00007FF7FC3118F6 call 00007FF7FC311370
int a = 10;
00007FF7FC3118FB mov dword ptr [rbp+4],0Ah
int b = 20;
00007FF7FC311902 mov dword ptr [rbp+24h],14h
int c = 0;
00007FF7FC311909 mov dword ptr [rbp+44h],0
c = Add(a, b);
00007FF7FC311910 mov edx,dword ptr [rbp+24h]
00007FF7FC311913 mov ecx,dword ptr [rbp+4]
00007FF7FC311916 call 00007FF7FC311348
00007FF7FC31191B mov dword ptr [rbp+44h],eax
我们来画图理解
这里跳转到add库函数
int Add(int x, int y)
{
00007FF7FC3117B0 mov dword ptr [rsp+10h],edx
00007FF7FC3117B4 mov dword ptr [rsp+8],ecx
//这里开始创建新空间给Add
00007FF7FC3117B8 push rbp
00007FF7FC3117B9 push rdi
00007FF7FC3117BA sub rsp,108h
00007FF7FC3117C1 lea rbp,[rsp+20h]
00007FF7FC3117C6 lea rcx,[00007FF7FC321008h]
00007FF7FC3117CD call 00007FF7FC311370
int z = 0;
00007FF7FC3117D2 mov dword ptr [rbp+4],0
z = x + y;
00007FF7FC3117D9 mov eax,dword ptr [rbp+0000000000000108h]
00007FF7FC3117DF mov ecx,dword ptr [rbp+0000000000000100h]
00007FF7FC3117E5 add ecx,eax
00007FF7FC3117E7 mov eax,ecx
00007FF7FC3117E9 mov dword ptr [rbp+4],eax
return z;
00007FF7FC3117EC mov eax,dword ptr [rbp+4]
}
00007FF7FC3117EF lea rsp,[rbp+00000000000000E8h]
00007FF7FC3117F6 pop rdi
00007FF7FC3117F7 pop rbp
00007FF7FC3117F8 ret
之后return销毁
这样就是一个完整的函数调用栈的创建和销毁