(子程序堆栈帧中,以EBP为界.向上(小地址)是局部变量,向下,第一个是返回地址,然后就是参数.
因为stdcall是从右向左压入的,所以第一个参数在上面,拿EBP+返回地址的4小字节+4就是第一个参数[ebp+8],再加4就是第二个参数,依此类推.
拿EBP-4就是第一个临时变量,再减4就是第二个,同样类推.
stdcall中子程序扔掉主程序(调作者)压入栈中的参数就能保持堆\栈平衡,
ret n中n是参数个数*4.这里是两个参数所以ret 8.三个参数就ret 12.看不出你说明了什么.)
vc:
push arg2
push arg1
call fun
在调用函数fun之前,esp是变化的。所以调用完函数后要恢复回去,通过ret n来完成。
gcc:
movl arg2 4(%esp)//此时用的是给本函数的临时变量预分配的,如:subl $16, %esp下面细说
movl arg1 (%esp)
call fun
在调用函数fun之前,esp是不变的。所以调用完函数之后只要ret就行了,不用修正esp.
对于gcc的堆栈变化情况如下:
int fun1(int a,int b)
{
return a+b;
}
int fun(int a,int b)
{
int c,d;
c=a+2;
d=b+2
return fun(c,d);
}
//call fun
0x11111:fun(10,11);
____________|high address|
____________|11________|this function's arg2
____________|10________|this function's arg1
____________|ip_________|next instruction
ebp(=old esp)_|old ebp____|store the ebp(push ebp) and esp(movl %esp %ebp)
____________|c_________|temp variables1
____________|d_________|temp variables2
____________|d_________|called function's args2
new esp_____|c_________|called function's args1
____________|low address|
没有评论:
发表评论