C'è qualche differenza tra i due? Secondo il libro di Ullman , i compilatori convertono una lingua in un'altra lingua (di solito di basso livello), così come un assemblatore. In che modo i due sono diversi?
C'è qualche differenza tra i due? Secondo il libro di Ullman , i compilatori convertono una lingua in un'altra lingua (di solito di basso livello), così come un assemblatore. In che modo i due sono diversi?
Risposte:
Un assemblatore traduce il codice assembly in codice macchina. La traduzione è meccanica e può essere eseguita in un solo modo. Al contrario, un compilatore ha più libertà quando compila il linguaggio di programmazione pertinente: può ottimizzare, ad esempio, e anche compilatori non ottimizzati producono codice diverso. Inoltre, i compilatori possono essere scritti in un modo che separa "front-end" (corrispondente al linguaggio di programmazione) e "back-end" (corrispondente all'architettura del computer), mentre con gli assemblatori i due sono sempre gli stessi.
La linea di fondo è che è più divertente scrivere un compilatore che un assemblatore. I linguaggi di assemblaggio sono generalmente progettati per essere quasi banali da analizzare e controllare i tipi e tendono a coinvolgere molti generatori basati su tabella ("il codice operativo per aggiungere è 01110", "per le istruzioni di caricamento il registro dell'operando di destinazione è specificato dai bit da 17 a 21 "). Di solito la parte più interessante di un assemblatore è la parte che risolve le etichette simboliche in numeri.
Tuttavia , la maggior parte degli assemblatori può eseguire una piccola quantità di aritmetica (aggiungendo insieme etichette simboliche con piccole costanti, per esempio) e la maggior parte degli assemblatori ha o è integrato con una funzione di elaborazione delle macro. (Sulla maggior parte dei sistemi Unix la funzione macro è effettivamente fornita eseguendo il pre-processore C sull'assemblaggio prima di passarlo al proprio assemblatore.)
L'assemblatore MIPS ha dovuto fare un passo oltre e ha preso alcune interessanti decisioni sulla generazione del codice e ha fatto una piccola quantità di ottimizzazione. Il linguaggio della macchina MIPS richiede sequenze di codice diverse per caricare diverse costanti, ad esempio, e quindi l'assemblatore doveva scegliere la sequenza di codici dopo aver costruito la costante . Inoltre, il codice macchina MIPS aveva il concetto di slot di ritardo , ma era responsabilità dell'assemblatore estrarre questi elementi e presentare al compilatore un linguaggio di assemblaggio astratto più "normale". Quindi l'assemblatore MIPS deve eseguire una pianificazione delle istruzioni locali.
La distinzione è ulteriormente offuscata da alcune delle opere di Norman Ramsey , in particolare il suo linguaggio di assemblaggio portatile C. (L'articolo pertinente è Ramsey e Peyton Jones, "Un singolo linguaggio intermedio che supporta molteplici implementazioni di eccezioni", Prog. Lang. Impl. E Dsgn. , (PLDI-21): 285–298, 2000 ). E infine, lì è anche un Typed Assembly Language di David Walker e Greg Morrisett con un assemblatore in grado di garantire la sicurezza della memoria.
Un po 'di risposta semplificata qui, la realtà è più complicata. Mi aspetto che la differenza tra un assemblatore (A) e un compilatore (C) sia tra le altre cose:
Tendiamo a chiamare il linguaggio assembly "basso livello" e la lingua di origine che un compilatore comprende "alto livello" (questa è una semplificazione grossolana, ma comunque).
Nel linguaggio assembly è possibile ad esempio eseguire un'operazione aggiuntiva dicendo:
In una lingua di alto livello potresti scrivere:
E questo potrebbe comportare un'istruzione o centinaia di istruzioni a seconda di una serie di circostanze, una è la CPU per la quale il compilatore crea istruzioni.
Come puoi vedere, il linguaggio di origine dell'assemblaggio è il più delle volte: (A) una riga di codice sorgente fornisce una riga di codici operativi della CPU e dipende molto dalla CPU di destinazione. Un compilatore di linguaggio di alto livello (C) gestisce tutti questi dettagli per te: una riga di codice sorgente potrebbe diventare zero, uno o più codici operativi della CPU e il compilatore gestisce i dettagli di ciò che la CPU può fare.
Oggi un compilatore consiste spesso in diverse fasi. Potrebbero essere chiamati frontend / backend o essere chiamati altre cose. In genere li vedo come quattro fasi:
Scrivere buoni compilatori è una professione altamente qualificata: creare un compilatore in linguaggio giocattolo può essere svolto in un pomeriggio da un amatuer (o bene, leggermente più a lungo).