栈桢
首先来看一段代码
#include<stdio.h>
int add(int x, int y)
{
int z = x + y;
return z;
}
int main()
{
int a = 10;
int b = 20;
int ret = add(a, b);
printf("ret = %d\n",ret);
return 0;
}
此处是为了给a,b分别开辟空间,这时栈桢如图所示
两条push命令将a,b变量入栈保存
接下来通过call命令,将call命令的下一条命令的地址入栈,目的是为了恢复,其次call命令通过jmp命令修改eip寄存器的值,从而达到跳转的目的
通过push命令将此时的ebp压栈保护(此时的ebp是main函数的ebp),再通过move将esp和ebp的指向变得相同(都指向esp指向的位置),再将esp减44,至此形成新的栈桢结构
接下来,通过以下几条命令计算出a + b,并将其保存,同时通过pop指令出栈,再用move指令将esp和ebp指向相同位置再通过ret将当前栈顶的数据弹回到eip(ret将当前栈顶数据弹回到eip 中)
对应汇编代码如下
此时对应的栈桢结构如图所示
此时已经回到初始状态,通过add和move指令达到将ebp返回到main函数的ebp,再将a+b的内容放到ebp-12的那块空间,如图所示.
至此完成所栈桢结构,以及临时变量的释放
再来看一段栈桢应用的代码:
#include<stdio.h>
#include<windows.h>
void bug();
int my_add(int x, int y);
void* ret = NULL;
void bug()
{
int x = 0;
int* q = &x;
q += 2;
*q = ret;
printf("bug: hehe i am a bug!\n");
Sleep(2000);
}
int my_add(int x, int y)
{
//printf("my_add:");
int* p = &x;
p--;
ret = *p;
*p = bug;
}
int main()
{
int a = 10;
int b = 20;
int c = my_add(a, b);
__asm
{
sub esp,4
}
printf("main: you should run here\n");
return 0;
}