I compilatori-scrittori devono effettivamente "capire" il codice macchina? [chiuso]

10

Potrebbe essere una specie di domanda strana.

Un ragazzo che scrive un compilatore C ++ (o qualsiasi altro linguaggio non VM): deve essere in grado di leggere / scrivere il linguaggio della macchina raw? Come funziona?

EDIT: mi riferisco in particolare ai compilatori che compilano il codice macchina, non ad un altro linguaggio di programmazione.

    
posta Aviv Cohn 19.04.2014 - 10:08
fonte

5 risposte

15

No, per niente. È perfettamente possibile (e spesso anche preferibile) che il compilatore emetta invece il codice assembly. L'assemblatore si occupa quindi di creare il codice macchina effettivo.

A proposito, la tua distinzione tra implementazione non VM e implementazione VM non è utile.

  • Per i principianti, l'utilizzo di una VM o la pre-compilazione su codice macchina sono solo modi diversi di implementare una lingua; nella maggior parte dei casi è possibile implementare una lingua utilizzando entrambe le strategie. In realtà ho dovuto usare un interprete in C ++ una volta.

  • Inoltre, molte macchine virtuali come la JVM hanno sia un codice macchina binario che un assemblatore, proprio come un'architettura ordinaria.

Il LLVM (che è usato dai compilatori Clang) merita una menzione speciale qui: definisce una VM per cui le istruzioni possono essere rappresentate come byte code, assembly testuale o una struttura dati che rende molto facile emettere da un compilatore. Quindi, anche se sarebbe utile per il debug (e per capire cosa stai facendo), non dovresti nemmeno sapere del linguaggio assembly, solo riguardo all'API LLVM.

La cosa bella del LLVM è che la sua VM è solo un'astrazione, e che il codice byte non viene solitamente interpretato, ma in realtà è JITted trasparente. Quindi è del tutto possibile scrivere una lingua compilata in modo efficace, senza dover mai conoscere il set di istruzioni della CPU.

    
risposta data 19.04.2014 - 10:42
fonte
9

No. Il punto chiave della tua domanda è che la compilazione è estremamente ampia. La compilazione può avvenire da qualsiasi lingua a qualsiasi lingua. E il codice assembly / machine è solo una delle tante lingue per il target di compilazione. Ad esempio, linguaggi Java e .NET come C #, F # e VB.NET sono tutti compilati con una sorta di codice intermedio al posto del codice specifico della macchina. Non importa se viene eseguito su VM, la lingua è ancora compilata. C'è anche l'opzione per compilare un altro linguaggio, come C. C è in realtà una destinazione di compilazione molto popolare e molti strumenti lo fanno. E infine, potresti usare qualche strumento o libreria per fare il duro lavoro di produrre codice macchina per te. c'è ad esempio LLVM che può ridurre lo sforzo necessario per creare un compilatore standalone.

Inoltre, la tua modifica non ha alcun senso. È come chiedere "Ogni ingegnere ha bisogno di capire come funziona il motore? E sto chiedendo agli ingegneri che lavorano sui motori". Se stai lavorando su un programma o una libreria che emette un codice macchina, devi capirlo. Il punto è che non devi fare una cosa simile quando scrivi un compilatore. Molte persone l'hanno fatto prima di te, quindi devi avere una seria ragione per farlo di nuovo.

    
risposta data 19.04.2014 - 10:40
fonte
3

Classicamente un compilatore ha tre parti: analisi lessicale, analisi e generazione di codice. L'analisi lessicale suddivide il testo del programma in parole chiave, nomi e valori. L'analisi mostra come i token che derivano dall'analisi lessicale siano combinati in affermazioni sintatticamente corrette per il linguaggio. La generazione del codice prende le strutture di dati prodotte dal parser e le traduce in codice macchina o in qualche altra rappresentazione. Al giorno d'oggi l'analisi lessicale e l'analisi possono essere combinati in un unico passaggio.

Chiaramente la persona che scrive il generatore di codice deve comprendere il codice macchina di destinazione a un livello molto profondo, compresi set di istruzioni, pipeline del processore e comportamento della cache. In caso contrario, i programmi prodotti dal compilatore sarebbero lenti e inefficienti. Molto bene potrebbero essere in grado di leggere e scrivere codice macchina come rappresentato da numeri ottali o esadecimali, ma generalmente scriveranno funzioni per generare il codice macchina, facendo riferimento internamente alle tabelle delle istruzioni della macchina. Teoricamente, la gente che scrive il lexer e il parser potrebbe non sapere nulla sulla generazione del codice macchina. In effetti, alcuni compilatori moderni consentono di collegare le proprie routine di generazione del codice che potrebbero emettere codice macchina per alcune CPU di cui lesseggiatore e parser non hanno mai sentito parlare.

Tuttavia, nella pratica, i redattori di compilatori di ogni fase conoscono molto le diverse architetture dei processori e questo li aiuta a progettare le strutture di dati di cui avrà bisogno la fase di generazione del codice.

    
risposta data 19.04.2014 - 10:40
fonte
2

Molto tempo fa scrissi un compilatore che convertiva tra due diversi script di shell. Non è andato vicino al codice macchina.

Una scrittura del compilatore deve comprendere il loro output , ma spesso non è un codice macchina.

La maggior parte dei programmatori mai scrive un compilatore che emette codice macchina o codice assembly, ma i compilatori personalizzati possono essere molto utili su molti progetti per produrre altri output.

YACC è uno di questi compilatori che non emette codice macchina ....

    
risposta data 19.04.2014 - 15:20
fonte
0

Non è necessario iniziare con una conoscenza dettagliata della semantica delle lingue di input e output, ma è meglio finire con una conoscenza squisitamente dettagliata di entrambi, altrimenti il compilatore sarà insolitamente buggato. Quindi se il tuo input è C ++ e il tuo output è un linguaggio macchina specifico, alla fine dovrai conoscere la semantica di entrambi.

Ecco alcune delle sottigliezze nella compilazione di C ++ al codice macchina: (appena in cima alla mia testa, sono sicuro che ce ne sono di più che sto dimenticando).

  1. Quali dimensioni saranno int ? La scelta "corretta" qui è un'arte, basata sia sulla dimensione naturale del puntatore della macchina, sulle prestazioni dell'ALU per varie operazioni aritmetiche, sia sulle scelte fatte dai compilatori esistenti per la macchina. La macchina ha anche aritmetica a 64 bit? In caso contrario, l'aggiunta di numeri interi a 32 bit deve essere convertita in un'istruzione mentre l'aggiunta di numeri interi a 64 bit deve essere convertita in una chiamata di funzione per l'aggiunta a 64 bit. La macchina ha operazioni di aggiunta a 8 e 16 bit o devi simulare quelli con operazioni ops e mascheramento a 32 bit (ad esempio il DEC Alpha 21064)?

  2. Qual è la convenzione di chiamata utilizzata da altri compilatori, librerie e lingue sulla macchina? I parametri vengono spinti nello stack da destra a sinistra o da sinistra a destra? Alcuni parametri entrano nei registri mentre altri vanno in pila? Sono interi e galleggianti in diversi spazi del registro? I parametri assegnati al registro devono essere trattati in modo particolare sulle chiamate varargs? Quali registri sono salvati dai chiamanti e quali sono salvati? Puoi eseguire ottimizzazioni chiamata foglia?

  3. Che cosa fanno le istruzioni di turno di ciascuna macchina? Se si chiede di spostare un intero a 64 bit di 65 bit, qual è il risultato? (Su molte macchine il risultato è lo stesso di uno spostamento di 1 bit, in altri il risultato è "0".)

  4. Quali sono le semantiche di consistenza della memoria della macchina? C ++ 11 ha una semantica della memoria ben definita che in alcuni casi pone delle restrizioni su alcune ottimizzazioni, ma consente ottimizzazioni in altri casi. Se stai compilando un linguaggio che non ha una semantica di memoria ben definita (come ogni versione di C / C ++ prima di C ++ 11, e molti altri linguaggi imperativi) allora dovrai inventare la semantica della memoria man mano che procederai, di solito vorrai inventare la semantica della memoria che meglio si adatta alla semantica della tua macchina.

risposta data 19.04.2014 - 21:24
fonte

Leggi altre domande sui tag