Perché abbiamo bisogno del linguaggio assembly?
Bene, in realtà c'è solo una lingua di cui avremo mai bisogno , che si chiama "linguaggio macchina" o "codice macchina". Sembra così:
0010000100100011
Questa è l'unica lingua che il tuo computer può parlare direttamente. È il linguaggio che parla una CPU (e tecnicamente, diversi tipi di CPU parlano versioni diverse). Fa anche schifo guardare e cercare di capire.
Fortunatamente, ogni sezione di binario corrisponde a un significato particolare. È diviso in diverse sezioni:
0010|0001|0010|0011
operation type source register other source destination register
0010 0001 0010 0011
Questi valori corrispondono a:
operation type 0010 = addition
source register 0001 = register 1
other source 0010 = register 2
destination register 0011 = register 3
Quindi questa operazione aggiungerebbe i numeri nei registri 1 e 2 e inserirà quel valore nel registro 3. Se metti letteralmente questi valori in una CPU e dici "vai", aggiungerà due numeri per te. L'operazione "sottrai" potrebbe essere un 0011 o qualcosa del genere, anziché 0010 qui. Qualunque sia il valore farà sottrarre la CPU.
Quindi un programma potrebbe assomigliare a questo (non cercare di capirlo, dal momento che ho inventato questa particolare versione del codice macchina per spiegare le cose):
instruction 1: 0010000100100011
instruction 2: 0011000110100100
instruction 3: 0101001100010111
instruction 4: 0010001001100000
Fa schifo leggere? Decisamente. Ma ne abbiamo bisogno per la CPU . Bene, se ogni codice macchina corrisponde a una particolare azione, facciamo solo una semplice scorciatoia "inglese", e quindi una volta che capiamo cosa sta facendo il programma, convertilo in un vero codice binario e darlo alla CPU per l'esecuzione.
Quindi le nostre istruzioni originali dall'alto potrebbero apparire come:
(meaning) operation type source register other source destination register
(machine code) 0010 0001 0010 0011
("English") add r1 r2 r3
Si noti che questa versione inglese ha una mappatura esatta al codice macchina . Quindi, quando scriviamo una riga di questo "inglese", stiamo davvero solo scrivendo un codice macchina più amichevole e comprensibile.
Bene, questo è il linguaggio assembly. Ecco perché esiste e perché è stato originariamente creato.
Per capire perché ne abbiamo bisogno ora, leggi le risposte sopra, ma la chiave per capire è questa: i linguaggi di alto livello non hanno una singola rappresentazione è il codice macchina. Ad esempio in C, o Python o qualsiasi altra cosa:
z = x + y
Questo suona proprio come la nostra aggiunta dall'alto, supponendo che x
sia nel registro 1, y
sia nel registro 2 e z
dovrebbe finire nel registro 3. Ma che dire di questa linea?
z = x * 2 + (y / 6) * p + q - r
Prova a rappresentare quella linea in 16 bit di binario e dire a una CPU "go". Non puoi. Il codice macchina non ha una singola istruzione operativa per eseguire addizioni, sottrazioni e quant'altro con 4 o 5 variabili contemporaneamente. Quindi deve prima essere convertito in una sequenza di codice macchina. Questo è ciò che fai quando "compili" o "interpreti" un linguaggio di alto livello.
Bene, abbiamo dei programmi per farlo, quindi perché abbiamo bisogno dell'assemblaggio ora? Bene, supponiamo che il tuo programma stia funzionando più lentamente di quanto ti aspetti, e vuoi sapere perché. Guardando il "output" del linguaggio macchina di questa linea, potrebbe apparire come:
1010010010001001
0010001000010000
0110010000100100
0010001011000010
0010100001000001
0100010100000001
0010010101000100
0010101010100000
0000100111000010
Solo per finire quella riga di Python. Quindi vuoi davvero eseguire il debug di questo?!?!?! NO . Piuttosto, chiedi al tuo compilatore di darti l'output nella forma che puoi effettivamente capire facilmente, che è la versione del linguaggio assembly che corrisponde esattamente a quel codice macchina. Quindi puoi capire se il tuo compilatore sta facendo qualcosa di stupido e provare a risolverlo.
(Nota aggiuntiva sul consiglio di @ Raphael: potresti effettivamente costruire CPU che funzionino con cose diverse dai codici binari, come i codici ternari (base 3) o decimali, o persino ASCII. Tuttavia, per scopi pratici, siamo rimasti fedeli al binario.)