gcc - GCC为x86生成的 “push %ebp; movl %esp, %ebp”有什么用途?

标签 gcc assembly x86

这两条指令在gcc为x86机器生成的汇编代码中产生了什么影响:

push %ebp
movl %esp, %ebp

最佳答案

unwind的解释是字面上的事实(尽管有一个较小的方向性错误),但没有解释原因。
%ebp是您的堆栈框架的“基本指针”。它是C运行时用来访问堆栈上的局部变量和参数的指针。这是GCC生成的一些典型的函数序言代码(准确地说是g++),首先是C++源代码。

// junk.c++
int addtwo(int a)
{
    int x = 2;

    return a + x;
}

这将生成以下汇编程序。
.file   "junk.c++"
    .text
.globl _Z6addtwoi
    .type   _Z6addtwoi, @function
_Z6addtwoi:
.LFB2:
    pushl   %ebp
.LCFI0:
    movl    %esp, %ebp
.LCFI1:
    subl    $16, %esp
.LCFI2:
    movl    $2, -4(%ebp)
    movl    -4(%ebp), %edx
    movl    8(%ebp), %eax
    addl    %edx, %eax
    leave
    ret
.LFE2:
    .size   _Z6addtwoi, .-_Z6addtwoi
    .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
    .section    .note.GNU-stack,"",@progbits

现在解释一下序言代码(.LCFI2:之前的所有内容),首先:
  • pushl %ebp将调用函数的堆栈框架存储在堆栈中。
  • movl %esp, %ebp采用当前的堆栈指针,并将其用作被调用函数的框架。
  • subl $16, %esp为局部变量留出空间。

  • 现在,您的功能已准备就绪,可以开始业务了。与%ebp%寄存器的偏移为负的任何引用都是您的局部变量(在本示例中为x)。任何从%ebp%寄存器偏移正值的引用都是您传入的参数。

    最后一个有趣的地方是leave指令,它是x86汇编程序指令,它负责恢复调用函数的堆栈帧。通常,这已优化为C代码中更快的move %ebp %esppop %ebp%序列。但是,出于说明目的,我根本没有进行任何优化。

    关于gcc - GCC为x86生成的 “push %ebp; movl %esp, %ebp”有什么用途?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2515598/

    相关文章:

    用于指定 ARM 或 Thumb 模式的 C 预处理器/编译器指令?

    c++ - 链接使用不同版本的 gcc 编译的库

    assembly - Switch Case 汇编语言

    c - 帮助理解 x86 内联汇编中的 DIV 指令

    c++ - 在分析代码时,我应该使用匹配的 (gcc) 编译器优化标志吗?

    c - 错误 c2400 发现新行

    pointers - 为什么指向堆栈中地址的 ESP 每次跳转 4h?

    assembly - MIPS 整数 Sandy Bridge

    visual-studio - 结构的第一个成员在 VS 调试器中不可见

    windows - 如何在 Windows 上将 clang 与 mingw-w64 header 一起使用