ASM изход на Clang срещу GCC

(Все още не знам почти нищо за асемблерния език).

Опитвам се да следвам това урок.

Проблемът е, че неговият компилатор и моята тестова настройка (gcc на Linux 32 бита) произвеждат напълно различен и значително по-малък резултат от основната ми настройка (кланг на OSX 64 бита).

Ето моите резултати за int main() {}

gcc на Linux 32 бита

$ 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

clang на 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 мога да използвам, за да генерирам по-малко многословен/шаблонен (?) код?


person user1527166    schedule 17.11.2012    source източник
comment
Забележка: няма причина да очаквате два различни компилатора да произвеждат еднакъв резултат. не само gcc срещу clang, но една версия към следващата. така че версията в урока срещу версията, която имате на вашия компютър.   -  person old_timer    schedule 17.11.2012


Отговори (2)


Уверете се, че сте инструктирали clang да генерира 32-битов код с clang -m32 на Mac OSX 64-битов и по същество не е нужно да се притеснявате за другите разлики.

Както директивите .cfi_XXX в изхода на gcc, така и редовете след .section __TEXT,__eh_frame в изхода на clang се използват за генериране на секцията .eh_frame за размотаване на стека. За подробности вижте: http://blog.mozilla.org/respindola/2011/05/12/cfi-directives/

person scottt    schedule 17.11.2012
comment
Съжалявам за въпроса, но 64-битовото асемблиране винаги ли е по-подробно от 32? Може ли по-сбито? clang -m32 ми даде хубав полезен резултат, но той трябва да бъде компилиран с -m32 и вероятно ще има ограничения и за 32-битова програма. - person user1527166; 17.11.2012
comment
@user1527166, 64-битовото асемблиране по-подробно ли е? наистина е грешният въпрос, който трябва да зададете във вашата ситуация. Урокът, който се опитвате да следвате, генерира 32-битов x86 код, който няма да работи такъв, какъвто е за x86-64. напр. в стъпка 2 от урока Писане на компилатор в Ruby, той се опитва да отпечата Hello World, като извиква функцията puts(). Кодът за сглобяване, използван за извикване на C функция, е различен на x86 и x86-64. Опитайте първо да прочетете глави 3 и 4 от тази книга download.savannah.gnu.org/releases/pgubook След това прочетете cs.washington.edu/education/courses/401/11au/lectures/ - person scottt; 17.11.2012

Компилирайте вашата програма с gcc -fno-asynchronous-unwind-tables. Или просто игнорирайте различни .cfi_XYZ директиви. За случая clang просто не обръщайте внимание на раздела __eh_frame. Имайте предвид, че е доста необичайно два различни компилатора да генерират идентичен код, дори от идентичен източник.

person chill    schedule 17.11.2012