为什么 GCC 不能编译 CLANG 生成的程序集?
Why can't GCC compile assembly produced by CLANG?
所以,我注意到 CLANG 生成的程序集无法用 GCC 编译。例如,对于一个简单的 "Hello world!" C 程序,CLANG 生成以下程序集:
.text
.file "hello.c"
.globl main # -- Begin function main
.p2align 4, 0x90
.type main,@function
main: # @main
.cfi_startproc
# %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq , %rsp
movabsq $.L.str, %rdi
movb [=10=], %al
callq printf
xorl %ecx, %ecx
movl %eax, -4(%rbp) # 4-byte Spill
movl %ecx, %eax
addq , %rsp
popq %rbp
.cfi_def_cfa %rsp, 8
retq
.Lfunc_end0:
.size main, .Lfunc_end0-main
.cfi_endproc
# -- End function
.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "Hello world!\n"
.size .L.str, 14
.ident "clang version 10.0.0 "
.section ".note.GNU-stack","",@progbits
.addrsig
.addrsig_sym printf
但是,当我尝试使用 gcc hello.s
编译该程序集时,我得到:
hello.s: Assembler messages:
hello.s:37: Error: unknown pseudo-op: `.addrsig'
hello.s:38: Error: unknown pseudo-op: `.addrsig_sym'
但是 GCC 和 CLANG 使用相同的汇编程序,即 GNU 汇编程序。那么,这里到底发生了什么?
这是什么目标?我从 movabsq $.L.str, %rdi
猜测 MacOS - 针对 Linux 编译器将使用 mov $.L.str, %edi
作为位置-dependent(非 PIE)代码(否则是相对于 RIP 的 LEA),并且 Windows 具有不同的调用约定。 clang 在这里没有使用相对于 RIP 的 LEA,这实际上是非常令人惊讶的;它会小于 movabs
.
据推测,.addrsig
指令是特定于 clang 的,对于 GAS 不知道如何创建的 MachO64 元数据。这可能也是 Apple 版本的 Clang,而不是主线 clang。
But both GCC and CLANG use the same assembler, the GNU Assembler.
不,它们使用相同的 asm 语法,但 clang 有一个集成的汇编器。正如@Marc Glisse 指出的那样,您可以使用 clang -no-integrated-as
来禁用它,这会将其提供给 GAS 并且可能会失败。
所以,我注意到 CLANG 生成的程序集无法用 GCC 编译。例如,对于一个简单的 "Hello world!" C 程序,CLANG 生成以下程序集:
.text
.file "hello.c"
.globl main # -- Begin function main
.p2align 4, 0x90
.type main,@function
main: # @main
.cfi_startproc
# %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq , %rsp
movabsq $.L.str, %rdi
movb [=10=], %al
callq printf
xorl %ecx, %ecx
movl %eax, -4(%rbp) # 4-byte Spill
movl %ecx, %eax
addq , %rsp
popq %rbp
.cfi_def_cfa %rsp, 8
retq
.Lfunc_end0:
.size main, .Lfunc_end0-main
.cfi_endproc
# -- End function
.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "Hello world!\n"
.size .L.str, 14
.ident "clang version 10.0.0 "
.section ".note.GNU-stack","",@progbits
.addrsig
.addrsig_sym printf
但是,当我尝试使用 gcc hello.s
编译该程序集时,我得到:
hello.s: Assembler messages:
hello.s:37: Error: unknown pseudo-op: `.addrsig'
hello.s:38: Error: unknown pseudo-op: `.addrsig_sym'
但是 GCC 和 CLANG 使用相同的汇编程序,即 GNU 汇编程序。那么,这里到底发生了什么?
这是什么目标?我从 movabsq $.L.str, %rdi
猜测 MacOS - 针对 Linux 编译器将使用 mov $.L.str, %edi
作为位置-dependent(非 PIE)代码(否则是相对于 RIP 的 LEA),并且 Windows 具有不同的调用约定。 clang 在这里没有使用相对于 RIP 的 LEA,这实际上是非常令人惊讶的;它会小于 movabs
.
据推测,.addrsig
指令是特定于 clang 的,对于 GAS 不知道如何创建的 MachO64 元数据。这可能也是 Apple 版本的 Clang,而不是主线 clang。
But both GCC and CLANG use the same assembler, the GNU Assembler.
不,它们使用相同的 asm 语法,但 clang 有一个集成的汇编器。正如@Marc Glisse 指出的那样,您可以使用 clang -no-integrated-as
来禁用它,这会将其提供给 GAS 并且可能会失败。