2010-08-25 7 views
30

Mam następujący kod C++Co to jest .cfi i .LFE w kodzie zestawu produkowanym przez GCC z programu C++?

int factorial(int n){ 

    if(n==0){ 
     return 1; 
    } 
    return n*factorial(n-1); 

} 

int main(void){ 
    factorial(5); 
    return 0; 
} 

Kiedy utworzyć plik montażowej za pomocą g ++ -S factorial.cpp uzyskać następujące:

.file "tail_call_opt.cpp" 
    .text 
.globl _Z9factoriali 
    .type _Z9factoriali, @function 
_Z9factoriali: 
.LFB0: 
    .cfi_startproc 
    .cfi_personality 0x0,__gxx_personality_v0 
    pushl %ebp 
    .cfi_def_cfa_offset 8 
    movl %esp, %ebp 
    .cfi_offset 5, -8 
    .cfi_def_cfa_register 5 
    subl $24, %esp 
    cmpl $0, 8(%ebp) 
    jne .L2 
    movl $1, %eax 
    jmp .L3 
.L2: 
    movl 8(%ebp), %eax 
    subl $1, %eax 
    movl %eax, (%esp) 
    call _Z9factoriali 
    imull 8(%ebp), %eax 
.L3: 
    leave 
    ret 
    .cfi_endproc 
.LFE0: 
    .size _Z9factoriali, .-_Z9factoriali 
.globl main 
    .type main, @function 
main: 
.LFB1: 
    .cfi_startproc 
    .cfi_personality 0x0,__gxx_personality_v0 
    pushl %ebp 
    .cfi_def_cfa_offset 8 
    movl %esp, %ebp 
    .cfi_offset 5, -8 
    .cfi_def_cfa_register 5 
    andl $-16, %esp 
    subl $16, %esp 
    movl $5, (%esp) 
    call _Z9factoriali 
    movl $0, %eax 
    leave 
    ret 
    .cfi_endproc 
.LFE1: 
    .size main, .-main 
    .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3" 
    .section .note.GNU-stack,"",@progbits 

mogę śledzić większość tego, ale to, co jest cel części .cfi i .LFE? Gdzie mogę dowiedzieć się więcej na temat zespołu produkowanego przez gcc?

+0

możliwy duplikat [Do czego służą dyrektywy CFI w Gnu Asembler (GAS)?] (Http://stackoverflow.com/questions/2529185/what-are-cfi-directives-in-gnu-assembler-gas- used-for) – Andrey

+3

To nie jest dupe. Drugie pytanie nie dotyczy LFE. – Puppy

Odpowiedz

48

Te dyrektywy nakazują gazowi emisję znaczników informacyjnych ramki połączeń, które są najwyraźniej używane do rekonstrukcji śledzenia stosu, gdy brakuje wskaźnika ramki. W twoim przypadku wskaźnik ramki jest obecny, więc myślę, że można go użyć do odwijania podczas obsługi wyjątków. Taki mechanizm ma mniejszy narzut niż stary sjlj (setjump/longjump). Zobacz here, a także połączoną specyfikację Dwarf.

Jeśli chodzi o etykiety .Lxx, przedrostek .L wskazuje, że etykieta jest lokalna dla tego pliku i nie będzie kolidować z etykietami o tej samej nazwie w innych plikach. GCC generalnie używa .L dla generowanych automatycznie etykiet. W tym przypadku najprawdopodobniej "FB" oznacza "funkcja rozpoczyna się", a "FE" oznacza "koniec funkcji".

+3

Rzeczywiście bardzo ładny opis. – AbiusX