栈桢
首先来看一段代码
#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;
}