Qual è la differenza tra codice oggetto, codice macchina e codice assembly?
Puoi dare un esempio visivo della loro differenza?
Qual è la differenza tra codice oggetto, codice macchina e codice assembly?
Puoi dare un esempio visivo della loro differenza?
Risposte:
Il codice macchina è un codice binario (1 e 0) che può essere eseguito direttamente dalla CPU. Se dovessi aprire un file di codice macchina in un editor di testo, vedresti immondizia, inclusi caratteri non stampabili (no, non quei caratteri non stampabili;)).
Il codice oggetto è una parte del codice macchina che non è stata ancora collegata in un programma completo. È il codice macchina per una particolare libreria o modulo che comporrà il prodotto completo. Può anche contenere segnaposto o offset non presenti nel codice macchina di un programma completato. Il linker utilizzerà questi segnaposto e offset per collegare tutto insieme.
Il codice assembly è un codice sorgente di testo semplice e (in qualche modo) leggibile dall'uomo che ha principalmente un analogo diretto 1: 1 con le istruzioni della macchina. Ciò si ottiene utilizzando mnemonici per le istruzioni, i registri o altre risorse effettive. Gli esempi includono JMP
e MULT
per le istruzioni di salto e moltiplicazione della CPU. A differenza del codice macchina, la CPU non comprende il codice assembly. Converti il codice assembly in machine con l'uso di un assemblatore o di un compilatore , sebbene di solito pensiamo ai compilatori in associazione con un linguaggio di programmazione di alto livello che sono astratte ulteriormente dalle istruzioni della CPU.
La creazione di un programma completo implica la scrittura del codice sorgente del programma in assembly o in un linguaggio di livello superiore come C ++. Il codice sorgente viene assemblato (per codice assembly) o compilato (per linguaggi di livello superiore) in codice oggetto e i singoli moduli vengono collegati insieme per diventare il codice macchina per il programma finale. Nel caso di programmi molto semplici, la fase di collegamento potrebbe non essere necessaria. In altri casi, ad esempio con un IDE (ambiente di sviluppo integrato), il linker e il compilatore possono essere richiamati insieme. In altri casi, un complicato make script o soluzione file può essere utilizzato per indicare l'ambiente come costruire l'applicazione finale.
Ci sono anche lingue interpretate che si comportano diversamente. Le lingue interpretate si basano sul codice macchina di un programma interprete speciale. A livello base, un interprete analizza il codice sorgente e converte immediatamente i comandi in un nuovo codice macchina e li esegue. Gli interpreti moderni, a volte chiamati anche ambiente di runtime o macchine virtuali , sono molto più complicati: valutare intere sezioni di codice sorgente alla volta, memorizzare nella cache e ottimizzare ove possibile e gestire complesse attività di gestione della memoria. Un linguaggio interpretato può anche essere precompilato in un linguaggio intermedio o bytecode di livello inferiore, simile al codice assembly.
Le altre risposte hanno fornito una buona descrizione della differenza, ma hai anche chiesto un elemento visivo. Ecco un diagramma che mostra il loro viaggio dal codice C a un eseguibile.
Il codice assembly è una rappresentazione leggibile dall'uomo del codice macchina:
mov eax, 77
jmp anywhere
Il codice macchina è puro codice esadecimale:
5F 3A E3 F1
Suppongo che intendi il codice oggetto come in un file oggetto. Questa è una variante del codice macchina, con la differenza che i salti sono in qualche modo parametrizzati in modo che un linker possa riempirli.
Un assemblatore viene utilizzato per convertire il codice assembly in codice macchina (codice oggetto) Un linker collega diversi file oggetto (e libreria) per generare un eseguibile.
Una volta ho scritto un programma assemblatore in esadecimale puro (nessun assemblatore disponibile) per fortuna questo era molto tempo fa sul buon vecchio (antico) 6502. Ma sono contento che ci siano assemblatori per i codici operativi del pentium.
Un punto non ancora menzionato è che esistono diversi tipi di codice assembly. Nella forma più semplice, tutti i numeri utilizzati nelle istruzioni devono essere specificati come costanti. Per esempio:
$ 1902: BD 37 14: LDA $ 1437, X $ 1905: 85 03: STA $ 03 $ 1907: 85 09: STA $ 09 $ 1909: CA: DEX $ 190A: 10: BPL $ 1902
Il bit di codice sopra, se memorizzato all'indirizzo $ 1900 in una cartuccia Atari 2600, visualizzerà un numero di righe in diversi colori prelevate da una tabella che inizia all'indirizzo $ 1437. Su alcuni strumenti, digitando un indirizzo, insieme alla parte più a destra della riga in alto, si memorizzerebbero i valori mostrati nella colonna centrale e si inizierà la riga successiva con il seguente indirizzo. Digitare il codice in quella forma era molto più conveniente che digitare in esadecimale, ma bisognava conoscere gli indirizzi precisi di tutto.
La maggior parte degli assemblatori consente di utilizzare indirizzi simbolici. Il codice sopra sarebbe scritto più simile a:
rainbow_lp: lda ColorTbl, x sta WSYNC sta COLUBK dex bpl rainbow_lp
L'assemblatore regolerebbe automaticamente l'istruzione LDA in modo da fare riferimento a qualsiasi indirizzo mappato all'etichetta ColorTbl. L'uso di questo stile di assemblatore rende molto più semplice la scrittura e la modifica del codice di quanto sarebbe possibile se si dovesse digitare manualmente e mantenere tutti gli indirizzi.
Codice sorgente, Codice assieme, Codice macchina, Codice oggetto, Codice byte, File eseguibile e File libreria.
Tutti questi termini sono spesso molto confusi per la maggior parte delle persone per il fatto che pensano di essere reciprocamente esclusivi . Vedi il diagramma per capire le loro relazioni. La descrizione di ciascun termine è riportata di seguito.
Istruzioni in linguaggio (programmazione) leggibile dall'uomo
Istruzioni scritte in un linguaggio di alto livello (programmazione),
ad esempio programmi
C, C ++ e Java
Istruzioni scritte in un linguaggio assembly (tipo di linguaggio di programmazione di basso livello). Come primo passo del processo di compilazione, il codice di alto livello viene convertito in questo modulo. È il codice assembly che viene quindi convertito in codice macchina reale. Sulla maggior parte dei sistemi, questi due passaggi vengono eseguiti automaticamente come parte del processo di compilazione.
ad esempio, program.asm
Il prodotto di un processo di compilazione. Può essere sotto forma di codice macchina o codice byte.
ad es. file.o
Istruzioni in linguaggio macchina.
ad es. a.out
Istruzioni in una forma intermedia che può essere eseguita da un interprete come JVM.
ad esempio, file di classe Java
Il prodotto del collegamento del processo. Sono codici macchina che possono essere eseguiti direttamente dalla CPU.
ad es. un file .exe.
Si noti che in alcuni contesti un file contenente istruzioni in codice byte o linguaggio di script può essere considerato eseguibile.
Parte del codice viene compilato in questo modulo per diversi motivi come la riutilizzabilità e successivamente utilizzato dai file eseguibili.
cc1
dell'eseguibile). Penso che il cerchio asm dovrebbe sporgere dalla parte sinistra del cerchio "sorgente", perché alcuni asm sono solo asm, non sorgente. Ovviamente non è mai un codice oggetto , ma un po 'di asm è un passaggio dalla sorgente ai file oggetto.
Il codice di assemblaggio è discusso qui .
"Un linguaggio assembly è un linguaggio di basso livello per la programmazione dei computer. Implementa una rappresentazione simbolica dei codici numerici della macchina e delle altre costanti necessarie per programmare una particolare architettura della CPU."
Il codice macchina è discusso qui .
"Il codice macchina o il linguaggio macchina è un sistema di istruzioni e dati eseguiti direttamente dall'unità centrale di elaborazione di un computer."
Fondamentalmente, il codice assembler è il linguaggio ed è tradotto in codice oggetto (il codice nativo che la CPU esegue) da un assemblatore (analogo a un compilatore).
Penso che queste siano le principali differenze
La leggibilità può migliorare o sostituire il codice 6 mesi dopo che è stato creato con sforzo litte, d'altra parte, se le prestazioni sono fondamentali, potresti voler usare un linguaggio di basso livello per indirizzare l'hardware specifico che avrai in produzione, quindi per ottenere esecuzione più veloce.
Oggi i computer IMO sono abbastanza veloci da consentire a un programmatore di eseguire rapidamente l'esecuzione con OOP.
Assembly è brevi termini descrittivi che gli esseri umani possono comprendere e che possono essere tradotti direttamente nel codice macchina che una CPU effettivamente utilizza.
Sebbene un po 'comprensibile per l'uomo, Assembler è ancora di basso livello. Ci vuole molto codice per fare qualcosa di utile.
Quindi invece usiamo linguaggi di livello superiore come C, BASIC, FORTAN (OK, so di essere uscito con me stesso). Una volta compilati, producono un codice oggetto. Le prime lingue avevano il linguaggio macchina come codice oggetto.
Oggi molte lingue come JAVA e C # di solito si compongono in un bytecode che non è un codice macchina, ma uno che può essere facilmente interpretato in fase di esecuzione per produrre codice macchina.
I file sorgente dei programmi vengono compilati in file oggetto, quindi il linker collega i file oggetto insieme, producendo un file eseguibile che include i codici macchina dell'architettura.
Sia il file oggetto che il file eseguibile coinvolgono il codice macchina dell'architettura sotto forma di caratteri stampabili e non stampabili quando viene aperto da un editor di testo.
Tuttavia, la dicotomia tra i file è che i file oggetto possono contenere riferimenti esterni non risolti (come printf
, ad esempio). Quindi, potrebbe essere necessario essere collegato ad altri file oggetto. Vale a dire, i riferimenti esterni non risolti sono necessari per essere risolti al fine di ottenere il file eseguibile eseguibile decente collegandosi con altri file oggetto come la libreria di runtime C / C ++ .