Il Microprocessore
Le istruzioni del microprocessore
Anche il più piccolo e semplice microprocessore (come quello che abbiamo visto in precedenza) deve avere un set di istruzioni che può eseguire. Ogni istruzione è in pratica una serie di bits che vengono caricati di volta in volta nel registro istruzioni. Ovviamente è quasi impossibile memorizzare delle sequenze di 0 e 1 e ricordarle, quindi per facilitare la programmazione dei microprocessori vengono ridefiniti usando delle brevi parole (short words).
Questa collezione di brevi parole formano il linguaggio assembler. Attraverso un traduttore assembler è possibile successivamente trasformare ogni singola "parola" in sequenze di bits che vengono inserite in memoria per essere eseguite dal microprocessore.
Ecco una sequenza di possibili parole che potrebbero essere create per il nostro microprocessore di esempio:
- LOADA mem - Carica il registro A con un valore di memoria
- LOADB mem - Carica il registro B con un valore di memoria
- CONB con - Carica il registro B con una costante
- SAVEB mem - Salva il registro B in un indirizzo di memoria
- SAVEC mem - Salva il registro C in un indirizzo di memoria
- ADD - Somma A e B e mette il risultato in C
- SUBD - Sottrae B da A e mette il risultato in C
- MUL - Moltiplica A e B e mette il risultato in C
- DIV - Divide A con B e mette il risultato in C
- COMP - Confronta A e B e mette il risultato in C
- JUMP addr - Salta ad un indirizzo
- JEQ addr - Salta ad un indirizzo se uguale
- JNEQ addr - Salta ad un indirizzo se non uguale
- JG addr - Salta ad un indirizzo se maggiore
- JL addr - Salta ad un indirizzo se minore
- STOP - Ferma l'esecuzione
Ecco un esempio di programma in Assembler:
// Assume a is at address 128 // Assume F is at address 129 0 CONB 1 // a=1; 1 SAVEB 128 2 CONB 1 // f=1; 3 SAVEB 129 4 LOADA 128 // if a > 5 the jump to 17 5 CONB 5 6 COM 7 JG 17 8 LOADA 129 // f=f*a; 9 LOADB 128 10 MUL 11 SAVEC 129 12 LOADA 128 // a=a+1; 13 CONB 1 14 ADD 15 SAVEC 128 16 JUMP 4 // loop back to if 17 STOP
Come abbiamo già detto ogni singola parola deve essere definita nella ROM con il corrispondente valore numerico (detto opcode). Ecco un esempio di codifica:
LOADA - 1 LOADB - 2 CONB - 3 SAVEB - 4 SAVEC mem - 5 ADD - 6 SUB - 7 MUL - 8 DIV - 9 COM - 10 JUMP addr - 11 JEQ addr - 12 JNEQ addr - 13 JG addr - 14 JGE addr - 15 JL addr - 16 JLE addr - 17 STOP - 18Il nostro programma, codificato opportunamente sostituendo ad ogni parola il corrispndente opcode diventerà così:
// Assume a is at address 128 // Assume F is at address 129 Addr opcode/value 0 3 // CONB 1 1 1 2 4 // SAVEB 128 3 128 4 3 // CONB 1 5 1 6 4 // SAVEB 129 7 129 8 1 // LOADA 128 9 128 10 3 // CONB 5 11 5 12 10 // COM 13 14 // JG 17 14 31 15 1 // LOADA 129 16 129 17 2 // LOADB 128 18 128 19 8 // MUL 20 5 // SAVEC 129 21 129 22 1 // LOADA 128 23 128 24 3 // CONB 1 25 1 26 6 // ADD 27 5 // SAVEC 128 28 128 29 11 // JUMP 4 30 8 31 18 // STOPIl programma che abbiamo appena visto è in realtà una semplice routine che calcola il fattoriale di un numero. In altri linguaggi (Visual Basic o C) l'avremmo scritta con 10 o al massimo 15 righe. In assembler come visto ne occorrono 17 che poi diventano 31 bytes in ROM/RAM.
Il componente del microprocessore che poi legge e traduce questi opcode in una serie di segnali che muovono i differenti componenti del processore è l' instruction decoder.