现在的位置: 首页 > 综合 > 正文

C语言函数调用栈剖析

2018年02月03日 ⁄ 综合 ⁄ 共 709字 ⁄ 字号 评论关闭

理解调用栈最重要的两点是:栈的结构,EIP/EBP/ESP寄存器的作用。

1.栈结构

首先必须明确一点也是非常重要的一点,栈是向下生长的,所谓向下生长是指从内存高地址->低地址的路径延伸,那么就很明显了,栈有栈底和栈顶,那么栈顶的地址要比栈底低。

2.EIP/EBP/ESP寄存器

对x86体系的CPU而言,在函数调用过程中,系统会用到下面三种寄存器:
1.EIP寄存器里存储的是函数调用完CPU下次要执行的指令的地址。
2.EBP寄存器里存储的是是栈的栈底指针,通常叫栈基址,EBP在未受改变之前始终指向栈帧的开始,也就是栈底,所以EBP的用途是在堆栈中寻址用的。
3.ESP寄存器可称为“ 栈指针”。ESP是会随着数据的入栈和出栈移动的,也就是说,ESP始终指向栈顶。

3.函数调用过程

假设函数A调用函数B,我们称A函数为"调用者",B函数为“被调用者”则函数调用过程可以这么描述:
1先将调用者A的堆栈的基址EBP入栈,以保存之前任务的信息。
2然后将调用者A的栈顶指针ESP的值赋给EBP,作为新的基址即被调用者B的栈底。
3然后在这个基址即被调用者B的栈底上开辟一般用sub指令相应的空间用作被调用者B的栈空间。
4函数B返回后,当前栈帧的EBP即恢复为调用者A的栈顶ESP,即栈顶恢复到函数B被调用之前的位置;然后调用者A再从恢复后的栈顶上弹出之前的EBP值可以这么做是因为这个值在函数B被调用前被压入堆栈。这样,EBP和ESP就都恢复了调用函数B前的位置,也就是栈恢复成函数B调用前的状态。

4.函数调用栈如下图所示:

解释:  //EBP 基址指针,是保存调用者函数的地址,总是指向函数栈栈底,ESP被调函数的指针,总是指向函数栈栈顶。

抱歉!评论已关闭.