bug函数修改的方式与myadd修改方式有所不同,myadd通过临时变量指针上移的方式修改,bug函数则通过函数内创建变量让指针下移。修改返回值时,因为最后一次是从bug函数跳转回main函数所以bug函数return的的返回值为最终返回值,下面代码用全局变量q保存了myadd的返回值所以ret依然等于myadd的返回值。
#include<stdio.h> #include<windows.h> int bug(); int *str3=NULL; int q=0; int myadd(int x,int y,int z); //函数调用开始时栈帧已经形成 int main() { int a=1; int b=2; int c=3; int ret=0; ret=myadd(a,b,c); //main函数在调用myadd函数时在main函数栈帧与myadd函数之间形成1.临时变量2.下一语句的地址3.main函数栈底(ebp)地址 printf("i am return main\n"); _asm{ sub esp,4; } printf("%d\n",ret); system("pause"); return 0; } int myadd(int x,int y,int z) { int sum=0; int *str=&x; //str指向临时变量x的地址 int *str2=&x; *str=10; //通过指针的上移依次修改临时变量x,y,z(注意x,y,z三个临时变量在栈中地址依次升高) str++; *str=20; str++; *str=30; sum=x+y+z; str2--; str3=*str2; *str2=bug; q=sum; printf("i am run over myadd\n"); //myadd函数调用完毕开始消除栈帧并返回保存好的下一语句地址,此时str2修改了保存好的地址修改为bug函数的地址 return sum; } int bug() { int x=0; int *p=&x; p+=2; *p=str3; //str3修改了本应返回的语句,bug函数调用结束栈帧销毁直接跳转回main函数 printf("i am bug!\n"); return q; }