Ing. Paolo Domenici SISTEMI A MICROPROCESSORE PREFAZIONE Il corso ha lo scopo di fornire i concetti fondamentali dei sistemi a microprocessore in modo semplice e interattivo. È costituito da una parte teorica e da una serie di esercitazioni. Nella parte teorica vengono descritte sinteticamente le caratteristiche di un semplice elaboratore, l’architettura interna del microprocessore, le principali istruzioni e la struttura di un programma. Le esercitazioni si dividono in due parti: nella prima vengono affrontati i problemi relativi allo scambio di dati fra CPU, memoria e dispositivi di I/O, nella seconda vengono scritti ed eseguiti semplici programmi in linguaggio macchina. Le esercitazioni vengono effettuate mediante un programma di simulazione, realizzato utilizzando il foglio elettronico Excel. N.B. Per un corretto funzionamento dei programmi di simulazione, è necessario impostare il numero di iterazioni massimo pari a 5. Per far ciò, una volta aperto il foglio elettronico Excel, seguire il seguente percorso: STRUMENTI – OPZIONI – CALCOLO – NUMERO MAX. DI ITERAZIONI: 5. (ing. Paolo Domenici) SISTEMI A MICROPROCESSORE INTRODUZIONE I sistemi elettronici tradizionali, detti sistemi a logica cablata, sono costituiti soltanto dalla parte fisica (hardware), cioè dal circuito stampato, dai componenti passivi e attivi ecc. Essi sono in grado di svolgere soltanto la funzione per la quale sono stati progettati. Per modificare tale funzione è necessario modificare o sostituire il dispositivo. I sistemi a logica programmata, oltre alla parte hardware, sono dotati anche di una parte software, costituita da un programma residente nella memoria di lavoro, cioè da una serie di istruzioni, senza la quale non sarebbero in grado di funzionare. I sistemi programmabili sono pertanto molto flessibili, adatti cioè a svolgere numerose funzioni, per modificare le quali è sufficiente cambiare il programma, lasciando inalterata la struttura fisica. ********* STRUTTURA DELL’ELABORATORE ELETTRONICO Un elaboratore elettronico è un sistema programmabile, generalmente composto da tre unità fondamentali: l’Unità Centrale (CPU), l’Unità di Ingresso/Uscita (I/O) e la Memoria, collegati fra loro da tre bus: il bus dati, il bus indirizzi e il bus controlli. La CPU (Central Processing Unit = unità centrale di elaborazione) è l’elemento principale del sistema. Ha lo scopo di dirigere tutte le operazioni e di eseguire i calcoli. E’ costituita dall’ Unità di Controllo (UC), dall’ Unità Logico – Aritmetica (ALU) e da una serie di Registri. L’UC coordina tutti i trasferimenti dei dati fra i blocchi della CPU e genera i segnali di controllo. L’ ALU esegue le operazioni aritmetiche e logiche. L’Unità di I/O permette lo scambio di informazioni fra la macchina e il mondo esterno. La Memoria contiene la sequenza di parole binarie che costituiscono il programma. Ogni dato, che può essere il codice di un’istruzione o un dato numerico, è memorizzato in una cella (o locazione), individuata da un numero, detto indirizzo. Quando la CPU deve leggere o scrivere un dato in una cella di memoria, invia il corrispondente indirizzo attraverso il bus indirizzi. Un particolare circuito interno alla memoria provvederà a selezionare la corrispondente cella, il cui contenuto sarà trasferito su un buffer a tre stati, che costituisce l’interfaccia fra la memoria e il bus dati. I Registri sono memorie temporanee, costituite da un insieme di flip-flop di tipo D, che ha lo scopo di memorizzare i dati. I registri più comuni sono: l’Accumulatore, che serve per contenere i risultati delle operazioni effettuate mediante l’ALU; il Program Counter, che contiene l’indirizzo della prossima istruzione che deve essere eseguita; il Registro degli Indirizzi, che costituisce l’interfaccia fra la CPU e il bus indirizzi, poiché contiene l’indirizzo della cella di memoria o del dispositivo di I/O con cui la CPU deve scambiare informazioni; il Registro dei Dati, che costituisce l’interfaccia fra la CPU e il bus dati, poiché memorizza tutti i dati che devono essere scritti o letti dalla memoria o dai dispositivi di I/O; il Registro delle Istruzioni, in cui viene memorizzato il codice delle istruzioni che devono essere eseguite; il Puntatore di Stack, che contiene indirizzi relativi ad una particolare parte di memoria, chiamata stack, in cui viene memorizzato temporaneamente il contenuto di alcuni registri (ad esempio il contenuto del contatore di programma, quando viene eseguita una subroutine); il Registro di Stato, che contiene informazioni sul risultato di un’operazione. Oltre ai registri citati, ve ne sono altri di uso generale, che variano a seconda del tipo di CPU. Un circuito integrato che implementa una CPU è detto Microprocessore. ********* LETTURA DI DATI DALLA MEMORIA La memoria di un sistema a microprocessore è costituita da un certo numero di celle in cui sono memorizzate le informazioni, da un circuito di selezione e da un buffer a tre stati, necessario per l’interfacciamento con il bus dati. Per leggere un dato dalla memoria sono necessarie le seguenti operazioni: 1. Selezione della cella mediante mediante l’invio del corrispondente indirizzo attraverso il bus indirizzi. 2. Selezione del chip di memoria mediante l’invio, attraverso una particolare linea del bus controlli, di un segnale di abilitazione. Nel caso che stiamo esaminando, tale operazione consiste nel porre il segnale MREQ/IORQ = 1. 3. Invio di un segnale di lettura attraverso il bus controlli. Nel caso in esame si pone R/W = 1. ESERCITAZIONE N° 1 Selezionare alcune celle di memoria e trasferire il relativo contenuto nel registro dei dati. Osservazione: Per semplicità di scrittura, i numeri si scrivono in codice decimale, anziché in codice binario, come avviene nei microprocessori reali. Eseguire la simulazione mediante il file Simulazione CPU1, da aprire con Excel. ********* LETTURA DI DATI DAI DISPOSITIVI DI I/O I dispositivi di I/O permettono alla CPU di effettuare lo scambio di informazioni con il mondo esterno. Per accedere ad un dispositivo di ingresso o di uscita, nel caso in cui non venga utilizzata la mappatura di memoria, è necessario effettuare le seguenti operazioni: 1) inviare l’indirizzo del dispositivo con cui ci si vuole collegare; 2) inviare, mediante un’opportuna linea del BUS CONTROLLI, un segnale di abilitazione dell’unità di I/O (nel caso in esame porre MREQ/IORQ=0); 3) inviare un segnale di lettura o scrittura (R/W). ESERCITAZIONE N° 2 Effettuare lo scambio di dati fra CPU e unità di I/O. Eseguire la simulazione mediante il file Simulazione CPU1, da aprire con Excel. ********* SCRITTURA DI DATI NELLA MEMORIA Per effettuare un’operazione di scrittura di dati nella memoria RAM si eseguono le stesse operazioni relative alla lettura, ponendo però R/W = 0. ESERCITAZIONE N° 3 Effettuare operazioni di scrittura e lettura nella memoria RAM. Eseguire la simulazione mediante il file Simulazione CPU1, da aprire con Excel. ********* PROGRAMMAZIONE DEL MICROPROCESSORE Il microprocessore, per funzionare, ha bisogno di un programma, cioè di una serie di istruzioni codificate mediante parole di 4, 8, 16 o più bit. Le istruzioni si dividono in ISTRUZIONI DI TRASFERIMENTO, ISTRUZIONI ARITMETICHE, ISTRUZIONI LOGICHE, ISTRUZIONI DI CONTROLLO, ISTRUZIONI DI SALTO. Ogni istruzione è formata da un codice operativo e da un operando. I tipi più comuni di indirizzamento sono: INDIRIZZAMENTO INDICIZZATO. IMPLICITO, IMMEDIATO, DIRETTO, INDIRETTO, Il microprocessore è in grado di riconoscere solo programmi scritti in linguaggio macchina, in cui anche il codice operativo è costituito da un numero binario. Poiché non è facile comprendere tale linguaggio, è stato ideato un linguaggio mnemonico, dello Assembly, in cui, al codice operativo di ogni istruzione, è associata una parola inglese abbreviata, di più semplice comprensione. Particolari programmi, detti compilatori assembly, o assemblatori, provvederanno a tradurre il programma assembly, detto programma sorgente, nel corrispondente programma in linguaggio macchina, detto programma oggetto, che il microprocessore è in grado di riconoscere e di eseguire. Le istruzioni di un programma assembly dipendono dal tipo di microprocessore, per cui faremo riferimento ad un semplice microprocessore didattico, costituito dagli elementi essenziali ed avente un set di istruzioni ridotto, che riportiamo nella seguente tabella: LDA# n = carica nell’accumulatore il numero n. È un’istruzione di trasferimento dati, con indirizzamento immediato, in quanto il numero n, che costituisce l’operando, viene caricato, cioè memorizzato, nell’accumulatore. Questa istruzione, tradotta in linguaggio macchina, occupa due celle di memoria: la prima contiene il codice operativo, cioè il numero binario corrispondente alla sigla LDA#, mentre la seconda contiene l’operando, cioè il numero n. STA n = scarica il contenuto dell’accumulatore nella cella di indirizzo n. È un’istruzione di trasferimento dati, con indirizzamento diretto, in quanto il numero n, che costituisce l’operando, è l’indirizzo della cella di memoria in cui viene memorizzato il dato contenuto nell’accumulatore. (Si osservi che, al termine dell’operazione, l’accumulatore non viene azzerato, ma contiene ancora il numero n). Anche questa istruzione, come la precedente, occupa due celle di memoria. ADD# n = somma il numero n al contenuto dell’accumulatore e scrivi il risultato ottenuto nell’accumulatore stesso. È un’istruzione aritmetica con indirizzamento immediato, che occupa due celle di memoria. Al termine di tale istruzione il contenuto dell’accumulatore viene modificato. SUB# n = sottrai il numero n al contenuto dell’accumulatore e scrivi il risultato ottenuto nell’accumulatore stesso. È un’istruzione aritmetica con indirizzamento immediato, che occupa due celle di memoria. Al termine di tale istruzione il contenuto dell’accumulatore viene modificato. IN n = legge il dato presente nella periferica di ingresso di indirizzo n e lo trasferisce nell’accumulatore. È un’istruzione di trasferimento con indirizzamento diretto. Occupa due celle di memoria. OUT n = invia il dato presente nell’accumulatore alla periferica d’uscita di indirizzo n. È un’istruzione di trasferimento con indirizzamento diretto. Occupa due celle di memoria. HLT = ALT. È un’istruzione di controllo, con indirizzamento implicito. Questo significa che è costituita dal solo codice operativo, senza operando. Per questo occupa una sola cella di memoria. La sua funzione è quella di bloccare il microprocessore. Questa istruzione viene scritta al termine del programma. JMP n = salta alla posizione di memoria di indirizzo n. È un’istruzione di salto incondizionato, con indirizzamento diretto. Quando il microprocessore incontra questa istruzione, non esegue quella successiva, ma salta a quella avente indirizzo n, cioè a quella scritta nella cella di memoria numero n. Occupa due celle di memoria. JZ n = salta alla posizione di memoria di indirizzo n solo se il contenuto dell’accumulatore è zero. È un’istruzione di salto condizionato, con indirizzamento diretto. Quando il microprocessore incontra questa istruzione, non esegue quella successiva, ma salta a quella avente indirizzo n, cioè a quella scritta nella cella di memoria numero n, solo se il numero contenuto nell’accumulatore è uguale a zero. Occupa due celle di memoria. Un programma assembly è costituito da una serie di istruzioni come quelle viste sopra, ognuna delle quali è preceduta da una label, o etichetta, che corrisponde all’indirizzo della cella di memoria in cui è scritto il codice operativo dell’istruzione stessa. Ad esempio, se vogliamo caricare nell’accumulatore il numero 25, dovremo scriviere il seguente programma assembly: 0 LDA# 25 2 HLT Nella cella di indirizzo 0 verrà scritto un numero binario corrispondente alla sigla LDA#. Nella cella successiva, avente indirizzo 1, verrà scritto il numero 25, convertito in codice binario. Nella cella di indirizzo 2 verrà invece scritto il numero binario corrispondente all’istruzione HLT. Se vogliamo eseguire la somma di due numeri, dobbiamo caricare il primo nell’accumulatore e sommare ad esso il secondo. Supponiamo, ad esempio, di voler eseguire la somma dei numeri 25 e 48. Il corrispondente programma è il seguente: 0 LDA# 25 2 ADD# 48 4 HLT Supponiamo ora di voler memorizzare il risultato ottenuto nel precedente programma in una cella di indirizzo 100. Il programma completo è il seguente: 0 LDA# 25 2 ADD# 48 4 STA 100 6 HLT Supponiamo invece di voler visualizzare tale risultato su un display. Facendo riferimento al microprocessore didattico su cui faremo le simulazioni, l’indirizzo del display è 1. Dovremo scrivere il seguente programma: 0 LDA# 25 2 ADD# 48 4 OUT 1 6 HLT Se vogliamo inviare alla CPU un numero, ad esempio il numero 25, utilizzando una tastiera, che, nel caso in esame ha indirizzo 0, trasferirlo nella cella di indirizzo 100 e visualizzarlo sul display, dobbiamo scrivere il seguente programma: 0 IN 0 2 STA# 100 4 OUT 1 6 HLT Analizziamo ora un esempio che richiede le istruzioni di salto. Vogliamo scrivere un programma che legga ciclicamente un dato dalla tastiera, finché non venga digitato un codice segreto (ad esempio il numero 45). La prima istruzione deve essere un’istruzione di input, che carica nell’accumulatore il numero digitato. Segue un’istruzione aritmetica, che effettua il confronto fra il numero presente nell’accumulatore e il numero 45. Tale istruzione esegue la differenza fra i due numeri, che viene memorizzata nell’accumulatore. Se i due numeri sono uguali, il numero contenuto nell’accumulatore è uguale a zero. A questo punto è sufficiente un’istruzione di salto condizionato ad un indirizzo contenente l’istruzione HLT. Se il contenuto dell’accumulatore è diverso da zero, tale salto non viene effettuato e il programma esegue l’istruzione successiva, che consiste in un salto incondizionato all’inizio del programma. Il listato corrispondente a tale programma è quello di seguito riportato: 0 IN 0 2 SUB# 45 4 JZ 8 6 JMP 0 8 HLT ESERCITAZIONE N°4 Scrivere ed eseguire semplici programmi, come quelli sopra riportati, mediante la seguente procedura: a) Scrivere il programma in linguaggio assembly. b) Tradurlo in linguaggio macchina, utilizzando la tabella riportata nel programma di simulazione. c) Ricopiare il listato così ottenuto nella memoria ROM del sistema a microprocessore virtuale relativo al suddetto programma. d) Eseguire il programma. Per l’esecuzione, procedere nel modo seguente: • Resettare il sistema, ponendo RESET = 0. • Riattivare il sistema, ponendo RESET = 1. • Incrementare di una unità per volta l’indirizzo, per eseguire, passo-passo, le varie istruzioni. (Per scrivere l’indirizzo delle celle di memoria con le quali ci si deve collegare, utilizzare l’apposita casella riportata in basso). L’esecuzione di alcune istruzioni richiedono operazioni supplementari, che sono indicate nelle righe scritte sotto il titolo, in cui viene riportata una semplice descrizione delle operazioni svolte. Osservazione: Per semplicità di scrittura e di realizzazione, sono stati adottati alcuni accorgimenti, che non corrispondono ai sistemi reali: • I numeri si scrivono in codice decimale, anziché in codice binario. • I dati non possono superare il valore 999, perché i numeri maggiori corrispondono ai codici operativi. Eseguire la simulazione mediante il file Simulazione CPU2, da aprire con Excel.