logo资料库

函数调用时栈与寄存器的变化.pdf

第1页 / 共4页
第2页 / 共4页
第3页 / 共4页
第4页 / 共4页
资料共4页,全文预览结束
在函数 a 中调用函数 b。 两个函数如下: int a() { int i=0; int c; b(i); /*b 函数的返回地址指向紧接之后的语句,即 return 0;*/ return 0; } int b(int i) int d=i; return 0; { } b 函数对应的汇编程序 b: pushl %ebp //ebp寄存器内容压栈,即保存b函数的上级调用函数的栈基地址 movl %esp, %ebp //esp值赋给ebp,设置b函数的栈基址 subl $4, %esp //分配栈地址给局部变量d leal 8(%ebp), %eax //将参数i的地址传递给eax,i参数的地址在ebp上方8个字节处,两者中间是b函数的 返回地址和ebp movl %eax, -4(%ebp) // d = i movl $0, %eax //返回值0传给eax寄存器 leave //将ebp值赋给esp,pop先前栈内的上级函数栈的基地址给ebp,恢复原栈基址 //相当于movl %ebp,%esp popl %ebp ret //将 a 函数中的“return 0;”语句的地址存入指令寄存器 IP a 函数执行到调用 b 函数之前时的栈
调用 b(i)执行到 b 函数汇编的 movl %esp, %ebp 语句前时的栈 执行完 subl $4, %esp 语句后的栈
此时 b 的参数 int i 处于%ebp+8 的位置 ,而 b 函数的局部变量 d 处于%ebp-4 的位 置。这里要注意,函数参数压栈按照从右到左的顺序依次进行。 执行 leave 时 esp 指向 ebp 当前位置 ,而 pop ebp 后 栈的分布如下
此时 ip 取 esp 寄存器指向的栈所存的返回地址 ,而 esp+4,即清空了 b 函数除参数以 外的栈,此时如果是以_stdcall 方式调用则 b 函数自动弹出所有参数,如果是以_cdecl 方式调用,则由 a 函数调整堆栈至初始状态。 NJU 顾伟颢
分享到:
收藏