2010-03-08 1 views
7

come principiante di asm, sto controllando il codice asm generato da gcc -S per imparare.perché gcc 4.x riserva di default 8 byte per lo stack su linux quando si chiama un metodo?

perché gcc 4.x riserva di default 8 byte per stack quando si chiama un metodo?

func18 è la funzione vuota senza restituzione nessun parametro nessuna variabile locale definita. Non riesco a capire perché 8 byte sono riservati qui (né alcun forum/sito menzione per il motivo, ppl sembra darlo per scontato) è per il% ebp basta premere? o restituire il tipo ?! molti thx!

 .globl _func18 
    _func18: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $8, %esp 
    .text 
+0

In realtà, nessuna di queste istruzioni ha senso ... una funzione senza variabili locali non dovrebbe aver bisogno di impostare un puntatore del frame – Martin

+0

Probabilmente dipende dal livello di ottimizzazione. Puoi includere il codice generato completo per la funzione? –

+2

Non è questo spazio per l'indirizzo di ritorno e il puntatore dello stack frame? – jdizzle

risposta

0

Come richard di cui sopra, è tutto a causa dell'ottimizzazione, mostrando di seguito. ma ancora non ho idea del motivo per cui 8 byte riservati è qualcosa di ottimizzato ?!

c originale

void func18() {} 
int main() {return 0;} 

compilare senza bandiera di ottimizzazione specificate

.text                     
.globl _func18 
_func18: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $8, %esp 
    leave 
    ret 
.globl _main 
_main:                      
    pushl %ebp 
    movl %esp, %ebp 
    subl $8, %esp 
    movl $0, %eax 
    leave 
    ret 
    .subsections_via_symbols 

con -Os ottimizzazione bandiera, riserva non più di stack

.text 
.globl _func18 
_func18: 
    pushl %ebp 
    movl %esp, %ebp 
    leave 
    ret 
.globl _main 
_main: 
    pushl %ebp 
    xorl %eax, %eax 
    movl %esp, %ebp 
    leave 
    ret 
    .subsections_via_symbols 
+2

metti questo nella tua domanda, non in una risposta separata – moo

0

Un modo semplice per scoprirlo: la funzione vuota chiama un'altra funzione con un parametro. Se il parametro è memorizzato direttamente nello stack (nessuna spinta), allora è a questo che serve lo spazio extra.

+0

Ho provato prima, sembra non riferirsi ad esso – nikcname

8

Alcune istruzioni richiedono che alcuni tipi di dati siano allineati fino a un limite di 16 byte (in particolare, il tipo di dati SSE __m128). Per soddisfare questo requisito, gcc garantisce che lo stack sia inizialmente allineato a 16 byte e alloca lo spazio di stack in multipli di 16 byte. Se è necessario inserire solo un indirizzo di ritorno a 4 byte e un puntatore del frame a 4 byte, sono necessari 8 byte aggiuntivi per mantenere lo stack allineato su un limite di 16 byte. Tuttavia, se gcc determina che l'allineamento aggiuntivo non è necessario (ovvero i tipi di dati di fantasia non vengono utilizzati e non vengono chiamate funzioni esterne), allora può omettere qualsiasi istruzione aggiuntiva utilizzata per allineare lo stack. L'analisi necessaria per determinarlo potrebbe richiedere l'esecuzione di alcuni passaggi di ottimizzazione.

Vedere anche la documentazione di gcc per l'opzione -mpreferred-stack-boundary=num.

+0

thx mark, quindi è tutto per l'allineamento dei dati quando si ottimizza con sse, molto ragionevole in quanto disabilito l'ottimizzazione e il $ 8 subl % esp è andato. il gcc ref è molto utile !!! solo 1 cosa, mentre aggancio il limite -mpreferred-stack-boundary, la prenotazione è solo tra 3 e 4, da 4 a 12, si attacca con 8 byte, ho pensato che la prenotazione dovesse essere di 20 byte, no? – nikcname

+0

Se hai usato -mpreferred-stack-boundary = 12, allora in qualsiasi funzione che richiami funzioni esterne assegnerà lo spazio di stack in multipli di 2^12 = 4096 byte. Se non si sta chiamando alcuna funzione esterna, sarà spesso in grado di capire che mantenere quell'allineamento non è necessario per il codice che sta generando (dipende dalla versione esatta di gcc, dalle opzioni e dall'architettura di destinazione). – mark4o

+0

quindi, nel caso in cui si funzioni func senza chiamare func esterna, gcc si limita a 8 byte di default? – nikcname