函数调用栈维护过程
Posted hadesblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数调用栈维护过程相关的知识,希望对你有一定的参考价值。
涉及到以下汇编指令:
pushl: 入栈
ebp指向栈底 esp指向栈顶
入栈时只需要将esp下移, 将入栈的值放入esp指向的地址,如下图所示:
popl: 出栈
先将栈顶的数据保存,再将esp上移
call:顾名思义,调用一个函数
调用一个函数需要将当前执行到的指令位置(eip寄存器的值)保存,也就是使用pushl指令入栈。再将eip寄存器的值置为要跳转的地址。
ret: 结束当前函数
恢复上个函数的执行位置,也就是将esp指向的地址保存至eip,再将esp上移。
观察以下代码生成的汇编语言:
#include <iostream> using namespace std; int power(int x) { return x*x; } int main() { int res = power(3); cout << res <<endl; return 0; }
g++ -S test.cpp -o test.S
得到生成的汇编代码:
_Z5poweri: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax imull 8(%ebp), %eax popl %ebp ret main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $20, %esp pushl $3 call _Z5poweri addl $4, %esp movl %eax, -12(%ebp) subl $8, %esp pushl -12(%ebp) pushl $_ZSt4cout call _ZNSolsEi addl $16, %esp subl $8, %esp pushl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ pushl %eax call _ZNSolsEPFRSoS_E addl $16, %esp movl $0, %eax movl -4(%ebp), %ecx leave leal -4(%ecx), %esp ret
power函数名经过name-mangling转化为_Z5poweri,_是开始标志,5是函数名长度,i表示返回值为int。
调用power函数的流程如下:
main函数先将函数参数保存,再调用call指令调用power函数,保存eip的值。就有了下图的第一个状态。
以上是关于函数调用栈维护过程的主要内容,如果未能解决你的问题,请参考以下文章