2012-11-17 37 views
0

(我幾乎不懂任何關於彙編語言的東西)。Clang的ASM輸出與GCC的

我正在嘗試關注this教程。

問題是他的編譯器和我的測試設置(Linux上32位的gcc)產生完全不同的輸出,並且比我的主設置(OSX 64位上的clang)輸出要少得多。

這裏是我在Linux 32 int main() {}

GCC位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 

$ 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產生類似組件輸出,所以我可以按照教程?或者這個彙編代碼是特定於平臺的?如果是這樣,我可以使用clang上的哪些標記生成較少的詳細/樣板代碼?

+2

注意:沒有理由期望兩個不同的編譯器生成相同的輸出。不僅僅是gcc vs clang,而是一個版本。因此教程中的版本與計算機上的版本相比較。 –

回答

1

gcc -fno-asynchronous-unwind-tables編譯程序。或者忽略各種.cfi_XYZ指令。對於clang的情況,請不要關注__eh_frame部分。請記住,兩個不同的編譯器生成相同的代碼是相當罕見的,即使來自相同的源代碼也是如此。

4

請確保您指示clang在Mac OSX 64位上使用clang -m32生成32位代碼,您基本上不必擔心其他差異。

gcc輸出中的.cfi_XXX指令和clang輸出中的.section __TEXT,__eh_frame之後的行都用於生成用於堆棧展開的.eh_frame部分。有關詳細信息,請參閱:http://blog.mozilla.org/respindola/2011/05/12/cfi-directives/

+0

對不起noob問題,但64位程序集總是比32更冗長?它可以更簡潔嗎? 'clang -m32'給了我一個很好的有用的輸出,但它必須用'-m32'編譯,並且可能也有32位程序的限制。 – user1527166

+1

@ user1527166,「64位程序集更詳細嗎?」在你的情況下問真的是一個錯誤的問題。您試圖遵循的教程會生成32位x86代碼,這些代碼不適用於x86-64。 E.g.在「在Ruby中編寫編譯器」教程的第2步中,他嘗試通過調用'puts()'函數來打印「Hello World」。用於調用C函數的彙編代碼在x86和x86-64上不同。請先閱讀本書的第3章和第4章http://download.savannah.gnu.org/releases/pgubook/ 然後閱讀https://www.cs.washington.edu/education/courses/401/11au/lectures /M-x86-64-project.pdf – scottt