2010-07-29 6 views
14

Ho appena notato qualche strano linguaggio assembly assembly del metodo main vuoto.Spiega lo strano assemblaggio della funzione C `main` vuota dal compilatore Visual C++

//filename: main.c 
void main() 
{ 

} 

smontaggio:

push  ebp 
mov   ebp,esp 
sub   esp,0C0h; why on the earth is it reserving 192 bytes? 
push  ebx 
push  esi 
push  edi ; good compiler. Its saving ebx, esi & edi values. 
lea   edi,[ebp-0C0h] ; line 1 
mov   ecx,30h ; line 2 
mov   eax,0CCCCCCCCh ; line 3 
rep stos dword ptr es:[edi] ; line 4 


xor   eax,eax ; returning value 0. Code following this line is explanatory. 
pop   edi ; restoring the original states of edi,esi & ebx 
pop   esi 
pop   ebx 
mov   esp,ebp 
pop   ebp 
ret 
  1. perché sulla terra è esso riservando 192 byte per funzione in cui non ci sono variabili
  2. cosa con le quattro linee: linea 1, linea 2, riga 3, riga 4? cosa sta cercando di fare & PERCHÉ?
+0

perché la sintassi del codice non è evidenziata? – claws

+0

Quale assembly viene prodotto quando si assembla un'istruzione principale non vuota e cosa succede quando si modifica il tipo restituito da main a int? –

+5

Vale la pena sottolineare che i principali rendimenti int. Usare il vuoto per main non è buono juju. – nmichaels

risposta

15

Le quattro righe di codice che hai indicato sono la build di debug che cancella lo spazio variabile locale con il valore speciale "clear" (0xCCCCCCCC).

Non sono sicuro del motivo per cui ci sono 192 byte di spazio apparentemente morto, ma quello potrebbe essere VC++ che crea uno spazio di guardia nell'area variabile locale per cercare di rilevare lo smashing dello stack.

Probabilmente otterrete un output molto diverso se passate da Debug a Release build.

+1

perché '0xCCCCCCCC' =' 1100 1100 1100 1100 1100 1100 1100 1100'? non risolvere il problema con 0x00000000 sarebbe più significativo? – claws

+0

@claws: Microsoft ha scelto questo valore perché è distinto e facile da identificare se il tuo programma finisce con l'uso di una variabile non inizializzata. L'utilizzo di zero maschererebbe molti potenziali bug perché spesso le variabili sarebbero inizializzate a zero in ogni caso, e il fatto che il compilatore lo facesse in una build di debug causerebbe il fallimento del build di release. –

+0

@Greg Hewgill: come visualizzare il disassemblaggio nella configurazione di rilascio in Visual Studio? Stavo inserendo un punto di interruzione nella staffa di chiusura e visualizzando lo smontaggio. Questo non sembra funzionare in modalità di rilascio. – claws

18

Greg ha già spiegato come il compilatore genera codice per diagnosticare variabili locali non inizializzate, abilitate dall'opzione di compilazione/RTCu. Il valore 0xcccccccc è stato scelto per essere distintivo e facilmente riconoscibile nel debugger. E per garantire il programma bombe quando un puntatore non inizializzato è dereferenziato. E per assicurarsi che termina il programma quando viene eseguito come codice. 0xcc è l'ideale per fare bene tutti questi lavori, è l'opcode di istruzioni per INT3.

I misteriosi 192 byte allocati nello stack frame sono lì per supportare la funzione Modifica + Continua,/opzione di compilazione ZI. Ti consente di modificare il codice mentre è attivo un punto di interruzione. E aggiungi le variabili locali a una funzione che quei 192 byte sono disponibili per fornire lo spazio per quelle persone aggiunte. Il superamento di tale spazio farà sì che l'IDE ti costringa a ricostruire il tuo programma.

Btw: questo può causare un problema se si utilizza la ricorsione nel codice. La build di debug bombarderà con questo nome del sito molto più velocemente. Normalmente non si tratta di un problema, esegui il debug con dimensioni di set di dati pratici.

+2

Su, per offrire informazioni oscure ma affascinanti. – mickeyf

+0

Quello che hai detto è corretto http://stackoverflow.com/questions/370195/when-and-why-will-an-os-initialise-memory-to-0xcd-0xdd-etc-on-malloc-free-new –

Problemi correlati