gcc程序集输出标签表示什么?

时间:2012-03-21 06:34:30

标签: gcc assembly

我写了一个简单的C程序test.c

#include <stdio.h>
#include <stdlib.h>
int add(int a, int b);
int main()
{
    int i=5,j=10;
    int result;
    result = add(i, j);
    printf("result is %d\n", result);
}
int add(int a, int b)
{
    return (a + b);
}

我编译了它:

gcc -S -Os -o test.s test.c 

我得到了汇编文件test.s

        .file   "test3.c"
    .section    .rodata
.LC0:
    .string "result is %d\n"
    .text
.globl main
    .type   main, @function
main:
.LFB5:
    pushq   %rbp
.LCFI0:
    movq    %rsp, %rbp
.LCFI1:
    subq    $16, %rsp
.LCFI2:
    movl    $5, -12(%rbp)
    movl    $10, -8(%rbp)
    movl    -8(%rbp), %esi
    movl    -12(%rbp), %edi
    call    add
    movl    %eax, -4(%rbp)
    movl    -4(%rbp), %esi
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    leave
    ret
.LFE5:
    .size   main, .-main
.globl add
    .type   add, @function
add:
.LFB6:
    pushq   %rbp
.LCFI3:
    movq    %rsp, %rbp
.LCFI4:
    movl    %edi, -4(%rbp)
    movl    %esi, -8(%rbp)
    movl    -8(%rbp), %eax
    addl    -4(%rbp), %eax
    leave
    ret
.LFE6:
    .size   add, .-add
    .section    .eh_frame,"a",@progbits
.Lframe1:
    .long   .LECIE1-.LSCIE1
.LSCIE1:
    .long   0x0
    .byte   0x1
    .string "zR"
    .uleb128 0x1
    .sleb128 -8
    .byte   0x10
    .uleb128 0x1
    .byte   0x3
    .byte   0xc
    .uleb128 0x7
    .uleb128 0x8
    .byte   0x90
    .uleb128 0x1
    .align 8
.LECIE1:
.LSFDE1:
    .long   .LEFDE1-.LASFDE1
.LASFDE1:
    .long   .LASFDE1-.Lframe1
    .long   .LFB5
    .long   .LFE5-.LFB5
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI0-.LFB5
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI1-.LCFI0
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE1:
.LSFDE3:
    .long   .LEFDE3-.LASFDE3
.LASFDE3:
    .long   .LASFDE3-.Lframe1
    .long   .LFB6
    .long   .LFE6-.LFB6
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI3-.LFB6
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI4-.LCFI3
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE3:
    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-48)"
    .section    .note.GNU-stack,"",@progbits

我理解所有这些说明,但我真的不明白这些标签的含义。 .LC0.LFB5.LCFI0.LCFI1.LCFI2.LFE5,...这些标签由gcc自动生成。为什么需要这些标签?似乎有些标签是多余的。

  • gcc版本:4.1.2
  • machine:x86_64

2 个答案:

答案 0 :(得分:5)

编译器将为需要引用地址的任何位置生成标签,无论是跳转指令还是分支指令,还是数据位置。

编译器不需要创建直观命名的标签,因为它们仅由它生成的代码引用并且没有最终用户可见性,因此它生成或多或少的顺序命名标签,并使用一种方案来防止意外创建两个不同地点的相同标签。

使用两个(或更多)标签标记相同位置绝对没有缺点,因此没有尝试避免这种情况。这就是为什么有几个位置有两个顺序标签,没有插入操作。

如果您真的想知道LCxLFBx系列标签的含义,请阅读compiler source code。这是一个非平凡的代码库,因此期望花费数小时来寻找相关模块。


我遇到了挑战,所以有了一些编译器编写经验 - 我发现module /trunk/gcc/dwarf2out.c似乎使用相同的策略生成标签名称。查看第250行,了解符号含义的简洁线索。这个模块的大部分都决定了标签,但它的长度接近23,000行,所以它可以很好地测试你的好奇心。

答案 1 :(得分:1)

尝试使用gcc -fverbose-asm -fdump-tree-all -S -Os -o test.s test.c获取更多信息,特别是包含GCC内部表示的部分视图的许多“转储”文件test.c.*

不要被明显无用的标签打扰。我猜GCC可以为每个基本块生成一个。

回想一下,GCC在内部表示(Gimple,Tree)上的工作量很大。优化过程(有数百个)正在显着修改这些内部表示。大多数优化都在中端,在Gimple等工作......

我在http://gcc-melt.org/上的幻灯片有更详细的解释(你可以在网上找到很多其他的)。

考虑使用MELT(扩展GCC 4.6或更高版本的域特定语言)来探索(甚至修改)内部GCC表示。 MELT非常适合这个目标。


NB:

你的gcc-4.1已有好几年了。 GCC 4.7 刚刚发布(实际上是4.7.0 second release candidate)。自4.1以来,海湾合作委员会取得了很多进展(2006年出现)。如果你关心优化,你真的应该使用更新的版本(至少4.6)。您可以在gcc@gcc.gnu.org上查询有关 GCC内部的问题(开发或黑客编译器的列表),但大多数GCC贡献者都忘记了4.1的详细信息。使用gcc-help@gcc.gnu.org获取有关GCC的一般帮助(即如何构建或使用它)。