【问题标题】:Running an external compiler (godbolt) assembly运行外部编译器 (godbolt) 程序集
【发布时间】:2020-08-01 18:48:22
【问题描述】:

假设我有以下 C 程序:

int main() {
    int a = 1;
    int b = 2;
    return a + b;
}

Compiler Explorer 上编译这个给了我:

main:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    $1, -4(%rbp)
        movl    $2, -8(%rbp)
        movl    -4(%rbp), %edx
        movl    -8(%rbp), %eax
        addl    %edx, %eax
        popq    %rbp
        ret

这(有点)类似于通过gcc 编译给我的东西,至少对于main 部分。但是,这不会作为“独立”编译,例如,如果我将 asm 复制粘贴到文件 gb.s 并运行 $ gcc gb.s 我会收到错误:

/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 11
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 1 has invalid symbol index 12
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 2 has invalid symbol index 2
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 3 has invalid symbol...
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

-- 除非我还在顶部包含.globl,例如:

.globl  main

由此,我有两个问题:

  • 为什么 godbolt 编译器不在顶部包含它,或者其他什么东西使它自包含?
  • 有没有办法运行gcc 并告诉它main 是主要/全局部分而不将.globl main 放在顶部?

【问题讨论】:

  • “我得到一个错误”你不认为你应该把它全部包含进去吗?
  • godbolt 也确实包含该内容,但您已将其过滤掉。请参阅“过滤器”选项。请注意,godbolt 只是为您运行 gcc -S 并格式化输出。
  • 为什么 Godbolt 编译器不在顶部包含它,或者其他什么东西使它自包含? - 因为这与它的目的相反。它正在删除样板,因此您可以看到有趣的部分。 How to remove "noise" from GCC/clang assembly output?。如果你了解 asm,你就知道函数在 .text 中,并且是带有 .type 函数的全局符号。该数据位于.rodata.data 中,具体取决于只读与否。

标签: c assembly gcc


【解决方案1】:

一个好人 Matt Godbolt 付出了很多努力来过滤生成的程序集中的所有噪音

.file   "example.c"
        .text
.Ltext0:
        .globl  main
        .type   main, @function
main:
.LFB0:
        .file 1 "./example.c"
        .loc 1 1 12
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        .loc 1 2 9
        movl    $1, -4(%rbp)
        .loc 1 3 9
        movl    $2, -8(%rbp)
        .loc 1 4 14
        movl    -4(%rbp), %edx
        movl    -8(%rbp), %eax
        addl    %edx, %eax
        .loc 1 5 1
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
.Letext0:
        .section        .debug_info,"",@progbits
.Ldebug_info0:
        .long   0x6e
        .value  0x4
        .long   .Ldebug_abbrev0
        .byte   0x8
        .uleb128 0x1
        .long   .LASF0
        .byte   0xc
        .long   .LASF1
        .long   .LASF2
        .quad   .Ltext0
        .quad   .Letext0-.Ltext0
        .long   .Ldebug_line0
        .uleb128 0x2
        .long   .LASF3
        .byte   0x1
        .byte   0x1
        .byte   0x5
        .long   0x6a
        .quad   .LFB0
        .quad   .LFE0-.LFB0
        .uleb128 0x1
        .byte   0x9c
        .long   0x6a
        .uleb128 0x3
        .string "a"
        .byte   0x1
        .byte   0x2
        .byte   0x9
        .long   0x6a
        .uleb128 0x2
        .byte   0x91
        .sleb128 -20
        .uleb128 0x3
        .string "b"
        .byte   0x1
        .byte   0x3
        .byte   0x9
        .long   0x6a
        .uleb128 0x2
        .byte   0x91
        .sleb128 -24
        .byte   0
        .uleb128 0x4
        .byte   0x4
        .byte   0x5
        .string "int"
        .byte   0
        .section        .debug_abbrev,"",@progbits
.Ldebug_abbrev0:
        .uleb128 0x1
        .uleb128 0x11
        .byte   0x1
        .uleb128 0x25
        .uleb128 0xe
        .uleb128 0x13
        .uleb128 0xb
        .uleb128 0x3
        .uleb128 0xe
        .uleb128 0x1b
        .uleb128 0xe
        .uleb128 0x11
        .uleb128 0x1
        .uleb128 0x12
        .uleb128 0x7
        .uleb128 0x10
        .uleb128 0x17
        .byte   0
        .byte   0
        .uleb128 0x2
        .uleb128 0x2e
        .byte   0x1
        .uleb128 0x3f
        .uleb128 0x19
        .uleb128 0x3
        .uleb128 0xe
        .uleb128 0x3a
        .uleb128 0xb
        .uleb128 0x3b
        .uleb128 0xb
        .uleb128 0x39
        .uleb128 0xb
        .uleb128 0x49
        .uleb128 0x13
        .uleb128 0x11
        .uleb128 0x1
        .uleb128 0x12
        .uleb128 0x7
        .uleb128 0x40
        .uleb128 0x18
        .uleb128 0x2117
        .uleb128 0x19
        .uleb128 0x1
        .uleb128 0x13
        .byte   0
        .byte   0
        .uleb128 0x3
        .uleb128 0x34
        .byte   0
        .uleb128 0x3
        .uleb128 0x8
        .uleb128 0x3a
        .uleb128 0xb
        .uleb128 0x3b
        .uleb128 0xb
        .uleb128 0x39
        .uleb128 0xb
        .uleb128 0x49
        .uleb128 0x13
        .uleb128 0x2
        .uleb128 0x18
        .byte   0
        .byte   0
        .uleb128 0x4
        .uleb128 0x24
        .byte   0
        .uleb128 0xb
        .uleb128 0xb
        .uleb128 0x3e
        .uleb128 0xb
        .uleb128 0x3
        .uleb128 0x8
        .byte   0
        .byte   0
        .byte   0
        .section        .debug_aranges,"",@progbits
        .long   0x2c
        .value  0x2
        .long   .Ldebug_info0
        .byte   0x8
        .byte   0
        .value  0
        .value  0
        .quad   .Ltext0
        .quad   .Letext0-.Ltext0
        .quad   0
        .quad   0
        .section        .debug_line,"",@progbits
.Ldebug_line0:
        .section        .debug_str,"MS",@progbits,1
.LASF2:
        .string "/home/ce"
.LASF3:
        .string "main"
.LASF0:
        .string "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g"
.LASF1:
        .string "./example.c"
        .ident  "GCC: (Compiler-Explorer-Build) 9.3.0"
        .section        .note.GNU-stack,"",@progbits

简单地取消选中“指令”

【讨论】:

    【解决方案2】:

    godbolt 编译器为什么不在顶部包含它,或者其他使其独立的东西?

    Godbolt (Compiler Explorer) 不是编译器,而是用于研究多种语言的多种编译器输出的 Web 界面。由于它主要用于研究优化和代码生成,因此默认情况下会过滤其输出以显示相关内容。

    有没有办法运行 gcc 并告诉它 main 是 main/global 部分而不将 .globl main 放在顶部?

    我认为这是 XY 问题的一个实例。假设您想要查看本地 GCC 生成的内容,您应该使用 -S 选项,该选项将为您提供未经过滤的输出。然后,您可以再次将其传递给 GCC 以链接它。

    换句话说,如果您想要将实际程序编译成程序集然后链接它们,则不需要 Compiler Explorer。

    【讨论】:

    • 你试过godbolt中的-S方法了吗?
    • @P__J__ 我不确定你想说什么。我说的是他们当地的 GCC,而不是 CE 的输出。为清晰起见进行了编辑。
    • 这家伙想要godbolt - 因为它更容易更快,特别是如果你想分享一些东西
    • @P__J__ 不,OP 没有说过“想要 Compiler Explorer”。 OP 正在讨论将程序集链接到一个可运行的程序,以及为什么 CE 的输出不能直接链接。
    • @P__J__:Godbolt 已经通过了-S,在选项框中再添加一个将无济于事。不过滤 Godbolt 上的指令是 UI 下拉列表中的一个选项。 (然后你可以从一些你没有在本地安装的有趣的编译器复制/粘贴可构建的 asm,例如为了对其进行基准测试。所以有一个用例可以做到这一点,而不是在本地使用 gcc -O2 -S。)
    猜你喜欢
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    相关资源
    最近更新 更多