Virtual CPU - Eniac
Università degli Studi di Roma “Tor Vergata”
Dr.ssa Veronica Marchetti
Overview



Capire perché è utile imparare a programmare a basso
livello;
i concetti base a monte della programmazione utilizzando la
CPU virtuale Eniac;
Conoscere la struttura (lo schema circuitale) della CPU
virtuale Eniac che adotteremo per programmare;

Acquisire il set di istruzioni disponibile;

Comprendere il funzionamento di piccoli programmi esistenti;

Imparare a programmare, a basso livello, applicativi di
piccola entità.
rev 1
2
“Capire perché è utile imparare a
programmare a basso livello”
rev 1
3
Capire l'importanza della
programmazione a basso livello

Contro

Assenza quasi totale della gestione dei tipi di dato nei
compilatori: è infatti il programmatore che si deve far
carico del corretto utilizzo dei tipi;

Portabilità ridotta rispetto ai linguaggi più moderni;

Difficoltà nel comprendere programmi già scritti;

Difficoltà anche nello scrivere programmi.

Non è più utilizzato dalla maggior parte delle aziende che
sviluppano software.
rev 1
4
Capire l'importanza della
programmazione a basso livello

Pro

Si percepisce come effettivamente si riescono a far
svolgere delle attività ad un calcolatore;

Si ha la giusta percezione di cosa può e cosa non può
fare un calcolatore;

Si possono ottimizzare particolari routine di un applicativo,
specialmente se scritto in C o in C++;

Fornisce la possibilità di intuire e ricostruire il codice
sorgente a monte di un eseguibile preesistente (Reverse
Engineering).
rev 1
5
“Conoscere la struttura (lo schema
circuitale) della CPU virtuale Eniac che
adotteremo per programmare”
rev 1
6
Un po' di terminologia



Emulatore: è un software che ricrea l'hardware di un sistema,
solitamente differente da quello di cui si dispone, permettendo
di far eseguire programmi di vario genere come se fossero
eseguiti nell'hardware emulato.
Simulatore: è un software che imita l'hardware di un sistema.
La differenza tra i due concetti risiede nel fatto che mentre il
primo ha come obiettivo primario il funzionamento del software,
per il secondo tale obiettivo è secondario: l'attenzione è infatti
principalmente rivolta alla rappresentazione degli aspetti
architetturali e funzionali dell'hardware emulato.
rev 1
7
Un po' di terminologia

Assembly: (definizione tratta dal sito di Wikipedia) è il
linguaggio di programmazione più vicino al linguaggio
macchina vero e proprio.
Infatti, esiste una corrispondenza pressoché biunivoca
tra gli mnemonici del linguaggio assembly ed i
corrispondenti codici macchina corrispondenti ai bitfields
(campi di bit) che compongono le istruzioni direttamente
eseguibili dal dispositivo elettronico (in genere una CPU)
che si sta programmando.
rev 1
8
Un po' di terminologia

Assembler: (definizione tratta dal sito di Wikipedia) è un
programma compilatore che si occupa di tradurre in
linguaggio macchina (ossia una serie di bit 0 e 1 che
costituiscono l'unico modo per comunicare con dispositivi
elettronici), una serie di comandi scritti in linguaggio
Assembly.
Oltre a questo compito base, un Assembler si occupa spesso
di ausiliare il programmatore, ad esempio consentendo
l'utilizzo nel codice sorgente del programma di nomi
mnemonici al posto di indirizzi esadecimali che costituiscono
l'esatta collocazione di una variabile o di una porzione di
programma nella memoria centrale del computer.
rev 1
9
Conoscere gli strumenti

Durante queste lezioni prenderemo in considerazione un
emulatore di una CPU virtuale progettata e realizzata dal
Dott. Mauro Codella e Dott. Dario Dussoni ;

L’emulatore preso in considerazione è Eniac

Attualmente il software è reperibile alla seguente URL :
http://sourceforge.net/projects/eniac/

Sun Java Development Kit ver. 1.6
rev 1
10
Conoscere gli strumenti



E.N.I.A.C., è l'acronimo di Electronic Numerical
Integrator And Computer, il primo computer
elettronico della storia (1946).
Nel 2006 si è celebrato il 60° anniversario, non solo
di ENIAC ma della storia della intera
programmazione;
Poiché tale emulatore è stato realizzato proprio nel
2006 gli è stato dato questo nome come tributo.
rev 1
11
Conoscere gli strumenti


Lo scopo dell’emulatore è quello di rendere possibile
sia l’esecuzione di programmi, che di rendere
comprensibile tutto ciò che accade all’interno di un
calcolatore.
Esso mette a disposizione un’interfaccia grafica
semplice e funzionale, che permetta di gestire
agevolmente tutte quelle risorse coinvolte
nell’esecuzione di un programma,quali memoria,
porte, registri, flags, ma non solo: la GUI di ENIAC è
stata pensata mirandola, in modo particolare, a
scopo didattico
rev 1
12
Conoscere gli strumenti


Dispone di un editor di testo sensibile alla sintassi
dell’assembly, per gestire tutte le celle di memoria, le
porte, i registri, i flags.
E’ inoltre contemplato un campo per visualizzare
eventuali errori.
rev 1
13
Il perché della scelta

Perché utilizzare un emulatore e non un assembler?

L'emulatore permette di analizzare le componenti salienti della
CPU in modalità real-time: durante l'esecuzione delle istruzioni
sono infatti visibili immediatamente le modifiche ai registri e ai
flag;

Possiamo eseguire il nostro codice su un qualunque calcolatore in
grado di eseguire l'emulatore;

Non vi è la necessità di ricompilare il programma ad ogni minima
modifica al codice;

I vantaggi offerti dall’assembler (velocità ed ottimizzazione del
codice) non sono pertinenti allo scopo di queste lezioni.
rev 1
14
“Acquisire i concetti base a monte della
programmazione assembly”
rev 1
15
Rappresentazione in base 2 di un
numero in base 10

Vogliamo richiamare qui l'algoritmo per la rappresentazione in base 2 di un numero
in base 10;

Algoritmo di conversione:
I. scegliamo il numero in base 10 da convertire;
II. memorizziamo il numero in una variabile che chiameremo x;
III.dividiamolo il valore in x per 2;
IV.riponiamo il resto della divisione in una pila P;
V.se il risultato della divisione è uguale a 0 allora salta al passo VIII, altrimenti
procedi con il passo successivo;
VI.riponiamo il risultato della divisione in x;
VII.ritorniamo al passo III;
VIII.fine: nella pila troviamo il numero convertito in binario, con la cifra più significativa
(MSB) sulla cima.
rev 1
16
Rappresentazione in base 16 di un
numero in base 10

Vogliamo richiamare qui l'algoritmo per la rappresentazione in base 16 di un
numero in base 10;

Algoritmo di conversione:
I. scegliamo il numero in base 10 da convertire;
II. memorizziamo il numero in una variabile che chiameremo x;
III.dividiamolo il valore in x per 16;
IV. riponiamo il resto della divisione in una pila P;
V.se il risultato della divisione è uguale a 0 allora salta al passo VIII, altrimenti
procedi con il passo successivo;
VI.riponiamo il risultato della divisione in x; (*)
VII.ritorniamo al passo III;
VIII.fine: nella pila troviamo il numero convertito in esadecimale, con la cifra più
significativa sulla cima.
rev 1
17
Rappresentazione in base 16 di un
numero in base 10
(*) incontriamo un problema: sapendo che, in
generale, il resto di una divisione per d è pari
ad un r nell'intervallo chiuso [0, d-1], come
ci comportiamo quando dividiamo per 16? Il
resto in questo caso è nell'intervallo [0, 15],
ma nella pila p siamo costretti ad inserire
una sola cifra... cosa fare?
rev 1
18
Rappresentazione in base 16 di un
numero in base 10
(*) ... semplicemente associamo ai valori 10, 11,
12, 13, 14 e 15 dei simboli univoci che li
rappresentano. In particolare si prende A per
rappresentare 10, B per 11, C per 12, D per 13,
E per 14 ed F per 15.
rev 1
19
Tabella riassuntiva delle cifre
esadecimali
D EC
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
BI N
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
rev 1
H EX
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
20
Rappresentazione in base 16 di un
numero in base 10
rev 1
21
Conversioni da base 2, base 16 a
base 10

Da base 2 a base 10:

Da base 16 a base 10:
rev 1
22
Notiamo una certa caratteristica nella
rappresentazione in base 16

Dalla tabella riassuntiva delle cifre esadecimali si vede chiaramente che esiste
una corrispondenza biunivoca tra codici binari a 4 bit e le cifre della
rappresentazione esadecimale;

Questo è il motivo chiave che ha spinto ad adottare la rappresentazione in base
16: permette infatti di rappresentare in forma compatta e facilmente leggibile i
numeri binari di grande dimensione;

Convertire un numero binario in uno esadecimale e viceversa è un'operazione
banale. Infatti:
rev 1
23
Convenzioni




Per indicare un numero in base 10, ad esempio x, si
utilizzerà (x)10 , o più semplicemente x;
Per indicare un numero in base 16, si utilizzerà la
sintassi (x)16, o più semplicemente xh;
Per indicare un numero in base 2, si utilizzerà la
sintassi (x)2 , o più semplicemente xb;
Sia x un carattere: di seguito si intenderà con 'x' il
codice numerico associato alla codifica di x.
rev 1
24
Concludendo: perché tre basi
diverse?

Le ragioni che hanno spinto i programmatori a basso livello ad
adottare tre basi diverse per indicare un numero sono le seguenti:

La base 10 permette di rappresentare i numeri nella forma che
meglio conosciamo: sin dagli albori dell'umanità l'uomo ha
contato utilizzando le dieci dita;

La base 2 permette di rappresentare i numeri nella forma
canonica dei calcolatori: è particolarmente utile quando si vuole
specificare una particolare sequenza di cifre binarie;

Spesso, le cifre binarie che si vogliono rappresentare sono
molto lunghe: l'utilizzo della base 16 permette di rendere
quattro volte più compatta la loro rappresentazione.
rev 1
25
Ecco come ENIAC ci assiste in task di
conversione di base


In ENIAC disponiamo di un Sottomenu Address
Format.
Permette di cambiare le modalità di visualizzazione
dei dati presenti all’interno delle risorse di ENIAC.
rev 1
26
Come è fatto il nostro calcolatore
rev 1
27
Un po' di terminologia
rev 1
28
Struttura della vCPU ENIAC a 24 bit
OpCode
rev 1
29
Visione d’insieme

MBR, MAR, PBR, PAR, sono registri che rappresentano i punti di
contatto tra la CPU e le risorse esterne.




PBR, PAR : memorizzano il dato in transito da o verso le porte (PBR) e contengono il
numero di porta alla quale ci si riferisce (PAR);
Control Unit : decodifica l’istruzione ed esegue l’operazione associata ad
essa.
ALU (Arithmetic and Logic Unit) : permette di effettuare operazioni logiche
e matematiche.


MBR, MAR : memorizzano il dato in transito da o verso la memoria (MBR) e
contengono l’indirizzo della cella in questione (MAR);
Può effettuare 10 operazioni differenti
Le componenti comunicano mediante connessioni dirette e NON
mediante bus.
rev 1
30
Visione d’insieme

AX, l’accumulatore;

BX, CX, DX, registri general purpose;

PSW (Processor Status Word) : il registro dei flags;

PC (il Program Counter) : contiene l’indirizzo della cella contenente
l’istruzione successiva da eseguire (non utilizzabile direttamente dal
programmatore ).

IR ( il Registro delle Istruzioni) : contiene l’istruzione appena prelevata
dalla memoria (non utilizzabile direttamente dal programmatore).
Ognuno di questi registri ha per semplicità la dimensione di una cella di
memoria (24 bit) .
rev 1
31
Flags



I flag, cioè i bit del registro PSW, sono essenziali per prendere
decisioni in merito all’esito delle istruzioni eseguite
precedentemente, per poter cambiare il flusso del programma.
Il valore dei flag dopo una computazione rappresentano una
parte dello stato finale in cui è arrivata la ALU.
I flag si distinguono in semplici e complessi. I flag semplici sono
così chiamati in quanto il meccanismo che ne calcola il valore
prescinde dal tipo di operazione effettuata. I flag complessi,
invece, vengono calcolati con meccanismi che oltre al risultato si
basano anche sull’operazione effettuata.
I bit b22b21 codificano la categoria
Memoria



Le celle di memoria hanno una dimensione pari a quella del formato di
istruzioni adottato (24 bit).
Le celle sono associate univocamente a dei valori numerici contigui,
crescenti a partire da zero, chiamati indirizzi.
La memoria contiene 212 celle, poiché abbiamo adottato la codifica del
complemento a 2 per rappresentare gli interi e nel formato delle
istruzioni abbiamo assegnato 13 bit all’argomento per contenere
l’indirizzo.
Formato dell’istruzione

Fissato a 24 bit.

8 bit dedicati al codice operativo (b23…b16).

3 bit per il tipo dell’argomento (b15…b13).

13 per l’argomento (b12…b0).
Tipologia di argomenti


L’argomento di una istruzione può essere di vari tipi: ad esempio:

Indirizzo della cella di memoria contenente l’operando necessario
all’istruzione;

L’operando, direttamente fruibile dall’istruzione.

Il codice del registro contenente l’operando.

Altro ancora…

Il tipo viene determinato dal valore dei bit b15…b13
Alcune istruzioni gestiscono argomenti di diversi tipi, mentre altre
ancora usano sempre la stesso. Questa differenza divide le istruzioni
in due classi:

Istruzioni che usano argomenti di diverso tipo.

Istruzioni che usano un argomento sempre dello stesso tipo.
Classi di istruzioni



La differenza tra le due categorie
viene formalizzata per mezzo
della specifica di due classi di
istruzioni: la classe  e la classe
.
Le due classi si distinguono per
mezzo dell’MSB dell’istruzione: il
bit b23.
Nella classe  i bit b15…b13 sono
sempre assegnati a zero in
quanto inutilizzati. La tipologia
dell’argomento è insita nel codice
operativo.
I Flag



Bit del registro PSW.
Utilizzati per prendere decisioni in base all’esito di
istruzioni precedenti, così da poter cambiare il flusso
del programma
Sono la rappresentazione di una parte dello stato
finale a cui è arrivata l’ALU nell’effettuazione
dell’ultima operazione
rev 1
37
I Flag


Semplici - il meccanismo che ne determina il valore
dipende solo dallo stato finale dell’ALU, NON da
quale operazione è stata effettuata
Complessi - vengono configurati anche in base a
criteri legati alle operazioni


in particolare le operazioni coinvolte sono quelle di
addizione e sottrazione.
(Vedremo successivamente la loro interpretazione a livello
aritmetico)
rev 1
38
I Flag
Flag semplici

SI = 1 se l’ultima operazione ha generato un risultato in cui il
bit più significativo = 1,
0 altrimenti;

ZE =1 se il risultato dell’ultima operazione è zero,
0 altrimenti;

EV =1 se la somma dei bit a 1 del risultato dell’ultima
operazione è pari (even) – Attenzione! non implica che il
risultato sia pari!,
0 altrimenti.
rev 1
39
La ALU e le sue funzionalità


Operazioni possibili:
somma, sottrazione, divisione,
moltiplicazione, negazione, modulo, and, or,
or esclusivo (xor) e not.
Ha quattro ingressi
 Due
di dati
 Uno di controllo
 Uno per il clock
rev 1
40
Ingressi
OpCode
rev 1
41
La ALU e le sue funzionalità




scelta progettuale

il secondo operando e il segnale di controllo sono specificati
nell’istruzione

il primo operando è sempre AX.

L’uscita va sempre in AX ma, nel caso specifico della moltiplicazione,
è distribuita in BX e AX.

Insieme al risultato escono anche i valori che configurano i flag nel
registro PSW.
il segnale di controllo specifica l’operazione da eseguire
I due operandi in ingresso hanno tanti bit quanti una
parola di memoria,
Il risultato può essere della dimensione o di una parola o
di due parole di memoria
rev 1
42
Comprendere la struttura della ALU
di vCPU

Descrizione incrementale (comprensione graduale)
Gli elementi :

Adder,

implementato per mezzo di un Full Adder, in grado di
effettuare delle addizioni

Gli operandi dell’operazione vengono inizialmente
memorizzati nei registri interni alla ALU, B0 e B1
(memorizzano rispettivamente il valore di AX e l’operando
specificato nell’istruzione)

La presenza di un circuito di complementazione a 2,
indicato nella figura come Complementor, permette
rev 1
inoltre di eseguire le sottrazioni.
43
Comprendere la struttura della ALU
di vCPU

Il modulo Governor :

decodifica l’opcode in input

attiva la circuiteria per effettuare l’operazione richiesta.
Infatti quando l’opcode identifica una sottrazione, il
Governor attiva il Complementor che trasforma il secondo
operando nel suo complemento a 2 e rende così possibile
effettuare la sottrazione dal primo operando mediante
l’Adder.
(3) - (5)
(3) + (compl a 2 di 5)
ovvero
(0011)2 + (1011)2
rev 1
44
Comprendere la struttura della ALU
di vCPU



Risultato viene memorizzato nel registro R0 da dove vengono
prelevati i valori necessari per il calcolo dei flag semplici
Flag semplici dell’ Adder

SI coincide con il bit più significativo in R0 (segno)

ZE con l’AND di tutti i bit in R0 negati

EV con lo XOR negato di tutti i bit in R0.
Flag complessi dell’Adder

CA = 1 se il bit di riporto dell’Adder vale 1 nell’ultima operazione,
0 altrimenti.

OV = 1 se l’ultima operazione ha generato un risultato il cui bit più
significativo differisce da entrambi i bit più significativi degli operandi,
0 altrimenti;
rev 1

Il registro R0 e’ inoltre connesso ad AX.
45
Una semplice ALU in grado di effettuare somme e
sottrazioni
rev 1
46
ALU somme sottrazioni e
moltiplicazioni
Successivo livello di complessità: aggiunta di un
modulo in grado di effettuare le operazioni di
moltiplicazione: il Multiplier



introduzione di due de-multiplexer, guidati dal
Governor, in grado di indirizzare gli operandi verso il
modulo d’interesse (Adder o Multiplier).
La natura dell’operazione di moltiplicazione
comporta l’introduzione di un secondo registro per la
memorizzazione del risultato: il registro R1.
il Multiplier memorizza la parte meno significativa del
risultato in R0 e la piu’ significativa
in R1
rev 1
47
Una semplice ALU in grado di effettuare somme e
sottrazioni e moltiplicazioni
rev 1
48
ALU somme sottrazioni e
moltiplicazioni

Conseguentemente all’introduzione del nuovo
registro, la logica per il calcolo dei flag semplici
cambia.

Per ZE ed EV vengono considerati anche i bit in R1

Per SI viene utilizzato un de-multiplexer, pilotato dal
Governor, in grado di selezionare il bit più significativo che
definirà valore del flag.
In particolare se l’operazione da effettuare è una
moltiplicazione, verrà utilizzato il bit più significativo in R1,
altrimenti quello in R0.
rev 1
49
Una semplice ALU in grado di effettuare somme e
sottrazioni e moltiplicazioni
rev 1
50
ALU somme sottrazioni e
moltiplicazioni

Come l’Adder anche il Multiplier genera dei flag
complessi

OV: viene assegnato a 0 quando i bit in R1 e il bit più
significativo in R0 sono tutti uguali tra di loro,
1 altrimenti.


CA: viene assegnato secondo lo stesso criterio usato per
OV.
Per poter avere solo un bit in uscita sia per il flag OV
che per CA, sono state introdotte due porte OR in
grado di riunire i segnalirevuscenti
dai moduli Adder e 51
1
Multiplier in uno solo.
ALU somme sottrazioni e
moltiplicazioni

Tenendo presente che :

le porte OR hanno output 1 nel caso in cui almeno uno
degli ingressi valga 1

grazie ai de-multiplexer collegati con gli operandi i moduli
Adder e Multiplier non possono essere attivi
contemporaneamente
i flag OV e CA in uscita dalla ALU hanno sempre il
valore generato dal modulo attivato.

Analogamente ai flag complessi, anche il registro R0
riceve in ingresso l’OR di
tutte le uscite dei moduli. 52
rev 1
ALU somme sottrazioni e
moltiplicazioni


Come visto prima, grazie ai de-multiplexer, può
essere attivo solo un modulo alla volta e il segnale in
uscita dal modulo attivato, in OR con tutte le uscite a
0 degli altri moduli, coincide proprio con il risultato
dell’operazione richiesta.
Conseguenza di ciò è che non si ha la necessità di
avere dei segnali di abilitazione per ogni modulo.
rev 1
53
Una semplice ALU in grado di effettuare somme e
sottrazioni e moltiplicazioni
rev 1
54
La ALU di vCPU

Completiamo ora la descrizione della struttura della
ALU di vCPU, con la presentazione degli altri moduli
necessari per implementare il resto delle operazioni

Divisione

Operazioni booleane
rev 1
55
La ALU di vCPU
rev 1
56
La ALU di vCPU
Elenco completo dei moduli presenti :
 Adder
effettua la somma di due interi relativi.
R0 = Operando1 + Operando2
 Complementor
restituisce l’opposto di un intero
relativo.
R0 = −Operando1
rev 1
57
La ALU di vCPU

Multiplier effettua il prodotto di due interi relativi.
R1,R0 = Operando1 Operando2

Divider effettua la divisione tra due interi relativi.
R0 = Operando1/Operando2

Moduler effettua il modulo della divisione tra due
interi relativi.
R0 = Operando1 mod Operando2

ANDer effettua l’AND logico bit a bit tra due interi
relativi.
R0 = Operando1 rev
AND
Operando2
1
58
La ALU di vCPU

ORer effettua l’OR logico bit a bit tra due interi
relativi.
R0 = Operando1 OR Operando2

XORer effettua l’OR esclusivo bit a bit tra due interi
relativi.
R0 = Operando1 XOR Operando2

NOTer effettua il NOT logico bit a bit di un intero
relativo.
R0 = ~ Operando1
rev 1
59
La ALU di vCPU
rev 1
60
La ALU di vCPU


La struttura del Multiplier e del Divider, e dei relativi
componenti interni, non verrà esaminata in maggior
dettaglio.
Per ulteriori informazioni relative a tale struttura si
rimanda alla tesi del Dott. Mauro Codella.
rev 1
61
Scarica

Assembly i80x86 - Dipartimento di Matematica