Codice assembly vs codice macchina vs codice oggetto?


227

Qual è la differenza tra codice oggetto, codice macchina e codice assembly?

Puoi dare un esempio visivo della loro differenza?


Sono anche curioso di sapere da dove proviene il nome "codice oggetto"? Cosa significa in essa la parola "oggetto"? È in qualche modo legato alla programmazione orientata agli oggetti o solo a una coincidenza di nomi?
SasQ


Non sto chiedendo cosa sia un codice oggetto, Capitano Ovvio. Sto chiedendo da dove viene il nome e perché si chiama codice "oggetto".
BarbaraKwarc,

Risposte:


296

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 JMPe MULTper 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.


24
+1: bella, ma in qualche modo semplificando la risposta - non tutte le istruzioni di assemblaggio sono tradotte 1: 1 in istruzioni macchina, e i file oggetto possono contenere anche altri dati (informazioni di trasferimento, tabelle dei simboli, ...)
Christoph

5
Aggiunta una parola donnola per il tuo primo numero, modificata per rendere il 2 ° più chiaro.
Joel Coehoorn,

2
@Christoph: dici "non tutte le istruzioni di montaggio sono tradotte 1: 1 in istruzioni macchina", per favore, fai un esempio.
Olof Forshell,

5
@Olof: le architetture RISC a volte forniscono un set di istruzioni virtuali a livello di assembly - ad esempio pseudo-istruzioni MIPS ( en.wikipedia.org/wiki/MIPS_architecture#Pseudo_instructions )
Christoph

3
@Panzercrisis Nulla viene aggiunto dall'assemblatore. È una traduzione diretta di ciò che hai scritto nelle istruzioni reali della macchina. E non definirei il codice aggiuntivo inserito dai compilatori "non necessario"
Joel Coehoorn,

125

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.


3
Lo trovo davvero utile, ma manca l'etichetta "Codice macchina"
Alexx Roche

Quindi quando è a livello di codice eseguibile, è equivalente al codice macchina?
CMCDragonkai,

3
Nel contesto di questo diagramma, il "codice oggetto" è il codice macchina.
Noob Graphics

5
In realtà, sia il codice oggetto che il codice eseguibile sono codici macchina. la differenza è che il codice oggetto non è il programma completato. Deve essere combinato con altri codici di libreria / modulo dell'helper come indicato nel diagramma per formare un programma / codice eseguibile completo.
okey_on

@okeyxyz a quale livello sarebbe corretto dire che viene eseguito direttamente dal processore? Dopo l'assemblatore, dopo il linker, dopo il caricatore, dopo che viene convertito in microcontrollore?
Celeritas,

49

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.


76
No no no no. Il codice macchina non è un codice esadecimale. è binario puro. Il codice esadecimale è solo una rappresentazione conveniente del binario.
Breton,

56
Se stiamo davvero andando al limite, non è binario, è una quantità di elettricità immagazzinata in un circuito. ;-)
Toon Krij il

17
Sì, naturalmente. Esiste una relazione tra l'esadecimale e quello che chiamereste "Codice macchina", ma non è del tutto esatto affermare che il codice esadecimale è codice macchina. Questo è tutto ciò che sto cercando di dire.
Breton,

9
@Breton In questo senso, non esiste un "codice esadecimale" giusto? "Codice esadecimale" è solo un modo per visualizzare il codice macchina. È possibile visualizzare il codice macchina in esadecimale, binario, ottale, decimale o come preferisci. Anche in questo senso, non esiste un "codice binario". Ancora una volta, il "codice binario" è solo un modo per visualizzare il codice macchina.
Utku,

9
@Breton Quello che dici non ha molto senso .. Il binario è un modo di rappresentazione, proprio come esadecimale. Se non è esadecimale, non è neanche binario.
Koray Tugay,

18

8B 5D 32 è il codice macchina

mov ebx, [ebp+32h] è il montaggio

lmylib.socontenente 8B 5D 32è il codice oggetto


8

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.


1
+1. Un ulteriore punto in più: esistono anche diverse sintassi del linguaggio assembly , la più famosa delle quali è Intel e AT&T .
informatik01,

1
@ informatik01: Che ne dici di Intel 8080 mnemonics vs Zilog Z80? Immagino che sia anteriore alla guerra di sintassi Intel vs AT&T.
supercat

Non discutendo, ho appena menzionato quell'aspetto (sintassi diversa) e ho dato un esempio di due sintassi più popolari / conosciute / famose.
informatik01,

4

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.


Tipi di codice


Codice sorgente

Istruzioni in linguaggio (programmazione) leggibile dall'uomo


Codice di alto livello

Istruzioni scritte in un linguaggio di alto livello (programmazione),
ad esempio programmi C, C ++ e Java


Codice di montaggio

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


Codice oggetto

Il prodotto di un processo di compilazione. Può essere sotto forma di codice macchina o codice byte.
ad es. file.o


Codice macchina

Istruzioni in linguaggio macchina.
ad es. a.out


Codice byte

Istruzioni in una forma intermedia che può essere eseguita da un interprete come JVM.
ad esempio, file di classe Java


File eseguibile

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.


File della libreria

Parte del codice viene compilato in questo modulo per diversi motivi come la riutilizzabilità e successivamente utilizzato dai file eseguibili.


1
Direi che non tutta l'assemblea è veramente fonte nel senso più stretto del codice scritto e / o mantenuto dagli umani. Spesso è generato automaticamente dalla fonte e non è mai destinato al consumo umano (ad esempio, gcc crea davvero un testo asm che alimenta a un assemblatore separato, invece di avere un assemblatore incorporato all'interno cc1dell'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.
Peter Cordes,

@PeterCordes Grazie mille per il commento. Non ero a conoscenza di quello che hai detto sul funzionamento di gcc. Tuttavia, temo di poter essere completamente d'accordo con te. Voglio dire, il codice sorgente è qualcosa di scritto usando un linguaggio di programmazione leggibile dall'uomo. Può essere o meno scritto o mantenuto dagli umani. Sono sicuro che sarai a conoscenza dei transcompilatori. Dal tuo punto di vista, a quale categoria metterai il prodotto di un tale compilatore? Codice sorgente o qualcos'altro? Per favore correggimi se sbaglio. Ulteriori commenti sono sempre ben accetti.
Bertram Gilfoyle,

1

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


1

Penso che queste siano le principali differenze

  • leggibilità del codice
  • controllo su cosa sta facendo il tuo codice

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.


1

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.


Il tuo commento su Java e C # - entrambi usano la compilazione Just In Time in modo che i bytecode non vengano interpretati. C # (.NET in genere) viene compilato in Intermediate Language (IL), che viene quindi JIT in linguaggio macchina nativo per la CPU di destinazione.
Craig Shearer,

-1

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

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.