2013-03-22 9 views
5

L'assunzione di un programma vuotoFunzione Prologo ed Epilogo rimossi da GCC Optimization

//demo.c 

int main(void) 
{ 

} 

La compilazione del programma a ottimizzazione di default.

gcc -S demo.c -o dasm.asm 

ottengo l'uscita di montaggio come

//Removed labels and directive which are not relevant 

main: 

pushl %ebp     // prologue of main 
movl %esp, %ebp   // prologue of main 
popl %ebp     // epilogue of main 
ret 

Ora Compilazione del programma a -O2 ottimizzazione.

gcc -O2 -S demo.c -o dasm.asm 

ottengo l'assemblaggio ottimizzato

main: 

rep 
ret 

Nella mia ricerca iniziale, ho trovato che l'ottimizzazione bandiera -fomit-frame-pointer è stato responsabile per la rimozione del prologo e un epilogo.

Ho trovato ulteriori informazioni sulla bandiera, nel gcc compiler manual. Ma non ho potuto capire questo motivo qui sotto, dato dal manuale, per rimuovere il prologo e l'epilogo.

Non mantenere il puntatore del frame in un registro per le funzioni che non sono richieste da .

C'è qualche altro modo di mettere la ragione di cui sopra?

Qual è il motivo dell'istruzione "rep", visualizzata all'ottimizzazione -02?

Perché la funzione principale non richiede l'inizializzazione del frame dello stack?

Se l'impostazione del puntatore del frame non viene eseguita dalla funzione principale, chi fa questo lavoro?

È fatto dal sistema operativo o è la funzionalità dell'hardware?

+5

'ret' rappresentante è un' ret' con un prefisso che non altera la semantica, mantiene alcuni processori AMD felici (alcuni di loro hanno una pena per saltare direttamente a a 'ret'). – harold

+0

Possibile duplicato di [Evitare l'overhead del prologo della funzione gcc?] (Http://stackoverflow.com/questions/5477673/avoiding-gcc-function-prologue-overhead) – mlt

risposta

5

I compilatori stanno diventando intelligenti, sapeva che non era necessario un puntatore del frame di stack memorizzato in un registro perché qualsiasi cosa si fosse inserita nella funzione main() non utilizzava lo stack.

Per quanto riguarda rep ret:

Ecco il principio. Il processore tenta di recuperare le prossime istruzioni da eseguire, in modo che possa avviare il processo di decodifica ed eseguirle. Lo fa anche saltando e restituendo le istruzioni , indovinando dove si dirigerà il programma.

Quello che AMD dice è che, se un'istruzione ret segue immediatamente un'istruzione di salto condizionale , il predittore non può capire dove sta andando l'istruzione ret. . La pre-raccolta deve fermarsi finché non viene eseguito il comando , e solo allora sarà in grado di ricominciare a cercare .

Il trucco "rep ret" funziona apparentemente attorno al problema e consente al predittore di eseguire il proprio lavoro. Il "rep" non ha alcun effetto sull'istruzione.

fonte: alcuni forum, google una frase per trovarlo.

Una cosa da notare è che solo perché non c'è un prologo non significa che non ci sono stack, è comunque possibile spingere e pop con facilità è solo che la complessa manipolazione dello stack sarà difficile.

Le funzioni che non hanno prologo/epilogo sono solitamente doppiate nuda. Agli hacker piace usarli molto perché non contaminano la pila quando si fa jmp su di loro, devo confessare che non conosco nessun altro uso al di fuori dell'ottimizzazione. In Visual Studio è fatto tramite:

__declspec(naked) 
+0

Ora ho provato, dichiarando una variabile dentro main, e ho scritto alcune dichiarazioni che lo manipolano e usano printf, ora ottengo un prologo, ma nessun epilogo (nessuna istruzione pop) –

+0

azzarderei un'ipotesi che la funzione main() semplicemente non ne abbia bisogno perché è la fine della strada. Prova a creare una funzione e fai printf() lì. –

+0

lo ha fatto, e ancora non riesci a trovare una singola istruzione popl, nel dump asm –