Nessun effetto è in natura sanza ragione, intendi la ragione e non ti bisogna sperienza
MICROPROCESSORI E MICROCONTROLLORI
… studiare, studiare ed ancora studiare,
è il solo modo di capire quanto possa
essere grande sia la propria ignoranza!
LINGUAGGIO DI PROGRAMMAZIONE
Un’istruzione è una configurazione binaria che produce una ben
definita azione da parte della CPU.
Il set di istruzioni rappresenta uno dei fattori che determinano le
prestazioni di un microprocessore.
Il programma è un insieme di istruzioni che consente di svolgere
un compito specifico, è in altri termini l’intelligenza del sistema.
Un programma scritto in codice binario è definito programma in
linguaggio macchina o anche programma oggetto.
Il binario è l’unico tipo di linguaggio che un sistema digitale è in
grado di comprendere.
Tuttavia la scrittura di un programma in linguaggio macchina crea non poche difficoltà al
programmatore: ogni istruzione sembra simile ad un’altra, è costituita da una sequenza di
bit 1 e 0.
Le istruzioni sono prive di significato immediato e lunghe da caricare care in memoria.
È facile pertanto per il progettista del software incorrere in errori di scrittura o trascrizione.
La trasformazione delle stringhe di bit in numeri esadecimali facilita senz’altro il compito del
programmatore, ma non elimina tutti i problemi.
Un sistema a microprocessore legge soltanto istruzioni in codice binario; nasce quindi il
problema di tradurre il programma dal codice esadecimale a quello binario.
I caricatori esadecimali sono programmi in grado di effettuare la traduzione dal codice
esadecimale al binario.
Con il linguaggio esadecimale le possibilità di errori nella scrittura diminuiscono notevolme-
-nte ma persiste il problema della mancanza di significato apparente per l’operatore e
l’impossibilità di controllare la logica seguita nella stesura del programma.
Il problema viene superato con l’uso della mnemonica, cioè di una simbologia che esplicita
il significato dell’azione prodotta dall’istruzione.
Il programma sorgente scritto dall’operatore viene definito programma in linguaggio
assembly.
L’assembly rende più esplicito, rispetto all’esadecimale, il significato di ogni singola istruzione
e facilita il compito del programmatore nella ricerca di eventuali errori di programmazione
(debugging).
I programmi assemblatori (o assembler) traducono il programma sorgente in programma
oggetto.
L’assembly è un linguaggio orientato alla macchina e pertanto esige una competenza
hardware specifica del sistema a microprocessore.
Il disassembler è invece il programma che esegue la conversione opposta, ovvero dal
linguaggio macchina all’assembly.
I linguaggi ad alto livello sono orientati al problema e non alla macchina e permettono di
esprimere ogni istruzione in un forma più vicina all’uomo; in questo caso non è necessaria
una conoscenza del hardware.
Il compilatore è il programma che traduce il sorgente, scritto in linguaggio ad alto livello, in
programma scritto in linguaggio macchina.
La programmazione in linguaggio ad alto livello (ad esempio Visual C++, Visual BASIC ecc.)
ha il vantaggio di poter essere utilizzato in qualsiasi sistema.
Il linguaggio assembly è legato strettamente all’hardware e pertanto non è trasferibile su
altri microprocessori.
Tuttavia nonostante i limiti presentati, la programmazione in linguaggio assembly è
preferibile a quella in linguaggio ad alto livello perché consente un miglior controllo della
funzionalità del sistema e dell’efficienza nell’utilizzo delle risorse hardware.
Il lavoro della programmazione si articola in quattro fasi distinte:
•
stesura del programma con l’ausilio del diagramma di flusso (flow chart) o della pseudo-
-codifica (se il programma è lungo e complesso);
•
verifica teorica della logica seguita nella progettazione del software (programma);
•
traduzione del programma in linguaggio macchina mediante un assemblatore che
individui anche eventuali errori di sintassi;
•
fase di debugging del programma possibilmente con l’ausilio di un sistema di sviluppo.
ISA (Instruction Set Architecture)
La ISA, ovvero l’insieme delle istruzioni, descrive le caratteristiche dell’architettura del
microprocessore accessibili da parte del programmatore.
Tali caratteristiche si possono così riassumere:
• i comandi implementati;
• le istruzioni;
• i registri interni e il loro utilizzo;
• i modi di indirizzamento;
• l’organizzazione del banco di memoria del sistema;
• la gestione degli interrupt;
• le porte di I/O.
L’ISA è una specificazione dell’insieme di tutti quei codici binari (op code) che rapprese-
-ntano i comandi implementati nella CPU.
Il set di istruzioni è ortogonale quando è possibile per le istruzioni utilizzare come operandi
qualsiasi registro. È possibile che microprocessori aventi un hardware completamente
differente possono condividere lo stesso set di istruzioni.
Esistono in commercio software di emulazione di ISA che consentono di far girare il
programma in un ambiente differente.
Le istruzioni del programma da eseguire sono dei veri e propri comandi per la CPU che le
decodifica e le esegue.
Le istruzioni possono essere differenti per la loro composizione e quindi anche per la
loro lunghezza; in genere hanno il formato indicato nella sottostante figura (a) e sono
composte dai seguenti campi:
Formato di un’istruzione: a due operandi (a), ad un solo operando (b),
con i campi aggiuntivi label e commento (c).
•
Il codice operativo (op code) rappresenta l’operazione che la CPU deve eseguire.
L’op code occupa un byte (8 bit) e ovviamente deve essere sempre presente in ogni
istruzione.
Esempi di op code possono essere ADD (somma), LD e MOV (trasferisci un dato) OUT
(trasferisci il dato dall’accumulatore a un I/O) ecc.
Un microprocessore a 8 bit potrebbe disporre teoricamente di 256 istruzioni ,
in pratica ne possiede decisamente in numero inferiore perché alcuni bit dell’op code
sono dedicati alla scelta del tipo di indirizzamento del dato.
•
I due campi operandi indicano gli operandi o gli indirizzi per accedere agli operandi
stessi.
In questi campi si può trovare un dato, un indirizzo o il nome dei registri interessati
all’operazione. Un’istruzione del tipo ADD A, 0FF oppure LD (indirizzo), A è costituita da
tre byte che occupano tre locazioni consecutive in memoria.
L’indirizzo della prima locazione, dove è allocato l’op code, viene assunto come indirizzo
di tutta l’istruzione.
In sede di decodifica la CU apprende che l’istruzione è completata da altri due byte.
Altre istruzioni possono contenere solo un campo operando anziché due, vedi figura (b).
Un’istruzione, costituita da due byte consecutivi, necessita di un minor tempo di
esecuzione.
Ad esempio l’istruzione CP dato confronta il dato con il contenuto del registro accumulatore.
In questo caso si ha un solo campo operando, quello del dato; il riferimento all’accumula-
-tore è implicito nell’op code stesso.
Vi sono istruzioni ad un solo byte, costituite dal solo codice operativo, ad esempio HALT e
NOP.
Il codice operativo è l’unico campo che non può mancare.
In un’istruzione possono essere presenti altri due campi, come indicato in figura ( c).
Il campo commento non viene mai tradotto dall’assembler in linguaggio macchina perché è
un aiuto al programmatore per una migliore comprensione e lettura del programma,
ovviamente non è indispensabile.
Il campo di label serve a identificare un segmento di programma che deve essere richia-
-mato da una particolare istruzione.
La label (etichetta), posta all’istruzione a cui si vuole saltare, viene sostituita dall’assembler
con il relativo indirizzo.
Per poter programmare correttamente in assembly è necessario conoscere le regole
sintattiche dell’assemblatore che si sta usando.
Il problema riguarda principalmente la separazione dei vari campi; in alcuni assembler, ad
esempio, una label deve essere separata dall’op code da due punti, l’op code dal campo
operando da uno spazio.
Esempio
Un programma con una label è il seguente:
JP FINE
…
…
FINE; HALT
Se l’indirizzo di memoria dell’istruzione HALT è ad esempio 0AFFH, l’assemblatore
sostituirà la label dell’istruzione JP FINE con i due byte (FFH, 0AH), ponendo prima la parte
bassa e poi quella alta dell’indirizzo:
JP FF0A
……
……
(0AFF); HALT
Le pseudo-istruzioni
Esistono alcune istruzioni, comuni alla maggior parte dei linguaggi assembly, che non
vengono tradotte in istruzioni in linguaggio macchina perché non corrispondono ad azioni
della CPU ma sono semplicemente delle direttive per l’assemblatore.
Lo scopo delle pseudo-istruzioni (o pseudo-operazioni) è di memorizzare nella RAM tabelle
di dati, definire grandezze costanti, assegnare al programma l’indirizzo di partenza in
memoria.
La mnemonica della pseudo-istruzione viene posta nel campo operativo e se richiesto è
accompagnata da un indirizzo o da un dato nel campo indirizzo.
Le pseudo-operazioni più comuni sono indicate nella
tabella a lato.
La pseudo-istruzione DATA consente di memorizzare
tabelle di ricerca, di conversione di codici, di mes-
-saggi, di coefficienti per equazioni, di codifica dei
tasti, di nomi ecc.
L’istruzione DATA è preceduta di solito da una label
che servirà per richiamare il dato memorizzato.
EQUATE invece uguaglia label e nomi a indirizzi e dati, in altri termini a definire il significato
delle label; ad esempio, è possibile utilizzare in una istruzione una label alla quale corrispo-
-nderà un indirizzo definito con EQU.
Per essere facilmente individuabili è preferibile posizionare le EQU all’inizio del programma
con un opportuno commento.
La pseudo-operazione ORG serve ad allocare in memoria il programma principale ovvero
routine di inizializzazione, routine di servizio degli interrupt ecc.
Si posiziona ovviamente all’inizio del programma o sottoprogramma.
Con RESERVE si assegna un nome a una zona della memoria RAM dichiarando l’estensione
riservata.
Si usa normalmente per riservare una parte della memoria a tabelle di dati, allo stack,ecc.
Pseudo istruzioni
Pseudo-istruzione
Mnemonica
Data
Data
EQUATE
EQU
ORIGIN
ORG
RESERVE
RESERVE