首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于汇编中push ebp和pop ebp指令的说明

关于汇编中push ebp和pop ebp指令的说明
EN

Stack Overflow用户
提问于 2010-09-04 01:24:16
回答 2查看 79K关注 0票数 47

我在汇编中使用了堆栈,但我不知道关于push ebp和pop的概念。

代码语言:javascript
复制
.intel_syntax noprefix

.include "console.i"

.text

askl:   .asciz  "Enter length: "
askb:   .asciz  "Enter breadth: "
ans:    .asciz  "Perimeter = "

_entry:

    push    ebp     # establishing stack-frame
    mov ebp, esp
    sub esp, 12

    Prompt  askl
    GetInt  [ebp-4]     # length
    Prompt  askb
    GetInt  [ebp-8]     # breadth

    mov eax, [ebp-4]    # eax = l
    add eax, [ebp-8]    # eax = l + b
    add eax, eax    # eax = 2 * (l + b)
    mov [ebp-12], eax

    Prompt  ans
    PutInt  [ebp-12]
    PutEoL

    mov esp, ebp
    pop ebp     # unwinding stack-frame
    ret

.global _entry

.end
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-09-04 01:35:58

也许你想知道这一点:

代码语言:javascript
复制
push    ebp
mov ebp, esp
sub esp, 12

这些行被称为汇编函数序号。前两条指令保存先前的基指针( EBP ),并将EBP设置为指向堆栈上的该位置(就在返回地址的正下方)。这会将EBP设置为。

sub esp,12行为函数中的局部变量节省了空间。可以使用诸如[ebp - 4]之类的寻址模式来寻址该空间。任何函数参数的推送/弹出,或者call指令本身推送返回地址,或者我们调用的函数的堆栈框架,都将在当前ESP的这个保留空间下发生。

最后,您将拥有:

代码语言:javascript
复制
mov esp, ebp         ; restore ESP
pop ebp              ; restore caller's EBP
ret                  ; pop the return address into EIP

这与开场白相反(即结束语),因此可以恢复之前的上下文。这有时被称为“拆卸”堆栈帧。

(EBP是非易失性的,也称为call--保留在所有标准的x86调用约定中:如果您修改它,您必须恢复调用者的值。)

leave指令所做的正是这两条指令所做的事情,一些编译器使用它来节省代码大小。(enter 0,0非常慢,而且从未使用过(https://agner.org/optimize/);leave的效率与mov +pop差不多。)

请注意,使用EBP作为帧指针是可选的,编译器不会对优化代码中的大多数函数执行此操作。相反,它们保存单独的元数据以允许堆栈展开/回溯。

票数 79
EN

Stack Overflow用户

发布于 2010-09-04 01:26:58

ebp称为基指针或帧指针。在进入函数时,您可以按下它(以保存调用函数的值)。然后,将堆栈指针esp复制到ebp中,以便ebp现在指向函数的堆栈帧。在函数结束时,然后弹出ebp,以便恢复调用函数的值。

为了澄清到底发生了什么- push指令将指定寄存器(本例中为ebp)的值放到堆栈上,并将堆栈指针递减适当的量。pop操作正好相反-它递增堆栈指针,并从堆栈中获取一个值并将其放入指定的寄存器中。

票数 50
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3638075

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档