edutecnica

Linguaggio macchina

        

La quasi totalità dei microprocessori esistenti attualmente sul mercato, sono stati realizzati per essere il nucleo di un sistema di calcolo che implementa una macchina di Von Neumann.

I microprocessori sono sistemi che operano su programmi sequenziali, nei quali ogni istruzione è caratterizzata da un indirizzo di memoria, mentre il flusso delle istruzioni è guidato da un puntatore (contatore di istruzioni) che percorre lo spazio di questi indirizzi di memoria secondo delle regole imposte dal programma stesso.

Questa architettura è denominata come sistema a singola istruzione e a singolo flusso di dati SISD (Single Instruction stream- Single Data stream) ; il sistema elabora le istruzioni una alla volta nell'ordine in cui sono scritte, a meno che l'istruzione stessa non imponga di modificare la sequenza di esecuzione.
Ogni singola istruzione viene eseguita in due fasi:

Fetch : lettura dell'istruzione dalla memoria.
Execute : interpretazione ed esecuzione effettiva dell'istruzione.

In quest'ordine di cose, i parametri che differenziano tra loro i microprocessori sono:

1 Set di istruzioni
2 Modalità di indirizzamento degli operandi.
3 Numero di indirizzi.
4 Ortogonalità.
5 Organizzazione dello spazio degli indirizzi.
6 Parallelismo del bus dati
7 Bus degli indirizzi
8 Ordine di memorizzazione delle informazioni.
9 Frequenza di lavoro.
10 Gestione dell' input/output.
11 Metodi di esecuzione delle istruzioni.

1 Set di istruzioni

Ogni microprocessore possiede un set di istruzioni logiche fondamentali (AND OR NOT) ed almeno delle istruzioni aritmetiche di somma (ADD) e di sottrazione (SUB).
Le altre, meno fondamentali possono essere o non essere presenti, dato che la moltiplicazione (MUL) può essere considerata una somma ripetuta e la divisione (DIV) una sottrazione ripetuta.
Maggiore è il set di istruzioni minore è l'insieme di istruzioni che devono essere scritte manualmente dal programmatore. Bisogna tener conto che in linea generale:

Quello che viene realizzato via hardware è più veloce della stessa cosa realizzata via software a parità di condizioni.

2 Modalità di indirizzamento degli operandi

Ogni istruzione è costituita fondamentalmente da due elementi : il codice operativo e l'operando. In informatica si possono usare diversi modi per assegnare il valore 3 ad una variabile (indirizzamento) ad es.

A=3 o B=3 indirizzamento immediato cioè l'istruzione stessa contiene il dato
A=B indirizzamento diretto, si specifica che il valore si trova all'indirizzo di memoria B
A[i]=3 indirizzamento indicizzato (vettore) etc..

Bisogna sempre conoscere i modi di indirizzamento di un μP per sapere quali tipi di dato si possono implementare direttamente e quali invece si devono simulare.
Ad esempio se un μP non permette il metodo indicizzato non è possibile realizzare algoritmi in cui siano presenti dei vettori.

3 Numero di indirizzi

Noi, usiamo descrivere l'architettura di un elaboratore in modo semplice, attraverso il seguente disegno, dove si riconosce la presenza del microprocessore (CPU=Central Processing Unit). Tutto quello che non è il microprocessore è considerato una periferica collegata alla CPU da delle linee chiamate BUS.

Nella CPU si evidenzia la ALU (arithmetic Logic Unit) che serve ad eseguire operazioni aritmetiche, prevalentemente somme. Per eseguire una operazione aritmetica ci vogliono degli operandi sui quali attuare l'operazione.
La sigla REG che si vede indica i registri interni al processore che sono delle locazioni di memoria dove vengono inseriti gli operandi sui quali eseguire le operazioni.

In genere il numero di operandi per eseguire una operazione è al massimo tre, se consideriamo una tipica operazione di somma C=A+B; partendo da questo assunto possiamo classificare i mocroprocessori in classi a:

3 indirizzi : consentono al programmatore di decidere tutti e tre gli indirizzi, cioè si può scrivere

ADD C, A, B

cioè C=A+B

2 indirizzi : consentono al programmatore di decidere due indirizzi mentre il terzo viene stabilito dal microprocessore, cioè si può scrivere

ADD B, A

che esplicitato significa B=B+A. In questo caso si possono specificare i due addendi mentre la variabile che deve contenere il risultato viene imposta dal μP ; in questo caso B significa sia l'addendo prima dell'operazione che la somma dopo l'operazione.

1 indirizzo : consente al programmatore di scegliere un solo operando mentre gli altri due vengono imposti dal microprocessore, ad es.

ADD B

che significa A=A+B; solo la variabile B viene scelta dal programmatore, mentre l'altro operando, in questo caso il registro accumulatore A, così come il risultato, sono impliciti nel codice operativo.

0 indirizzi : sono processori che permettono di scrivere solo il codice operativo mentre gli operandi vengono imposti; è il caso delle stack machine, architetture nelle quali la memoria viene vista come una pila (stack) e si può accedere solo ai dati che stanno in cima alla catasta. Ad es.

ADD

il  μP prende i primi due dati in cima allo stack, ne calcola la somma e rimette il risultato in cima allo stack.

4 Ortogonalità

Un microprocessore si dice ortogonale quando tutti i registri sono in grado di fornire gli stessi servizi utilizzabili in qualsiasi istruzione; in caso contrario il microprocessore si dice non ortogonale.

La quasi totalità dei microprocessori esistenti in commercio non sono ortogonali; per cui occorre conoscere preventivamente quali sono i registri che permettono di eseguire determinate istruzioni e quali no.

5 Organizzazione dello spazio degli indirizzi

E' necessario conoscere l'organizzazione della memoria dal punto di vista logico che possono essere di due tipi

lineare
segmentata.

Nell'organizzazione lineare la memoria è unidimensionale, cioè lo spazio degli indirizzi è organizzato come un'unica sequenza di locazioni, ciascuna dotata di un indirizzo.
Per indirizzare le locazioni di memoria è sufficiente un solo registro (Program Counter) e quindi quando si scrivono le istruzioni dobbiamo indicare un solo argomento per individuare una locazione.
Tradizionalmente i microprocessori della famiglia Motorola utilizzavano (almeno inizialmente) questo tipo di organizzazione.

Nell'organizzazione segmentata il programmatore definisce i segmenti e al microprocessore vanno forniti due parametri per referenziare la locazione di memoria: il segmento e la posizione relativa al segmento (offset).
Il processore deve essere dotato di un registro per il segmento e un registo per il displacement (spiazzamento : distanza dall'indirizzo base del segmento).
I microprocessori della famiglio Intel/AMD adottano questo tipo di organizzazione.

6 Parallelismo del bus dati

Con il termine parallelismo si indica la dimensione in bit degli operandi che i microprocessori possono elaborare nelle loro operazioni. In un microprocessore ad 8 bit gli operandi hanno la dimensione di un byte (8 bit) In un microprocessore a 64 bit si possono gestire operandi che hanno la dimensione di 8 byte.

7 Bus degli indirizzi

In in generale qualsiasi elaboratore è dotato di tre tipi di bus:

bus dei dati
degli indirizzi
bus di controllo

anche se esistono elaboratori che usano le stesse linee di trasmissione sia per i dati che per gli indirizzi. La dimensione del bus degli indirizzi è molto importante perchè definisce la quantità di memoria fisica che il microprocessore può gestire.
Un μP a 16 bit può indirizzare 216 byte di memoria un processore con n bit indirizza 2n byte di memoria.

8 Ordine di memorizzazione delle informazioni

Nelle operazioni computazionali si può avere a che fare con diversi tipi di dati aventi dimensioni diverse (interi, reali a virgola fissa, reali a virgola mobile etc..) che devono essere rappresentati in memoria all'interno di locazioni la cui dimensione è un multiplo di un byte.
Noi dobbiamo tener presente che dal punto di vista fisico, la memoria è una sequenza di locazioni da un byte; quindi se un dato occupa 16bit (2 byte) nelle due aree adiacenti assegnate vengono proma memorizzati gli 8 bit più significativi e poi gli 8 bit meno significativi o viceversa.
I processori Intel usano questa convenzione, i processori Motorola ad es. usano la convenzione inversa.

9 Frequenza di lavoro

Quando andiamo ad acquistare un elaboratore elettronico o anche un dispositivo mobile, uno dei primi parametri che viene fornito dal commerciante è la frequenza di lavoro (del clock) la cui velocità viene espressa in GHz (109 Hz).
Questo valore esprime il numero di cicli macchina eseguiti dal microprocessore in un secondo. Per esegure una operazione, vengono impiegati alcuni cicli macchina: la durata (periodo) di un ciclo macchina è l'inverso della frequenza.
La frequenza di clock non è il parametro decisivo per stabilire se un sistema di calcolo è più veloce di un altro perchè ci sono altre caratteristiche del sistema che possono influenzarne l'efficienza come la RAM disponibile o la velocità di rotazione del disco con il suo tempo medio di accesso.

10 Gestione dell' input/output

Ogni elaboratore si interfaccia col mondo esterno tramite le periferiche di input e output ed ogni interfaccia può essere vista dal punto di vista software come un gruppo di tre indirizzi:

uno per la parte relativa ai registri di controllo
uno relativo ai registri di comando
uno relativo al porto (port) dell'interfaccia.

Nei microprocessori Intel è sempre stata adottata una filosofia di I/O isolato con un set di istruzioni specifico per l'input-output.
Nei dispositivi Motorola si è sempre adottato un sistema I/O mappato, dove non c'è un set di istruzioni specifico dedicato ma si usano le stesse istruzioni adoperate per la lettura/scrittura in memoria. Quest'ultima politica è considerata, ovviamente, più versatile.

11 Metodi di esecuzione delle istruzioni

Tutti i microprocessori implementano la logica di Von Neumann ma ognuno può adottare accorgimenti specifici per migliorare le prestazioni come le seguenti:

Prefetch. In questo caso il microprocessore viene interpretato come un sistema costituito da due sezioni: la sezione esecutiva e la sezione di decodifica, controllo e temporizzazione. Dato che la sezione esecutiva non è interessata da operazioni di fetching, si organizza il lavoro del μP in modo da eseguire la fase di fetching dell'istruzione successiva mentre si è in fase di esecuzione dell'istruzione in corso. I processori Intel adottano questa filosofia.

Pipeline. In questo caso la fase esecutiva viene suddivisa in sottofasi, come in una catena di montaggio (pipeline) : si hanno simultaneamente diverse fasi di esecuzione di diverse istruzioni, eliminando in questo modo i tempi delle fasi intermedie.

Memoria cache. Per velocizzare le operazioni, tutti i sistemi sono dotati di una memoria tampone (cache) dove vengono immagazzinati dati ed istruzioni eseguiti più frequentemente e più recentemente. In questo modo il sistema è in grado di anticipare i dati prima che il microprocessore li debba chiedere.


Microprocessore 8088/86

        

L'importanza di questo microprocessore della Intel è dovuta all'introduzione e alla successiva grande diffusione dei personal computer basati su sistema operativo MS-DOS che si è avuta negli anni '80, in Italia ben rappresentati dall' "iconico" elaboratore Olivetti M24 con parallelismo dati di 16 bit e con ben 20 bit per il bus degli indirizzi.

Si tratta di un processore non ortogonale dotato di 14 registri raggruppabili per tipologia.

Registri accumulatori
I registri accumulatori (general purpose=di utilizzo generico) sono 4 registri a 16 bit denominati AX, BX, CX, DX.

Con le sigle AX, BX, CX, DX si referenziano tutti i 16 bit di ciascun registro.
Indicando AH, BH, CH, DH vengono indirizzati gli 8 bit più significativi dei registri suddetti.
Indicando AL, BL, CL, DL vengono indirizzati gli 8 bit meno significativi dei registri suddetti.

Il registro AX, oltre che come accumulatore, viene coinvolto automaticamente in altre operazioni, come la moltiplicazione , la divisione e le operazioni di I/O.

Il registro BX viene usato come indice di un vettore o come base di una tabella.

Il registro CX viene usato anche come contatore a 16 bit in particolari istruzioni come i LOOP.

Il registro DX viene anche automaticamente usato nelle operazioni di moltiplicazione per contenere la parte più significativa di un prodotto o nelle divisioni per memorizzare il resto. Nei sistemi MS-DOS è coinvolto nelle operazioni di I/O contenendo l'indirizzo del punto di ingresso o di uscita di un dato per una periferica.

Registri Puntatori e Indice
Esistono 4 registri a 16 bit, chiamati registri indice usati per organizzare vettori e strutture record e per gestire le procedure dello stack. In questi registri si possono referenziare solo tutti e 16 i bit disponibili.

Il registro SP indica le prime locazioni disponibili nello stack.

Il registro BP permette di organizzare lo stack come se fosse un vettore per la gestione dei parametri quando si usano le procedure (PROC).

I registri SI e DI sono usati per implementare vettori; vengono poi automaticamente coinvolti nelle operazioni sulle stringhe: SI indica la stringa sorgente, DI la stringa di destinazione.

Registri di segmento e puntatore di istruzione
Come abbiamo detto il microprocessore Intel 8086 vede la memoria in modo segmentato, esso può referenziare una locazione di memoria tramite due valori: il segmento e la posizione relativa al segmento (offset displacement).

L'indirizzo del segmento è contenuto in uno dei registri di segmento relativo all'area che si sta referenziando, più di preciso:

Il registro CS (Code Segment) che indica la base del segmento di memoria in cui è stato allocato il codice del programma .

Il registro DS (Data Segment) indica la base del segmento in cui sono stati allocati i dati.

Il registro SS (Stack Segment) che indica la base del segmento definito come area di stack, utile per implemetare procedure con passaggio di parametri.

Al contenuto del registro di segmento bisogna aggiungere:

l'offset che viene fornito dal registro IP (Istruction Pointer), se si deve referenziare un'istruzione ( come nei salti condizionali) oppure dalla variabile che inseriamo nell'istruzione, se viene referenziato un dato.

il registro SP (Stack Pointer) se usiamo istruzioni che si riferiscono allo stack.

Il registro ES (Extra Segment) è un segmento extra per i dati, quindi possiamo accedere a due segmenti per dati.
Nella pratrica ES viene usato nelle istruzioni che anno riferimento alle stringhe e spesso referenzia la stessa area dati definita in DS.

I microprocessori della classe 8088/8086 eseguono le istruzioni in modo sequenziale una alla volta nell'ordine scritto dalla prima all'ultima a meno che l'istruzione stessa non imponga l'esecuzione di un istruzione che si trova in una posizione diversa da quella dell'istruzione successiva (come avviene nel caso dei salti condizionali).

La coppia di registri che permettono la sequenzializzazione è data da CS:IP.

La memoria fisica di un sistema di calcolo può essere pensata come un array monodimensionale, per cui il processore deve trasformare un indirizzo bidimensionale in uno lineare, cioè deve calcolare l'indirizzo effettivo EA (effective address). Il calcolo viene fatto attraverso la seguente formula:

EA=Segmento×16+Offset

questa formula è adottata nel processore 8086 che è dotato di un bus degli indirizzi di 20bit cioè 220=1.048.576 byte= 1 MB.
Il segmento lungo 16bit, moltiplicato per 16 viene trasformato in 20 bit aggiungendo come parte meno significativa 4 bit di valore 0 e sommando quindi il relativo offset, anch'esso di 16 bit.

Utilizzando l'aritmetica in esadecimale questa operazione viene eseguita facilmente:

Segmento=FFF0
Offset=EEE0

applicando la formula si ha

EA=FFF00+EEE0=10EDE0


Registro dei flag

      

Il registro dei flag indicato anche come registro di stato è un registro a 16 bit contenente 9 bit (flag), che vengono usati per indicare, in modo indipentente, differenti condizioni durante l'esecuzione di un programma.

i bit 0, 2, 4, 6, 7, 11 contengono flag di stato che denotano risultati di operazioni di programma; i bit 8, 9, 10 contengono flag di controllo; gli altri non vengono utilizzati.

I flag possono essere analizzati dopo aver fatto eseguire opportune istruzioni. il loro stato (set = 1 o reset = 0) condiziona le istruzioni di salto condizionato.

Flag di stato

Flag di Carry (CF)
Questo flag viene impostato a 1 (settato) se dall'esecuzione di un'istruzione di addizione, per esempio, risulta un riporto (carry), o se in una sottrazione risulta un prestito (borrow). in caso contrario il flag è resettato. questo è significativo se le due operazioni di addizione e sottrazione sono applicati a dati che rappresentano numeri naturali.

Flag di Parità (PF)
Questo flag è impostato a 1 se il peso (somma di bit di valore 1) di un dato è pari, resettato quando il peso è dispari. questo flag era utilizzato nei processori precedenti alla classe x86, nei quali l'input e l'output veniva fatto direttamente dal microprocessore per controllare gli eventuali errori di trasmissione e ricezione. Nella comunicazione seriale asincrona il codice a controllo di peso è usato come codice di rilevazione degli errori: questo codice è noto come codice di controllo parità.

Flag di Carry ausiliario (AF)
Opera in modo analogo al flag di carry, ma viene usato per indicare un riporto dal bit 3 al bit 4 in una somma a 8 bit o un prestito dal bit 4 al bit 3 in una sottrazione a 8 bit.

praticamente, il flag viene settato quando in una somma ce un rapporto da un nibble (4 bit o semi byte) a quello immediatamente piu significativo, oppure quando, in una sottrazione, si ha un prestito da un semibyte a quello immediatamente meno significativo.

Flag di Zero (ZF)
Il flag di 0 viene settato quando il risultato di un operazione ha valore 0. questo puo accadere, per esempio, dopo l'esecuzione di un istruzione di sottrazione o di decremento oppure dopo l'esecuzione di un confronto di due numeri dello stesso valore. Per risultati diversi da 0 il flag viene resettato.

Flag di Segno(SF)
Il flag viene usato per controllare se un numero è positivo o negativo, oppure per verificare se un istruzione ha prodotto un risultato positivo o negativo, in termini di complemento a 2 aritmetico. Il bit più significativo di un numero in complemento a 2 è usato per indicare un valore positivo (resettato) o negativo (settato): questo è il bit che viene copiato nel bit 7 del registro dei flag. In alcuni microprocessori viene indicato come flag N (flag di negativo).

Flag di Overflow (OF)
Si tratta di un flag molto utile nelle istruzioni di addizione e sottrazione con numeri interi e indica un overflow, cioè l'operazione tra due valori concordi ha prodotto come risultato un valore discorde (e viceversa). Ha la stessa funzione del flag di carry nelle operazioni tra numeri naturali.

Flag di controllo
I flag di questa categoria servono a gestire alcune modalità operative del microprocessore e possono essere impostati da programma.

Flag di Trap(TF)
Questo flag viene settato quando si vuole eseguire un programma passo passo (step by step), cioè si vuole imporre al microprocessore di passare il controllo dell'utente dopo l'esecuzione di ogni istruzione.

Flag di Interrupt (IF)
Viene resettato per disabilitare le interruzioni (eventi asincroni) oppure viene settato per abilitarli.
Il flag IF è controllato dalle istruzioni STI (Set Interrupt) e CLI (Clear Interrupt).

Flag di Direzione(DF)
Le istruzioni di stringa sono le istruzione che terminano per S, come MOVS, SCAS, CMPS, STOS e così via: queste istruzioni servono, per esempio, per copiare un certo numero di locazioni da una zona ad un'altra della memoria oppure per confrontare due zone di memoria.
Il flag di direzione viene usato per indicare la direzone secondo la quale queste istruzioni agiscono, in accordo con gli indirizzi di memoria contenuti nei registri SI e DI.
Il flag è resettato per stringhe che si stanno elaborando nella direzione della memoria per indirizzi crescenti e settato per stringhe in elaborazione per indirizzi decrescenti di memoria.