先奉上代码:(X86环境运行!X64会不一样哦!)
#include <stdio.h>
int Add(int x, int y)
{
int z = x + y;
return z;
}
int main()
{
int a = 66;
int b = 34;
int c = 0;
c = a + b;
printf("%d\n", c);
return 0;
}
这里仅涉及到了简单的变量创建和函数调用,以此我们来深入剖析其背后的实现原理。
如果看一眼堆栈:

可知 main 函数也被其他函数调用,但这不必过度分析,只需要了解即可。
目录
第四、五、六行:push ebx; push esi; push edi
第七、八、九行:lea edi, [ebp-24h]; mov ecx, 9; mov eax, 0CCCCCCCCh
第十行:rep stos dword ptr es:[edi]
第二、三行:mov dword ptr [ebp-14h],22h; mov dword ptr [ebp-20h],0
认识寄存器
大家都知道在CPU内集成了很多寄存器,例如:eax,ebx,ecx,edx,ebp,esp等等
这里我们主要关注的是 ebp 和 esp 两个寄存器:
ebp - 储存了栈底地址;esp - 储存了栈顶地址
认识汇编指令
push - 入栈操作
pop - 出栈操作
mov - 移动操作
sub - 减法
add - 加法
lea - load effective address - 加载有效地址
rep stos - 填充
call - 函数调用
jmp - 跳转
ret - 返回到地址处执行
当然不理解也没关系,接下来会详细讲解。
汇编代码一览
005718B0 push ebp
005718B1 mov ebp,esp
005718B3 sub esp,0E4h
005718B9 push ebx
005718BA push esi
005718BB push edi
005718BC lea edi,[ebp-24h]
005718BF mov ecx,9
005718C4 mov eax,0CCCCCCCCh
005718C9 rep stos dword ptr es:[edi]
005718CB mov ecx,57C008h
005718D0 call 0057131B
int a = 66;
005718D5 mov dword ptr [ebp-8],42h
int b = 34;
005718DC mov dword ptr [ebp-14h],22h
int c = 0;
005718E3 mov dword ptr [ebp-20h],0
c = Add(a, b);
005718EA mov eax,dword ptr [ebp-14h]
005718ED push eax
005718EE mov ecx,dword ptr [ebp-8]
005718F1 push ecx
005718F2 call 005710B4
005718F7 add esp,8
005718FA mov dword ptr [ebp-20h],eax
printf("%d\n", c);
005718FD mov eax,dword ptr [ebp-20h]
00571900 push eax
00571901 push 577B30h
00571906 call 005710D2
0057190B add esp,8
return 0;
0057190E xor eax,eax
}
00571910 pop edi
00571911 pop esi
00571912 pop ebx
00571913 add esp,0E4h
00571919 cmp ebp,esp
0057191B call 00571244
00571920 mov esp,ebp
00571922 pop ebp
00571923 ret
汇编剖析(执行前)
由于调用 main 函数的函数没必要展开描述,所以下文只是简述。可知 ebp 和 esp 对栈是这样维护的:

所以如果我们假设调用 main 函数的函数统称为 startmain 函数(纯编造,勿当真)
其准备执行第一行汇编代码时,堆栈情况如下:

第一行:push ebp
即入栈,注意:入栈 esp 会跟随向上移动,所以这一步执行后,栈情况如下:

push 前:(地址仅起演示作用)

push 后: (地址仅起演示作用)

注:内存的使用是从高地址到低地址,所以这里 esp 减少但实际是在向上移
第二行:mov ebp, esp
mov 指令是将后者的值给前者,即这里把 esp 的值给了 ebp,这个时候 esp 和 ebp 指向同一位置:
第三行:sub esp, 0E4h
这里 esp 的减少,实际上是在向上开空间,栈空间如下:


本文深入剖析了X86环境下函数栈帧的创建和销毁过程,通过汇编代码展示了如何使用ebp和esp寄存器管理栈,详细解释了push、pop、mov等指令的作用,并探讨了局部变量的创建、函数调用时参数的传递和返回值的处理。
最低0.47元/天 解锁文章
2813





