x86 的 ebp 寄存器,可能比 cr3 更重要,好好掰扯一下 ebp

在 x86 架构的计算机中,ebp(Extended Base Pointer)寄存器通常用于指向当前函数的栈帧(stack frame)的基地址。栈帧是函数调用期间在栈上分配的一块内存区域,用于存储局部变量、函数参数、返回地址和其他临时数据。Linux 中,用户注册的信号处理函数,就是从内核态回到用户态时,发现有此信号,于是内核修改用户态的栈,增加一个栈帧来对应执行信号处理函数,从而实现了 Linux 信号机制。

1,栈帧和 ebp 的作用

   1.1. 栈帧的结构:

    每次函数调用时,都会在栈上分配一个新的栈帧。栈帧通常包含以下内容:

            <1> 函数的局部变量

            <2> 函数参数

            <3> 返回地址(调用函数的地址)

            <4> 前一个栈帧的基地址(即调用者的 ebp 值)

   1.2. ebp 的作用:

             <1> ebp 寄存器指向当前栈帧的基地址。通过 ebp,程序可以方便地访问栈帧中的各个元素

            <2> 在函数调用时,ebp 的值会被保存到栈上,并且 ebp 会被更新为当前栈帧的基地址

             <3> 当函数返回时,ebp 会被恢复为调用者的栈帧基地址。

2,函数调用过程中的 ebp 使用

    2.1. 函数入口:

在函数入口处,当前的 ebp 值会被保存到栈上,然后 ebp 会被更新为当前栈顶的值。这通常通过以下汇编指令实现:

push ebp        ; 保存调用者的 ebp 值

mov ebp, esp    ; 更新 ebp 为当前栈顶的值

这是32为x86中的寄存器名字,x86_64 有对应的急促起,rbp,rsp等

C语言函数的 push ebp 的作用是压栈保存调用函数的栈帧基址;

被调用这的栈帧基址如何获得呢?即调用者的栈帧栈顶地址,所以调用者执行

mov   ebp,   esp;

即将调用者的栈帧栈顶地址,作为被调者的帧基址使用。

实现了栈帧堆叠效果,Linux中栈向下增长:

main() -> func1() -> func2() ->

——————————

全局数据区

main() 栈帧

func1() 栈帧

func2() 栈帧

 以下面的hello.c 中的 add() 为例:

int add(int x, int y)
{
	return x+y;
}

int main()
{

	int s = 3;
	int t = 4;
	int u = 5;
	u = u + add(s, 5);

	return u;
}

生成 -m32 汇编代码如下:

注意,

x86 call 指令,附带功能:将下一条指令的偏移地址ip入栈,然后跳转至被调函数标号处;

调用结束时,ret指令会将IP弹出

这对应着编译原理中活动记录的内容。C语言的函数栈帧即函数执行一次的活动记录。

main中 call add指令之后的  addl $8, %esp,就是俗称的平栈,esp本来是子函数活动记录的TOP指针,现在返回后应当恢复回来。

即,移动TOP这个动作,在x86中,是调用者返回后做的第一件事儿,即返回地址的第一条指令是修改TOP值,即esp寄存器的值。通常是 add esp, 8 之类的;这个8是由实际参数个数和其他数据的长度决定。

    2.2. 函数内部:

在函数内部,通过 ebp 可以访问函数参数和局部变量。例如:

  • 函数参数:[ebp + 8] 表示第一个参数,[ebp + 12] 表示第二个参数,依此类推。

  • 局部变量:[ebp - 4] 表示第一个局部变量,[ebp - 8] 表示第二个局部变量,依此类推。

    2.3. 函数返回:

在函数返回时,ebp 会被恢复为调用者的栈帧基地址,然后栈顶指针 esp 会被更新为 ebp 的值,如图一所示。

这通常通过以下汇编指令实现:

        pop     ebp
        ret

其中:

     pop ebp         ; 恢复调用者的 ebp 值,栈帧基址,即活动记录基地址

     ret             ; 返回调用者,会自动将call指令push IP寄存器值,再自动pop 出去恢复IP寄存器的值,确保调用程序调用子函数返回后继续往下执行。

3,示例 intel 汇编格式

以下是一个简单的 C 函数及其对应的汇编代码示例:
 

int add(int x, int y)
{
	return x+y;
}

对应的汇编代码可能如下:

add:
        push    ebp
        mov     ebp, esp
        mov     edx, DWORD PTR [ebp+8]
        mov     eax, DWORD PTR [ebp+12]
        add     eax, edx
        pop     ebp
        ret

 实际返回表效果:

4,总结

ebp 寄存器在 x86 架构中用于指向当前函数的栈帧基地址。

通过 ebp,程序可以方便地访问栈帧中的函数参数和局部变量。

在函数调用过程中,ebp 的值会被保存和恢复,以维护栈帧的结构。

通过理解 ebp 的作用,可以更好地理解函数调用过程中的栈帧管理和内存布局。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值