2013-03-08 6 views
6

ho fatto -S gcc sul programma molto complesso di seguito su x86_64:gcc intesa -S uscita

int main() { 
    int x = 3; 
    x = 5; 
    return 0; 
} 

E quello che ho ottenuto è stato:

 .file "main.c" 
     .text 
.globl main 
     .type main, @function 
main: 
.LFB0: 
     .cfi_startproc 
     pushq %rbp 
     .cfi_def_cfa_offset 16 
     .cfi_offset 6, -16 
     movq %rsp, %rbp 
     .cfi_def_cfa_register 6 
     movl $3, -4(%rbp) 
     movl $5, -4(%rbp) 
     movl $0, %eax 
     leave 
     .cfi_def_cfa 7, 8 
     ret 
     .cfi_endproc 
.LFE0: 
     .size main, .-main 
     .ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)" 
     .section  .note.GNU-stack,"",@progbits 

Mi chiedevo se qualcuno mi potrebbe aiutare capire l'output o riferirmi ad alcuni link che spiegano. In particolare, che cosa significa cfi ,LFB0,LFE0 , leave? Tutto quello che ho trovato riguardo a questi è this post ma non ho potuto capire appieno a cosa serviva. Inoltre, cosa fa in questo caso lo ret? Sto indovinando che sta tornando a __libc_start_main() che a sua volta chiamerebbe do_exit(), è corretto?

risposta

11

Tali .cfisomething direttive verificarsi generazione di dati aggiuntivi dal compilatore. Questi dati aiutano a superare lo stack di chiamate quando un'istruzione causa un'eccezione, quindi il gestore di eccezioni (se presente) può essere trovato ed eseguito correttamente. Le informazioni sullo stack di chiamata sono utili per il debug. Molto probabilmente questi dati vanno in una sezione separata dell'eseguibile. Non è inserito tra le istruzioni del tuo codice.

.LFsomething: sono solo etichette regolari che sono probabilmente referenziate da quei dati extra relativi alle eccezioni.

leave e ret sono istruzioni della CPU.

leave è equivalente a:

movq %rbp, %rsp 
popq %rbp 

e annulla l'effetto di queste due istruzioni

pushq %rbp 
movq %rsp, %rbp 

e istruzioni che allocano spazio sulla pila sottraendo qualcosa da rsp.

ret restituisce dalla funzione. Apre l'indirizzo di ritorno dallo stack e salta a quell'indirizzo. Se era __libc_start_main() che ha chiamato main(), allora ritorna lì.

+1

Su questa architettura, tutte le etichette locali di GCC inizieranno con '.L' e terminano con un numero. Le etichette con solo '.L' e un numero sono target di salto; le etichette con qualche altra lettera in mezzo hanno qualche altro scopo. In questo caso, "FB" sta per "function begin" e "FE" sta per "function end", e sono * probabilmente * non usati più per nulla.Gli IIRC erano richiesti quando GCC calcolava i dati di gestione delle eccezioni invece di fare l'assemblatore, e sono ancora lì perché il backend x86 è molto complicato, quindi è difficile essere sicuri che non siano necessari. – zwol

7

Qui si va:

1: .LFB0, .LFE0 non sono altro che le etichette locali.

2: .cfi_startproc viene utilizzato all'inizio di ogni funzione e la fine della funzione avviene con .cfi_endproc.

3: l'istruzione leave è un'istruzione x86 assemblatore che esegue il ripristino del frame dello stack della funzione di chiamata.

e infine dopo l'istruzione Ret, è quello che succede

 o %eip contains return address 
     o %esp points at arguments pushed by caller 
     o called function may have trashed arguments 
     o %eax contains return value (or trash if function is void) 
     o %ecx, %edx may be trashed 
     o %ebp, %ebx, %esi, %edi must contain contents from time of call