问题re:使用gcc从我的C++生成的汇编

psi*_*er4 3 c++ linux x86 assembly

编译此代码:

int main ()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用:

gcc -S filename.cpp

...生成这个程序集:

        .file   "heloworld.cpp"
    .text
.globl main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    movl    $0, %eax
    popl    %ebp
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)

我的问题:

  1. 一切都在"."之后.一条评论?
  2. 什么是.LFB0:?
  3. 什么是.LFE0:?
  4. 为什么只有"int main()"和"return 0;"这么大的代码?

PS我读了很多汇编网书,很多(至少30个)教程,我所能做的就是复制代码并粘贴或重写它.现在我正在尝试一种不同的方法来尝试以某种方式学习它.问题是我确实理解什么是movl,pop等,但是不明白如何将这些东西结合起来使代码"流动".我不知道在asm中正确开始编写程序的位置或方法.我仍然像C++一样静态不动,但我想学习装配.

Syl*_*sne 7

正如其他人所说,.file,.text,...是汇编指令和.LFB0,.LFE0是局部标签.生成的代码中唯一的指令是:

pushl   %ebp
movl    %esp, %ebp
movl    $0, %eax
popl    %ebp
ret
Run Code Online (Sandbox Code Playgroud)

前两个指令是函数序言.帧指针存储在堆栈中并进行更新.eax寄存器中的下一个指令存储区0 (i386 ABI表示通过eax寄存器返回整数返回值).最后两个指令是功能结尾.恢复帧指针,然后函数通过ret指令返回其调用者.

如果使用编译代码-O3 -fomit-frame-pointer,代码将编译为两个指令:

xorl    %eax,%eax
ret
Run Code Online (Sandbox Code Playgroud)

第一个设置eax为0(只需要两个字节进行编码,而movl 0,%eax占用5个字节),第二个是ret指令.帧指针操作可以简化调试(没有它就可以回溯,但是更难).