[Powered by Google Translate] ROB BOWDEN: Parliamo di compilatori.
Fino a questo punto, si è appena digitato il tuo codice sorgente in
alcuni file, inviato loro attraverso questa grande scatola nera che è
Clang, e viene fuori il file eseguibile che fa
esattamente quello che hai scritto nel codice sorgente.
Per quanto magico che è stato, stiamo andando a prendere una più stretta
guardare a ciò che succede
quando si compila un file.
Quindi, che cosa significa per compilare qualcosa?
>> Beh, in senso più generale, significa solo
trasformando codice scritto in uno
linguaggio di programmazione ad un altro.
Ma di solito quando le persone dicono di compilare qualcosa,
significa che stanno prendendo da una programmazione di livello superiore
lingua per un linguaggio di programmazione di livello inferiore.
Possono sembrare termini molto soggettivi.
Per esempio, probabilmente non pensare a C come un alto
livello di linguaggio di programmazione, ma non lo compila.
Ma è tutto relativo.
Come vedremo, il codice assembly e, infine, della macchina
codice che si compila fino a è senza dubbio un livello inferiore
di C.
Anche se useremo Clang in manifestazione di oggi, un
molte delle idee qui riporto ad altri compilatori.
>> Per Clang, ci sono quattro passaggi importanti nella generale
compilazione.
Si tratta di uno, pre-elaborazione effettuata dal preprocessore, due,
compilazione fatta dal compilatore, tre, assemblaggio
svolto dal assemblatore e quattro,
collegamento fatto dal linker.
Si può confondere che una delle sottofasi del complessivo
Compilatori Clang è chiamato compilatore, ma
ci arriveremo.
Useremo un semplice programma ciao mondo come il nostro esempio
tutto questo video.
Diamo uno sguardo.
>> Il primo passo è preelaborazione.
Che cosa fa il preprocessore fare?
In quasi ogni programma C che tu abbia mai letto o scritto,
hai utilizzato linee di codice che iniziano con un hash.
Lo chiamerò hash, ma si può anche chiamare sterline, il numero
firmare, o taglienti.
Ogni tale linea è una direttiva del preprocessore.
Avete probabilmente visto # define e # include prima, ma non ci
sono molti di più che il preprocessore riconosce.
Proviamo ad aggiungere un # define al nostro esempio ciao mondo.
Ora eseguire solo il preprocessore su questo file.
Passando clage bandiera-E, si sta istruendo l'esecuzione
solo il preprocessore.
Vediamo cosa succede.
Sembra Clang sputa appena fuori tutto
dalla riga di comando.
Al fine di salvare tutto questo output in un nuovo file chiamato
hello2.c, faremo aggiungere> hello2.c al nostro comando.
Ora diamo uno sguardo al nostro file pre-elaborato.
>> Ehi, che fine ha fatto il nostro programma po 'corto?
Se andiamo fino in fondo di questo file, vedremo
parte del codice che in realtà abbiamo scritto.
Si noti che il # define è andato e tutte le istanze del nome
sono stati sostituiti con esattamente quello specificato
la riga # define.
Così che cosa sono tutti questi typedef e le dichiarazioni di funzione
all'inizio del file?
Si noti che il # define non era l'unico preprocessore
direttiva che abbiamo specificato.
Abbiamo anche # include stdio.h.
Quindi, tutte le linee sono in realtà solo pazzi stdio.h copiato
e incollato nella parte superiore di questo file.
È per questo che i file header sono così utili per la funzione
dichiarazioni.
Invece di dover copiare e incollare tutte le funzioni
dichiarazioni si prevede di utilizzare nella parte superiore del file, le
preprocessore copia e incolla dalla testata
il file per te.
>> Ora che abbiamo finito di pre-elaborazione, passiamo
compilazione.
Il motivo per cui chiamiamo questa compilation passo è perché questo è
il passaggio in cui in realtà si Clang sua compilazione da C a
assembly di codice.
Al fine di avere Clang compilare un file verso assembly, ma
proseguire oltre, passare il flag-S
dalla riga di comando.
Diamo uno sguardo al gruppo
file che è stato emesso.
Sembra piuttosto una lingua diversa.
Il montaggio è molto codice specifico processore.
In questo caso, poiché il CS50 apparecchio è in esecuzione su un
virtuale processore x86, questo è il codice assembly x86.
Pochissime persone scrivere direttamente in codice assembly in questi giorni,
ma ogni programma C che mai scrivere si trasforma in giù
nel montaggio.
Anche in questo caso, si chiama questo passo la compilazione del C in assembly
dal momento che stiamo passando da un livello più alto a un livello inferiore
linguaggio di programmazione.
>> Ciò che rende il livello di montaggio inferiore a C?
Beh, in assemblea, siamo molto limitati in ciò che possiamo fare.
Non ci sono se, mentre, per, o anelli di qualsiasi tipo.
Ma è possibile eseguire le stesse cose che questi controlli
strutture offrono utilizzando le operazioni limitate che
montaggio non fornire.
Ma per vedere come assieme di livello basso è davvero, andiamo
un ulteriore passo avanti nella nostra compilation, assemblaggio.
E 'il lavoro del montatore di trasformare il codice assembly
in oggetto o codice macchina.
Ricordate che l'assembler non assembly di output;
piuttosto, ci vuole in assemblea e la macchina uscite codice.
Codice macchina è l'attuale 1 e 0 che una CPU può
capire, anche se abbiamo ancora un po 'di lavoro a sinistra
prima di poter eseguire il nostro programma.
Facciamo assemblare il nostro codice assembly passando
Clang il flag-c.
Vediamo ora cosa c'è nel file montato.
>> Beh, questo non ci aiuta molto.
Ricordate che il codice macchina è il uno e zero che
il computer può capire.
Questo non significa che sia facile per noi da capire.
Quindi, esattamente come a basso livello è l'Assemblea?
E 'quasi identico al codice oggetto.
Passando da assembly a codice oggetto è molto più di un
traduzione di una trasformazione, ed è per questo
non si potrebbe prendere in considerazione l'assemblatore di
fare qualsiasi effettiva compilazione.
In realtà, è abbastanza facile da tradurre manualmente da
assembly in codice macchina.
Guardando il gruppo per una funzione principale, che la prima linea
succede a corrispondere a 0x55 esadecimali.
In binario, che è 1010101.
La seconda riga succede a corrispondere 0x895 esadecimale.
E la successiva, 0x56.
Data una tabella relativamente semplice, si potrebbe tradurre
assembly nel codice che le macchine in grado di capire troppo.
>> Quindi c'è un passo rimanente in
compilazione, che è il collegamento.
Collegamento unisce un gruppo di file oggetto in un unico file
che si può effettivamente eseguire.
Il collegamento è molto dipende dal sistema.
Quindi il modo più semplice per collegare Clang solo oggetto
file insieme è quella di chiamare Clang su tutti i file che
si vuole abbinare.
Se si specifica. File o, allora non avrà bisogno di rielaborare,
compilare e assemblare tutto il codice sorgente.
Buttiamo una funzione matematica nel nostro file, così abbiamo
qualcosa da collegare trovi
Ora compilarlo indietro al codice oggetto e
Clang chiamano su di esso.
Oops.
Dal momento che abbiamo inserito una funzione matematica, abbiamo bisogno di collegare in
la libreria matematica con-lm.
>> Se volessimo collegare insieme o gruppo di file. Che
ha scritto il nostro, che avevamo appena specificare tutti al
riga di comando.
La limitazione è che uno solo di questi file devono essere
effettivamente specificare una funzione principale, oppure il
eseguibile risultante non saprei da dove cominciare
esegue il codice.
Qual è la differenza tra la specifica di un file da collegare in
con-l e solo specificando un file direttamente?
Niente.
E 'solo che Clang capita di sapere esattamente cosa del file
qualcosa di simile accade-lm di riferimento.
Se si sapeva che file manualmente, è possibile specificarlo
esplicitamente.
Basta ricordare che tutto l bandiere venire alla fine
della richiesta del cliente.
>> E questo è tutto ciò che devi fare.
Quando si basta eseguire Clang su determinati file, questo è ciò che è
effettivamente facendo.
Il mio nome è Rob Bowden, e questo è CS50.