Function 为什么在通话中要将ESP保留在EBP中?

Function 为什么在通话中要将ESP保留在EBP中?,function,assembly,x86,callstack,cpu-registers,Function,Assembly,X86,Callstack,Cpu Registers,我的意思是,当你输入通话时,你应该将ESP寄存器的值复制到EBP,他还提供了以下模板: function_label: pushl %ebp movl %esp, %ebp < normal function code goes here> movl %ebp, %esp popl %ebp ret 功能标签: 推力%ebp 移动%esp,%ebp 移动%ebp,%esp popl%ebp ret 我不明白为什么这是必要的。当您将

我的意思是,当你输入通话时,你应该将
ESP
寄存器的值复制到
EBP
,他还提供了以下模板:

function_label:
    pushl %ebp
    movl %esp, %ebp
    < normal function code goes here>
    movl %ebp, %esp
    popl %ebp
    ret
功能标签:
推力%ebp
移动%esp,%ebp
<此处为正常功能代码>
移动%ebp,%esp
popl%ebp
ret
我不明白为什么这是必要的。当您将某个内容推到函数中时,您显然想要将其弹出,从而将
ESP
恢复为其原始值

那么为什么要使用此模板呢?
那么
EBP
寄存器有什么用呢

我显然错过了什么,但那是什么

当您将某个内容推到函数内部时,您显然打算将其弹出

这只是使用堆栈的部分原因。更常见的用法是代码段中缺少的一种,即存储局部变量。设置EBP后,您看到的下一个常见代码是ESP上的减法,相当于本地变量存储所需的空间量。这当然也很容易平衡,只需在函数结尾处添加相同的数量。当代码同时使用C99可变长度数组或非标准但常用的_alloca()函数时,这会变得更加困难。能够从EBP恢复ESP使这变得简单

更重要的是,没有必要像这样设置堆栈帧。大多数x86编译器都支持名为“帧指针省略”的优化选项。在MSVC上使用GCC的-fomit帧指针/Oy打开。这使得EBP寄存器可供一般使用,这对于缺少cpu寄存器的x86非常有用


不过,这种优化有一个非常严重的缺点。如果EBP寄存器不指向堆栈帧的开始,执行堆栈遍历将变得非常困难。当您需要调试代码时,这很重要。堆栈跟踪对于了解代码是如何崩溃的非常重要。当您从客户那里得到崩溃的“核心转储”时,这是非常宝贵的。非常有价值,Microsoft同意使用Windows二进制文件来帮助客户诊断崩溃。

这称为堆栈帧,用于创建局部变量,这些局部变量在函数完成后会被销毁。@Sp。我为什么不弹出这些局部变量?/为什么弹跳不能摧毁它们?抱歉有点慢。也许你需要看看这个答案,更好的解释是,它使代码更可读和可调试,这不是必需的。堆栈框架设置的堆栈指针在整个函数中保持静态,因此局部变量相对于堆栈指针始终处于相同的偏移量。然后,真正的堆栈指针可以为其他函数调用添加和删除要设置的内容。另一种方法是局部变量/数据在整个函数中使用堆栈时更改其偏移量,这样更难读取/跟踪/调试。当然,这要快得多。