[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.