È possibile un linguaggio assembly universale per tutti i computer?


23

Vorrei porre alcune domande sul linguaggio dell'Assemblea. La mia comprensione è che è molto vicino al linguaggio automatico, rendendolo più veloce ed efficiente.

Dato che esistono diverse architetture di computer, ciò significa che devo scrivere codice diverso in Assembly per architetture diverse? Se è così, perché Assembly non è, scrivi una volta - esegui ovunque il tipo di linguaggio? Non sarebbe più semplice renderlo universale, in modo da poterlo scrivere una sola volta e poterlo eseguire praticamente su qualsiasi macchina con diverse configurazioni? (Penso che sarebbe impossibile, ma vorrei avere delle risposte concrete e approfondite)

Alcune persone potrebbero dire che C è la lingua che sto cercando. Non ho mai usato C prima, ma penso che sia ancora un linguaggio di alto livello, anche se probabilmente più veloce di Java, per esempio. Potrei sbagliarmi qui.


10
Che ricerca hai fatto? Ci aspettiamo che tu faccia delle ricerche prima di fare una domanda, per aiutarti a porre una domanda migliore. C'è molto scritto sul linguaggio assembly.
DW

4
Ci aspettiamo che tu faccia una notevole quantità di ricerca / studio individuale prima di fare una domanda e di comunicarci nella domanda quale ricerca hai fatto. In questo caso, la ricerca potrebbe includere la lettura di pertinenti articoli di Wikipedia (ad es. Sul linguaggio assembly e l'architettura del computer) e la lettura di un libro di testo sull'architettura del computer. Per rendere questa una domanda migliore: fai quella ricerca, se non l'hai già fatto, e poi modifica la domanda per spiegare la ricerca che hai fatto. Spesso quel tipo di ricerca ti aiuta a formulare una domanda migliore; e in ogni caso aiuta i rispondenti a non ripetere ciò che già sai.
DW

15
Inizia a capire che / perché non esiste una lingua chiamata Assembly.
Raffaello

2
un problema "classico" con la portabilità in C sono le dimensioni di primitive diverse (es. numeri interi) su hardware diverso e ce ne sono alcune citate.
vzn

3
Questo è più un problema sociale che tecnico - è necessario convincere tutti i produttori di CPU affinché le loro CPU accettino lo stesso linguaggio macchina. (In realtà, x86 sarebbe quasi stato questo, per caso - poi gli smartphone sono decollati)
user253751

Risposte:


45

Il linguaggio assembly è un modo per scrivere le istruzioni per il set di istruzioni del computer , in un modo leggermente più comprensibile per i programmatori umani.

Architetture diverse hanno insiemi di istruzioni diversi: l'insieme di istruzioni consentite è diverso per ogni architettura. Pertanto, non si può sperare di avere un programma di assemblaggio write-once-run-ovunque. Ad esempio, il set di istruzioni supportato dai processori x86 sembra molto diverso dal set di istruzioni supportato dai processori ARM. Se si scrivesse un programma di assemblaggio per un processore x86, ci sarebbero molte istruzioni che non sono supportate sul processore ARM e viceversa.

Il motivo principale per usare il linguaggio assembly è che consente un controllo di livello molto basso sul programma e di trarre vantaggio da tutte le istruzioni del processore: personalizzando il programma per sfruttare le funzionalità che sono uniche per il particolare processore verrà eseguito, a volte è possibile accelerare il programma. La filosofia write-once-run-ovunque è fondamentalmente in contrasto con questo.


1
Penso che a questa domanda sia già stata data risposta al terzo paragrafo della mia risposta. Come hai detto, un tale schema non sarebbe efficace, quindi sarebbe fondamentalmente in contrasto con la ragione principale per usare il linguaggio assembly.
DW

26
@nTuply Non appena modifichi il linguaggio assembly per soddisfare macchine diverse, diventa un linguaggio di alto livello con una sintassi orribilmente in stile assembly. Una volta che hai deciso di usare un linguaggio di alto livello, puoi anche usarne uno con una sintassi più amichevole e lasciare che il compilatore faccia il duro lavoro.
David Richerby,

15
Non è un'idea del tutto stupida avere un "linguaggio assembly" che viene tradotto per macchine diverse, perché in sostanza è "IR" di LLVM. Tuttavia, per i motivi indicati da David, normalmente non si scrive un assembly LLVM. Anche perché 99 volte su 100 faresti un lavoro peggiore di scriverlo rispetto a clang della traduzione della tua C in LLVM. Le lingue di assemblaggio sono potenzialmente più efficienti delle lingue di alto livello, ma nelle mani della maggior parte dei programmatori effettivi con un tempo tipico a disposizione per ottimizzare, non raggiungono comunque il loro potenziale.
Steve Jessop,

9
@nTuply, quello esiste. Il processo di passaggio da quel linguaggio extra-assembly alle istruzioni della macchina si chiama compilazione.
Paul Draper,

3
@PJTraill Non vi è alcun motivo per scrivere un compilatore in assembler su un sistema moderno, ad eccezione del primo passo di bootstrap (e la maggior parte delle volte, nemmeno allora). I compilatori scritti in un linguaggio ad alto livello sono di gran lunga maggiori probabilità di essere effettivamente gestibile. Anche confrontare Come può un linguaggio il cui compilatore è scritto in C può mai essere più veloce di C? . Lo scopo di un compilatore è tradurre da una lingua (la lingua di origine) a un'altra (di solito linguaggio macchina per una specifica architettura e sistema operativo); questo può essere scritto in qualsiasi lingua.
un CVn

13

La DEFINIZIONE del linguaggio assembly è che è una lingua che può essere tradotta direttamente nel codice macchina. Ogni codice operazione in linguaggio assembly si traduce esattamente in un'operazione sul computer di destinazione. (Bene, è un po 'più complicato di così: alcuni assemblatori determinano automaticamente una "modalità di indirizzamento" basata su argomenti a un codice operativo. Tuttavia, il principio è che una linea di assemblaggio si traduce in un'istruzione di linguaggio macchina.)

È possibile, senza dubbio, inventare una lingua che assomiglierebbe a quella dell'assembly ma che sarebbe tradotta in diversi codici macchina su computer diversi. Ma per definizione, questo non sarebbe il linguaggio assembly. Sarebbe un linguaggio di livello superiore che ricorda il linguaggio assembly.

La tua domanda è un po 'come chiedere: "È possibile fare una barca che non galleggia o non ha altri modi per viaggiare sull'acqua, ma ha ruote e un motore e può viaggiare a terra?" La risposta sarebbe che, per definizione, un tale veicolo non sarebbe una barca. Sembra più una macchina.


1
C è stato spesso descritto come "linguaggio assembly portatile".
Larry Gritz,

2
@LarryGritz Sure. E quando è stato inventato il C, è stato rivoluzionario: ha offerto gran parte del potere del linguaggio assembly con la facilità d'uso di un compilato. Ma per definizione, è ancora un linguaggio compilato
Jay,

8

Non v'è alcun concettuale (oserei dire, nessun computer science ) ragione contro avendo uno il linguaggio assembly per tutti i computer del mondo. In effetti, ciò renderebbe molte cose molto più facili. Per quanto riguarda la teoria, sono tutti uguali, comunque, fino a qualche biiezione funky.

In pratica, tuttavia, esistono chip diversi per scopi diversi, con operazioni e principi di progettazione diversi (ad esempio RISC vs CISC) che servono obiettivi diversi e i set di istruzioni che li gestiscono e pertanto i linguaggi di assemblaggio differiscono. Alla fine, la risposta è la stessa di quando ci si chiede perché ci siano così tanti linguaggi di programmazione diversi: obiettivi diversi, decisioni progettuali diverse.

Detto questo, puoi ovviamente introdurre livelli di astrazione per arrivare a un'interfaccia condivisa. x86, per esempio, è stato eliminato a livello di chip da un po 'di tempo; c'è un piccolo pezzo di hardware che traduce le istruzioni x86 in qualunque cosa il tuo processore funzioni davvero . Lingue come C sarebbero un altro passo dall'hardware (seppur probabilmente minuscolo), fino a lingue come Haskell, Java o Ruby. Sì, il compilatore è uno dei principali risultati dell'informatica perché rende possibile separare le preoccupazioni in questo modo.


6
"se discutibilmente minuscolo" - ci sono i tuoi due tipi di programmatore proprio lì. Coloro che considerano C un linguaggio di basso livello perché le sue operazioni di base assomigliano molto al tipo di cose che compaiono nei set di istruzioni della CPU e quelli che considerano C un linguaggio di alto livello perché non è lo stesso set di istruzioni della macchina.
Steve Jessop,

Se per linguaggio assembly si intende uno che dà il controllo completo sul codice macchina generato per un tipo specifico (o famiglia) di hardware, sarebbe possibile definire una lingua "per tutti i computer" nel nostro mondo in un dato momento, ma sarebbe continuare a cambiare. Sarebbe certamente (se ben progettato) abbreviare la curva di apprendimento per la codifica per una nuova architettura, ma mi aspetto che qualsiasi lavoro che vorresti fare con esso piuttosto che un compilatore si applicherebbe solo a una piccola frazione di architetture. Che i computer siano gli stessi a livello astratto è un'aringa rossa, si tratta di codice macchina.
PJTraill,

7

Citi la frase "scrivi una volta corri ovunque" senza sembrare accorgersene. Questo è lo slogan di marketing per Sun Microsystems che commercialmente ha inventato il concetto di una "macchina virtuale" e "bytecode" per Java, anche se forse l'idea potrebbe aver avuto origine nel mondo accademico 1 °. L'idea è stata successivamente copiata da Microsoft per .Net dopo essere stati citati con successo da Sun per violazione della violazione delle licenze Java. I bytecode Java sono un'implementazione dell'idea di assembly o linguaggio macchina cross-machine. Sono usati per molte altre lingue oltre a Java e possono teoricamente essere usati per compilare qualsiasi lingua. Dopo molti anni di ottimizzazione molto avanzata, Java si avvicina nelle prestazioni ai linguaggi compilati mostrando che l'obiettivo della tecnologia della macchina virtuale indipendente dalla piattaforma ad alte prestazioni è raggiungibile in generale.

Un'altra nuova idea nelle prime fasi / circolazione relativa alle vostre esigenze si chiama progetto di ricomputazione ed è per la ricerca scientifica sebbene possa essere usata per altri scopi. L'idea è di rendere replicabili gli esperimenti computazionali tramite la tecnologia delle macchine virtuali. Questa è principalmente l'idea di simulare diverse architetture di macchine su hardware arbitrario.


8
Sun non ha inventato né macchine virtuali né codice byte, non erano nemmeno il primo gruppo a guadagnare da loro. Cerca il codice p.
jmoreno,

@jmoreno: potrebbe anche voler cercare Smalltalk.
Bob Jarvis - Ripristina Monica l'

l'articolo non rivendica macchine virtuali / codice byte inventati da Sun. c'è altra storia non citata ma citata. tra l'altro un'altra tecnologia chiave molto rilevante qui: google native client (funzione chrome)
vzn

5

Ragioni di alto livello

Quando ci pensi, un microprocessore fa una cosa incredibile: ti consente di prendere una macchina (come una lavatrice o un ascensore) e sostituire un intero pezzo di meccanismi o circuiti progettati su misura con un silicio economico prodotto in serie patata fritta. Risparmia un sacco di soldi sulle parti e molto tempo sul design.

Ma aspetta, un chip standard , che sostituisce innumerevoli design personalizzati ? Non può esistere un singolo microprocessore perfetto per ogni applicazione. Alcune applicazioni devono ridurre al minimo il consumo di energia ma non devono essere veloci; altri devono essere veloci ma non devono essere facili da programmare, altri devono essere a basso costo, ecc.

Quindi, abbiamo molti "sapori" diversi di microprocessore, ognuno con i suoi punti di forza e di debolezza. È auspicabile che tutti utilizzino un set di istruzioni compatibile, poiché ciò consente il riutilizzo del codice e facilita la ricerca di persone con le giuste competenze. Tuttavia, il set di istruzioni non incidere sul costo, la complessità, la velocità, la facilità d'uso e vincoli fisici del processore, e quindi abbiamo un compromesso: NON alcuni "tradizionali" set di istruzioni (e molti minori), e all'interno di ogni set di istruzioni ci sono molti processori con caratteristiche diverse.

Oh, e quando la tecnologia cambia, tutti questi compromessi cambiano, quindi i set di istruzioni si evolvono, ne emergono di nuovi e quelli vecchi muoiono. Anche se ci fosse un "migliore" set di istruzioni di oggi, potrebbe non essere tra 20 anni.

Dettagli hardware

Probabilmente la più grande decisione di progettazione in un set di istruzioni è la dimensione della parola , ovvero quanto un numero può essere "naturalmente" manipolato dal processore. I processori a 8 bit gestiscono numeri da 0 a 255, mentre i processori a 32 bit gestiscono numeri da 0 a 4.294.967.295. Il codice progettato per uno deve essere completamente ripensato per un altro.

Non si tratta solo di tradurre le istruzioni da un set di istruzioni a un altro. Un approccio completamente diverso può essere preferibile in un set di istruzioni diverso. Ad esempio, su un processore a 8 bit una tabella di ricerca potrebbe essere l'ideale, mentre su un processore a 32 bit un'operazione aritmetica sarebbe migliore per lo stesso scopo.

Vi sono altre importanti differenze tra i set di istruzioni. La maggior parte delle istruzioni rientra in quattro categorie:

  • Calcolo (aritmetica e logica)
  • Flusso di controllo
  • Trasferimento dati
  • Configurazione del processore

I processori si differenziano per il tipo di calcoli che possono eseguire, nonché per il modo in cui si avvicinano al flusso di controllo, al trasferimento dei dati e alla configurazione del processore.

Ad esempio, alcuni processori AVR non possono né moltiplicarsi né dividere; mentre tutti i processori x86 possono farlo. Come puoi immaginare, l'eliminazione dei circuiti necessari per attività come la moltiplicazione e la divisione può rendere un processore più semplice ed economico; queste operazioni possono ancora essere eseguite utilizzando routine software se sono necessarie.

x86 consente alle istruzioni aritmetiche di caricare i loro operandi dalla memoria e / o salvare i loro risultati in memoria; ARM è un'architettura load-store e quindi ha solo alcune istruzioni dedicate per l'accesso alla memoria. Nel frattempo x86 ha istruzioni dedicate al ramo condizionale, mentre ARM permette praticamente a tutte le istruzioni di essere eseguite in modo condizionale. Inoltre, ARM consente di eseguire i bit-shift come parte della maggior parte delle istruzioni aritmetiche. Queste differenze portano a caratteristiche prestazionali diverse, differenze nella progettazione interna e nel costo dei chip e differenze nelle tecniche di programmazione a livello di linguaggio assembly.

Conclusione

Il motivo per cui è impossibile avere un linguaggio assembly universale è che, per convertire correttamente il codice assembly da un set di istruzioni in un altro, è necessario progettare nuovamente il codice, cosa che i computer non possono ancora fare.


Risposta eccellente! Le persone non comprendono abbastanza bene che le cose informatiche che devono essere programmate sono ovunque tra noi. Non sono solo le applicazioni che vediamo in esecuzione sui nostri schermi. Quanti miliardi di chip vengono prodotti ogni anno?
phs,

4

Aggiungendo alla meravigliosa risposta di DW: se si desidera avere un assemblatore, è necessario mantenere tutte le architetture, un traduttore perfetto tra loro e comprendere appieno cosa si sta facendo.
Alcuni codici fortemente ottimizzati per un'architettura dovrebbero essere de-ottimizzati, compresi a un livello più astratto e ottimizzati l'uno per l'altro.
Ma se ciò fosse possibile, avremmo un compilatore C perfetto e scrivere in puro assemblaggio non sarebbe affatto vantaggioso.
Il punto principale dell'utilizzo dell'assemblatore è la prestazione, che non può essere compresso dai compilatori recenti.
Scrivere un programma del genere sarebbe ancora più difficile dei compilatori esistenti e mantenere tutte le nuove architetture create lo renderebbe ancora più difficile.
E per il programma "solo uno", significherebbe anche la piena retrocompatibilità.


Nella stragrande maggioranza dei casi, gcc esegue un'ottimizzazione migliore rispetto a un programmatore. Il punto principale dell'utilizzo dell'assemblatore è fare cose che non si possono fare in C come accedere ai registri. Se guardi l'albero dei sorgenti di Linux è praticamente quello per cui usano assembly.
Slebetman,

@slebetman - gcc consente di inserire una variabile in un registro senza ricorrere all'assembly.
Jirka Hanika,

@JirkaHanika: stai parlando dei registri della CPU o dei registri hardware per scopi speciali indirizzati con istruzioni speciali? Sospetto che slebetman significhi quest'ultimo.
PJTraill

"Tutti i codici" - "GCC does better" = "you use assembler". Sì, è possibile accedere ai registri senza inserimenti dell'assemblatore.
Evil

@PJTraill - Il commento di Slebetman è generalmente eccellente e forse dovrebbe essere incorporato nella risposta. Ma entrambi i suoi esempi (accesso al registro e albero dei sorgenti di Linux) probabilmente alimenteranno idee sbagliate comuni piuttosto che essere esempi eccellenti di ciò che non si può fare in C con estensioni di gcc; quelli dovrebbero essere sostituiti o omessi. (Se c'è un'istruzione HW per fare qualcosa oggi, avrai la corrispondente estensione gcc tra un anno da oggi. Non sempre, ma molto spesso. Esempi di età.)
Jirka Hanika

3

Microsoft ha inventato MSIL come linguaggio assembly intermedio. I programmi verrebbero compilati da C # o VB.Net a MSIL. In fase di esecuzione, MSIL è stato compilato in codice macchina per la macchina che lo stava eseguendo utilizzando un compilatore JIT . Il file contenente MSIL era un file .EXE con alcune istruzioni all'inizio in X86 per avviare il programma. Su un processore ARM, dovresti digitare la parola mono davanti al nome del programma per eseguirlo.


Qual è la differenza tra "linguaggio assembly intermedio" e "macchina virtuale"?
Bob Jarvis - Ripristina Monica l'

@BobJarvis: uno è il codice mentre l'altro è un interprete. Avresti dovuto chiedere qual è la differenza tra assembly intermedio e bytecode
slebetman

Questo non sembra rispondere alla domanda. Finché ogni macchina compila / assembla MSIL in modo diverso, non c'è nulla di universale in ciò, e lo scopo di tale compilazione è il porting di funzionalità generiche e non lo sfruttamento di un particolare set di istruzioni che, come sottolinea DW, è il (o a) motivo dell'utilizzo dell'assemblatore.
PJTraill

3

Come notato, LLVM è la cosa più vicina a questa finora. Un grande ostacolo a un linguaggio veramente universale saranno le differenze fondamentali legate a compromessi impliciti: concorrenza, uso della memoria, velocità effettiva, latenza e consumo energetico. Se scrivi in ​​uno stile esplicitamente SIMD, potresti usare troppa memoria. Se si scrive in uno stile SISD esplicito, si otterrebbe una parallelizzazione non ottimale. Se ottimizzi per la velocità effettiva, danneggi la latenza. Se si massimizza la velocità di trasmissione a thread singolo (ovvero: velocità di clock), si compromette la durata della batteria.

Per lo meno, il codice dovrebbe essere annotato con i compromessi. Ciò che può essere più importante è che il linguaggio abbia buone proprietà algebriche / di tipo che danno al compilatore un ampio margine di manovra per ottimizzare e rilevare incoerenze logiche.

Quindi c'è la questione del comportamento indefinito. Gran parte della velocità di linguaggio C e assembly deriva da un comportamento indefinito. Se ammetti comportamenti indefiniti che si verificano effettivamente, finisci per gestirli come casi speciali (ad esempio: hack specifici per architettura e contesto).


0

Forse quello che stai cercando è una notazione Universal Turning Machine in cui tutti sono d'accordo sui simboli per i comandi. ( https://en.wikipedia.org/wiki/Universal_Turing_machine )

Un "assemblatore" che traduce una lingua che si trasforma in accettabile nel codice macchina specifico del fornitore sottostante e che viene creato per una qualsiasi delle cose che chiamiamo computer.

In The Art of Computer Programming c'è un esempio di come potrebbe apparire.

Ma considera la domanda "perché non è un linguaggio universale disponibile in commercio che può essere usato con tutti i computer". Suggerirei che le influenze più dominanti siano (1) convenienza, non tutti i linguaggi di assemblaggio sono i più comodi da usare; (2) l'economia, la fornitura, l'incompatibilità tra macchine di marchi e fornitori diversi è una strategia aziendale nonché il risultato di risorse limitate (tempo / denaro) per progettare macchine.


La domanda è su un linguaggio assembly che può essere utilizzato per programmare qualsiasi computer, non un linguaggio assembly che sia universale nel senso di "macchina di Turing universale".
David Richerby,

1
Church-Turing ci dice che l'UTC può fare ciò che può fare qualsiasi computer programmabile. A parte problemi di archiviazione fisica finiti. Un linguaggio assembly per un UTC è abbastanza fattibile. Ma come ho detto, la praticità culturale ed economica può limitare l'effettiva attuazione e adozione sul mercato.
Chris,

Ti manca il problema più grande, ovvero le prestazioni ! Perché usare un linguaggio 1000 volte più lento solo per un obiettivo nobile di essere indipendente dall'hardware? La Turing Machine è un modello terribile per il calcolo pratico.
Artelius,

1
Ai commentatori piacerebbe offrire qualche informatica per sostenere le loro affermazioni? Questo è dopo tutto il forum di informatica.
Chris,

1
Non sono un esperto di CS. Ma quello che credo è che l'architettura von Neumann è un brillante pezzo di ingegneria che trova un equilibrio tra programmabilità e prestazioni, mentre lo scopo della macchina di Turing è mostrare che anche la macchina più semplice può calcolare tutto ciò che una macchina più complessa potrebbe. Certo, puoi continuare ad aggiungere sempre più funzionalità a una macchina Turing (più nastri, aritmetica), ma poi ottieni lo stesso problema che hai avuto in primo luogo, vale a dire le persone che non concordano su un set di istruzioni. Inoltre, la mancanza di accesso casuale crea grandi spese generali in molti algoritmi.
Artelius,

0

ipotesi: compilare e ottimizzare una lingua di alto livello L1 in una lingua di livello inferiore L0 è più semplice della compilazione e dell'ottimizzazione di una lingua di alto livello da L2 (superiore a L1) a L0; più facile nel senso che presumibilmente puoi generare codice più ottimizzato durante la compilazione da L1 a L0 rispetto a L2 a L0.

Penso che il presupposto sia probabilmente corretto, ecco perché probabilmente la maggior parte dei compilatori usa un linguaggio intermedio di basso livello (IR / LLVM).

se questo è vero, utilizzare qualsiasi linguaggio di basso livello L0 e scrivere compilatori per tradurre L0 in altre lingue di basso livello. Ad esempio, utilizzare il set di istruzioni MIPS e compilarlo in x86, arm, power, ...

-Taoufik


Quindi non sai se la tua risposta è vera? E non puoi supportarlo?
Evil
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.