【问题标题】:Clang's ASM output vs GCC'sClang 的 ASM 输出与 GCC 的对比
【发布时间】:2012-11-17 12:58:42
【问题描述】:

(我对汇编语言几乎一无所知)。

我正在尝试关注this 教程。

问题在于他的编译器和我的测试设置(Linux 32 位上的 gcc)产生的输出完全不同,而且输出比我的主要设置(OSX 64 位上的 clang)要少得多。

这是我对int main() {} 的输出

32 位 Linux 上的 gcc

$ cat blank.c
int main() {}
$ gcc -S blank.c              
$ cat blank.s
    .file   "blank.c"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    popl    %ebp
    .cfi_def_cfa 4, 4
    .cfi_restore 5
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
    .section    .note.GNU-stack,"",@progbits

Mac OSX 64 位上的叮当声

$ cat blank.c
int main() {}
$ clang -S blank.c
$ cat blank.s
    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
Leh_func_begin0:
## BB#0:
    pushq   %rbp
Ltmp0:
    movq    %rsp, %rbp
Ltmp1:
    movl    $0, %eax
    popq    %rbp
    ret
Leh_func_end0:

    .section    __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame0:
Lsection_eh_frame0:
Leh_frame_common0:
Lset0 = Leh_frame_common_end0-Leh_frame_common_begin0 ## Length of Common Information Entry
    .long   Lset0
Leh_frame_common_begin0:
    .long   0                       ## CIE Identifier Tag
    .byte   1                       ## DW_CIE_VERSION
    .asciz   "zR"                   ## CIE Augmentation
    .byte   1                       ## CIE Code Alignment Factor
    .byte   120                     ## CIE Data Alignment Factor
    .byte   16                      ## CIE Return Address Column
    .byte   1                       ## Augmentation Size
    .byte   16                      ## FDE Encoding = pcrel
    .byte   12                      ## DW_CFA_def_cfa
    .byte   7                       ## Register
    .byte   8                       ## Offset
    .byte   144                     ## DW_CFA_offset + Reg (16)
    .byte   1                       ## Offset
    .align  3
Leh_frame_common_end0:
    .globl  _main.eh
_main.eh:
Lset1 = Leh_frame_end0-Leh_frame_begin0 ## Length of Frame Information Entry
    .long   Lset1
Leh_frame_begin0:
Lset2 = Leh_frame_begin0-Leh_frame_common0 ## FDE CIE offset
    .long   Lset2
Ltmp2:                                  ## FDE initial location
Ltmp3 = Leh_func_begin0-Ltmp2
    .quad   Ltmp3
Lset3 = Leh_func_end0-Leh_func_begin0   ## FDE address range
    .quad   Lset3
    .byte   0                       ## Augmentation size
    .byte   4                       ## DW_CFA_advance_loc4
Lset4 = Ltmp0-Leh_func_begin0
    .long   Lset4
    .byte   14                      ## DW_CFA_def_cfa_offset
    .byte   16                      ## Offset
    .byte   134                     ## DW_CFA_offset + Reg (6)
    .byte   2                       ## Offset
    .byte   4                       ## DW_CFA_advance_loc4
Lset5 = Ltmp1-Ltmp0
    .long   Lset5
    .byte   13                      ## DW_CFA_def_cfa_register
    .byte   6                       ## Register
    .align  3
Leh_frame_end0:


.subsections_via_symbols

是否可以在我的 Mac 上生成类似的汇编输出,以便我可以按照教程进行操作?或者这个汇编代码是特定于平台的?如果是,我可以使用clang 上的哪些标志来生成更少冗长/样板(?)代码?

【问题讨论】:

  • 注意:没有理由期望两个不同的编译器产生相同的输出。不仅是 gcc vs clang,还有一个版本到下一个版本。所以教程中的版本与您计算机上的版本相比。

标签: gcc assembly llvm clang


【解决方案1】:

确保您在 Mac OSX 64 位上使用 clang -m32 指示 clang 生成 32 位代码,您基本上不必担心其他差异。

gcc 输出中的.cfi_XXX 指令和clang 输出中.section __TEXT,__eh_frame 之后的行都用于生成用于堆栈展开的.eh_frame 部分。详情见:http://blog.mozilla.org/respindola/2011/05/12/cfi-directives/

【讨论】:

  • 对不起一个菜鸟问题,但是 64 位汇编总是比 32 更冗长吗?可以更简洁吗? clang -m32 给了我一个很好的有用输出,但它必须用 -m32 编译,并且可能也有 32 位程序的限制。
  • @user1527166,“64 位汇编更冗长吗?”在您的情况下,这确实是一个错误的问题。您尝试遵循的教程会生成 32 位 x86 代码,这些代码无法按原样用于 x86-64。例如。在“使用 Ruby 编写编译器”教程的第 2 步中,他尝试通过调用 puts() 函数来打印“Hello World”。用于调用 C 函数的汇编代码在 x86 和 x86-64 上是不同的。尝试先阅读本书的第 3 章和第 4 章 download.savannah.gnu.org/releases/pgubook 然后阅读 cs.washington.edu/education/courses/401/11au/lectures/…
【解决方案2】:

使用gcc -fno-asynchronous-unwind-tables 编译您的程序。或者只是忽略各种.cfi_XYZ 指令。对于clang 的情况,只需不要关注__eh_frame 部分。请记住,两个不同的编译器生成相同代码的情况很少见,即使来自相同的源也是如此。

【讨论】:

    猜你喜欢
    • 2013-09-22
    • 1970-01-01
    • 2013-11-19
    • 2017-04-05
    • 1970-01-01
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多