pushl %ebp
movl %esp, %ebp
这是我的理解:
移动到堆栈顶部。但是,我不确定%ebp或%ebp寄存器中存储的是什么。
如果我使用这个%esp的基本理解是Sourche和%ebp是目的地。所以我将寄存器%esp中的内容移动到寄存器%ebp中。寄存器%esp是什么?
答案 0 :(得分:1)
按照惯例,esp是堆栈指针,ebp是帧指针。请参阅Intel x86 Function-call Conventions - Assembly View。
因此,通过这种约定,当进行调用时,保留当前帧指针(ebp,调用者的帧指针)(以便在返回调用者时可以恢复它 - 所以从调用者的角度来看帧指针永远不会改变)。然后将当前堆栈指针(esp)存储在ebp中,使其成为被调用代码的帧指针。
答案 1 :(得分:0)
%esp
是当前的堆栈指针,即。它的顶部。 %ebp
表示当前函数的基指针。它是必需的,因此函数知道其堆栈开始的位置。您需要将之前的函数%ebp
(pushl %ebp
)保存到堆栈中才能分配自己的函数。
稍后,当再次向上移动堆栈时,每个函数都会恢复其基本指针,以便能够继续工作。
答案 2 :(得分:0)
pushl %ebp
movl %esp, %ebp
这段代码的“样式”是源是第一个参数,第二个是目的地;在英特尔风格中你会看到像
这样的东西 push ebp
mov ebp, esp
这是对这些代码行的简单解释。意义取决于。通常,它是由高级语言(例如C)生成的函数的常见序言,尊重某些调用约定。 epilog应该看起来像
movl %ebp, %esp
popl %ebp
ret
通过递减esp并使用ebp访问数据,可以在堆栈上“创建”局部变量的空间,保留esp的正常使用,例如对于另一个函数的另一个调用(返回地址被压入堆栈),并避免覆盖局部变量:递减的esp和基本ebp之间的内存类似于当前函数可以使用的堆栈上的“保留区域”。
由于每个输入的函数都保留了ebp和esp,递归函数调用(直到达到堆栈限制)在此调用约定机制中相当自然,并且嵌套函数可以被称为 ad libitum (直到堆栈结束!)。