Beta [ Pagina Principale || Sommario || Redazione || Informazioni || Beta Browser ]
coordinamento di Fernando Carello
La CPU e il resto del mondo...
di Francesco Sileno
Nota: in questo articolo ci sono dei riferimenti ipertestuali a termini tecnici definiti
nei precedenti Numeri di Beta. Nel collegare questi argomenti, si è assunto che la
directory del Numero 2 sia "../0295", del Numero 3 sia "../0395" e così via per gli altri Numeri.
Per esempio una struttura tipica potrebbe essere c:\beta\0295, c:\beta\0395, ecc., prendendo come nome di directory il numero contenuto nel nomefile di Beta,
oppure nel file di revisione.
I riferimenti sono attivi solo per installazione in locale.
In vista di una serie di articoli dedicati all'assembly, vi riassumo qui di
seguito, in maniera rapida e indolore, il funzionamento della CPU, la sua
struttura e il modo in cui si interfaccia con le periferiche. Lascio il
compito di spiegare il funzionamento dei singoli segnali di strobe e
sincronismo al collega Fernando, che ringrazio comunque per l'assistenza
prestatami.
L'architettura di cui mi occuperò sarà quella adottata dai
cloni IBM compatibili, probabilmente la più diffusa, sicuramente
l'unica su cui mi possa permettere di dissertare.
CPU
La CPU, il cuore del computer. Il suo unico scopo è eseguire
ininterrottamente istruzioni, sempre. Persino quando il PC si inchioda, la
CPU continua a eseguire istruzioni, anche se sono istruzioni senza più
alcun senso.
Al suo interno vi sono un ALU (Aritmetic Logic Unit), programmata in logica cablata, che si occupa
di svolgere i calcoli matematici (non parlo del coprocessore, la ALU lavora
solo su interi), una CU (Control Unit), che 'capisce' le istruzioni che arrivano al
processore e le 'esegue', una serie di registri e buffer ad uso interno,
dei registri ad uso di tutti, e nelle versioni più recenti alcuni integrati
di controllo, cache e coprocessore.
I Registri
Il registro è una componente della CPU in grado di memorizzare a tempo intederminato
un valore, di dimensione pari alla parola che il processore stesso è in grado di elaborare.
Ad ogni registro è associato un nome mnemonico, ed è tramite tale nome che si
può accedere al suo contenuto.
Noi prendiamo in considerazione solo quelli in qualche modo accessibili all'utente, e
rimaniamo a quelli compatibili 8086 (per ora). Accanto ad ognuno di essi la
descrizione e un indicazione sull'uso che se ne fa in generale.
Registri Segmento
ES - Extra Segment - Dati
DS - Data Segment - Dati
CS - Code Segment - Codice
SS - Stack Segment - Stack
Registri Offset
IP - Instruction Pointer - Codice
SP - Stack Pointer - Stack
BP - Base Pointer - Stack/Dati
DI - Destination Index - Dati
SI - Source Index - Dati
Registri di uso generale
AX - Accumulator
BX - Base
CX - Counter
DX - Destination
CS:IP - Punta alla prossima istruzione da dover eseguire
SS:SP - Punta alla testa dello stack
Con r1:r2 intendo dire che per sapere l'indirizzo effettivo si devono
tenere in considerazione entrambi i registri, vedremo poi in che modo.
Registro Flag
Questo registro è un po' particolare. Alcuni suoi bit sono usati per
rappresentare determinate situazioni, e nonostante non sia visibile
dall'utente ci sono istruzioni che permettono di controllarne i singoli
bit.
Bit: |
15 |
14 |
13 |
12 |
11 |
10 |
09 |
08 |
07 |
06 |
05 |
04 |
03 |
02 |
01 |
00 |
Flag: |
|
|
|
|
OF |
DF |
IF |
TF |
SF |
ZF |
|
AF |
|
PF |
|
CF |
OF - Overflow
Owerflow aritmetico, quando la dimensione del risultato di un'operazione
supera la dimensione del registro/locazione di destinazione.
DF - Direction
Indica se le istruzioni per uso su stringhe causano un auto-incremento o un
auto-decremento dei registri indice.
OF - Interrupt Enable
Quando questo flag è a 0, nessun interrupt, tranne i non mascherabili (NMI), può essere generato.
TF - Trap
Usato dai debugger, se il flag è attivo, dopo ogni istruzione viene
generato in INT 3
SF - Sign
0 per numeri positivi, 1 per numeri negativi.
ZF - Zero
Se il risultato dell'operazione è 0, il flag è attivo.
AF - Auxiliary Carry
Usato per istruzioni ad aritmetica-decimale, senga resti prestiti
intermedi.
PF - Parity Flag
Se il numero di bit con valore pari a 1 è pari nel risultato, il
flag è attivo.
CF - Carry Flag
Indica la presenza di riporto o di prestito nel risultato. Utile per numeri
multi-word.
I Bus
Se ci fosse solo la CPU, sarebbe un ben misero guadagno la possibilità di
fargli fare milioni di operazioni al secondo. Per questo è stata fornita di
una serie di canali per comunicare e interagire con l'esterno.
Tre sono le vie di comunicazione:
- DATA BUS
- costituito da 2^N linee fisiche, qui sopra viaggiano i dati in ingresso
e in uscita. Un registro interno, il Data Register (DR), mentiene l'ultima
parola transitata sul bus.
- ADDRESS BUS
- 2^M linee, l'informazione che questo bus trasmette è l'indirizzo della
locazione di memoria (ma non solo) che si intende leggere o scrivere, ed è
unidirezionale, dalla CPU al mondo. Il registro che mantiene l'indirizzo
impostato è l'AR (Address Register).
- CONTROL BUS
- un insieme di linee che svolgono svariati compiti, raggruppati
idealmente in un bus per comodità. In questo bus sono presenti ad esempio i
segnali MEMR,MEMW,DRQ,IRQ, etc. Ad ogni segnale corrisponde un piedino
della CPU, e la bidirezionalità o meno dipende dal segnale stesso.
La dimensione dell'ADDRESS BUS ci dice quante parole
può effettivamente indirizzare la nostra CPU.
Facciamo un esempio: supponiamo una CPU con parola di 8bit, bus indirizzi
di 16bit, che voglia leggere il byte precedentemente memorizzato
all'indirizzo 534h. Quello che deve fare, in una versione estremamente
semplificata e idealizzata, è:
- prendere il controllo del bus indirizzi e del bus dati, traminte un
apposito segnale del bus di controllo
- immettere sul bus indirizzi il numero 0534h
- attivare il segnale di richiesta lettura
- attendere che la memoria renda disponibile sul bus dati il byte
richiesto e invii il segnale di operazione completata
- mettere il byte ricevuto in un suo buffer interno, liberare i
due bus e fare quello che deve fare
CPU al Lavoro:
per ogni istruzione che la CPU esegue, si possono distinguere tre fasi di
elaborazione:
- FETCH, in cui la CPU legge, nel modo che abbiamo visto in precedenza,
la parola corrispondemte all'istruzione da eseguire, puntata da CS:IP.
Quindi la coppia viene incrementata in modo da puntare alla prossima
istruzione.
- DECODE, l'istruzione assembly viene tradotta in microcodice, ovvero in
una serie di passi elementari a bassissimo livello da compiere. In genere
la traduzione in microcodice avviene tramite tabelle HASH
impresse nella CPU, ma alcune CPU (come quella che usa il VAX, se non erro),
prevedono la possibilità di modificare anche il microcodice.
- EXECUTE, il microcodice viene eseguito, quindi si torna al punto 1.
Esempio:
1234:5678 mov ax,4C00 (B8004C)
1234:567B int 21 (CD21)
CS:IP vale 1234:5678.
- La CPU legge la parola B800, che viene posta in un registro interno (IR
- Instruction Register). Quindi CS:IP vengono posti a 1234:567B.
- Decodificando l'istruzione la CPU si accorge che l'istruzione ha dei
parametri, quindi genera la serie di passi che serviranno a:
- incrementare l'AR (incrementare CS:IP non vuol dire automaticamente
metterli sul bus indirizzi), da 179B8 a 179B9.
- inviare un segnale di lettura, la parola 4C00 verrà così
a trovarsi nel DR. Non dimentichiamoci che l'INTEL
memorizza dati a partire dal byte meno significativo, ecco perchè in
memoria abbiamo 004C.
- trasferire il contenuto del DR in AX
- I passi sopra elencati vengono eseguiti, e si torna al punto 1.
In realtà le cose non avvengono esattamente così: anche le CPU più vecchie
hanno una PREFETCH QUEUE, ovvero un piccolo buffer dove non caricano solo la parola puntata, ma
anche un certo numero di quelle successive. Ma il discorso non cambia molto.
Segmentazione:
ovvero l'astruso modo inventato dai tecnici INTEL per accedere alla
memoria, basato su un segmento e un offset. Gli 8086 potevano indirizzare
al massimo 1MB. Perchè? Se si usasse un solo registro, IP, si avrebbero 16
linee di indirizzo, pari a 64k. D'altronde usandone due, CS:IP, sommati
così:
[CS]0000 +
[IP] =
----------
[CS][IP]
si avrebbero avute 32 linee di indirizzo, pari a 4Gb.
Evidentemente all'epoca sembrava uno spreco immane usare 32bit di
indirizzo, quando Bill Gates affermava che 640kb sarebbero stati più
che sufficenti per tutti. (Poi, quando lo stesso Bill inventò
Windows, ripresero in considerazione i 32bit, e crearono il MODO PROTETTO). Allora fecero in
questo modo
[CS]0 +
[IP] =
-------
20bit
la memoria indirizzabile fu 2^20 = 1Mb. Per questo motivo, la locazione
1234:5678 e la locazione 1000:79B8 sono la stessa di 1700:09B8. Tutte e tre
hanno come indirizzo effettivo il numero 179B8, ricordatevene quando
lavorate con segmenti e offset. Allo stesso modo, notate che un segmento
non può superare la dimensione di 64Kb, in quanto l'offset è a 16bit.
Questo tipo di indirizzamento viene usato quando la CPU si trova a lavorare
in MODO REALE
PERIFERICHE
Quando costruirono la prima CPU, si resero conto che sarebbe stato carino
avere un modo per dirgli cosa fare, e per sapere cosa ha fatto. Così
cominciarono a inventarsi le schede perforate, i tastierini esadecimali,
fino ad arrivare ai monitor, le tastiere, le schede sonore, le schede
WinTv, etc... Ora, come fanno tutte queste cose a interagire con la CPU? Da
quello che abbiamo visto finora, si potrebbe pensare di riservare un area
di memoria alla periferca, ed in effetti qualcuna fa così. Ma
questo, oltre a sottrarre indirizzi alla memoria centrale, non è
sufficente. Quindi misero a disposizione della CPU altri metodi per
chiacchierare con il mondo là fuori...
Porte di I/O:
sono ulteriori canali a 8bit, che permettono lo scambio di informazioni
senza dover usare o rimappare della memoria. Possono essere uni o
bi-direzionali, ad ogni porta della periferca corrisponde un registro o una
locazione di una piccola memoria, che la periferica usa per scambiare dati
o per configurarsi. Persino alcuni chip di controllo del PC, come il
generatore di clock o il controller degli interrupt, hanno delle porte che
permettono al bios (e a noi!) di riconfigurarli secondo i nostri gusti.
Fate attenzione che spesso viene indicata soltanto la prima delle porte di
I/O usate, sottintendendo che un certo numero di quelle immediatamente
successive è a loro volta usato. La Sound Blaster, ha come porta base la
220h, ma dalla 220h alla 233h le usa tutte (SB16).
IRQ:
L'IRQ (Interrupt ReQuest) è un segnale che una periferica invia alla
CPU per segnalare una particolare situazione, il terminato trasferimento o
la disponibilità di dati. E' un segnale hardware, da non confondere
con gli interrupt software, indicati con INT. Per ogni IRQ ricevuto la CPU
genera un ben determinato INT:
IRQ |
INT |
|
IRQ |
INT |
0 |
0x08 |
|
8 |
0x70 |
1 |
0x09 |
|
9 |
0x71 |
2 |
0x0A |
|
10 |
0x72 |
3 |
0x0B |
|
11 |
0x73 |
4 |
0x0C |
|
12 |
0x74 |
5 |
0x0D |
|
13 |
0x75 |
6 |
0x0E |
|
14 |
0x76 |
7 |
0x0F |
|
15 |
0x77 |
Sembrerà strano, ma si è presa l'abitudine di indicare gli IRQ in
numerazione decimale, mentre gli INT vengono espressi in esadecimale.
Gli XT avevano a disposizione soli gli IRQ 0..7, dagli AT in poi sono
diventati 15 (quasi).
Il fatto che in corrispondenza di un IRQ venga generato un INT, ci permette
di poter installare su tale INT una routine di gestione della periferca.
DMA:
Il DMA (Direct Memory Access) permette un trasferimento direttamente con
la memoria del PC, scavalcando la CPU, tramite un canale dedicato.
L'integrato controllore del DMA si impossessa del bus dati e bus indirizzi
ed effettua lo spostamento, rilasciandoli per brevi intervalli alla CPU in
modo da non bloccare del tutto il sistema. Al termine del trasferimento la
periferca genera un IRQ, che avvisa la CPU del completamento
dell'operazione. Come sopra, gli XT avevano 4 canali DMA (0..3), poi ne
misero 8.
Considerazioni:
Anzitutto, vediamo con una breve tabella quali sono i modi usati
dalle principali periferiche del PC:
|
I/O |
IRQ |
DMA |
Tastiera |
SI |
SI |
NO |
Monitor |
SI |
[1] |
NO |
Floppy |
SI |
SI |
SI |
HD |
SI |
SI |
SI(opt.) |
Int. Seriale |
SI |
SI |
NO |
Int. Parallela |
SI |
SI |
SI[2] |
Scheda Sonora |
SI |
SI |
SI |
CD-ROM non IDE |
SI |
SI |
SI(opt.) |
Scheda di rete |
SI |
SI |
SI(opt.) |
Scanner |
SI |
SI |
SI |
[1] Alcune schede grafiche EGA fanno uso di un IRQ per avvisare
l'avvenimento di un retrace dello schermo.
[2] Le nuove interfacce parallele ECP permettono il
traferimento tramite DMA.
Buffo notare che i floppy hanno da sempre usato il trasferimento
DMA, al contrario degli HD che pure hanno un loro canale dedicato.
Quando entra in gioco il trasferimento di grandi quantità di dati,
o quando è importante la velocità con cui i dati devono essere
trasferiti, la differenza nell'usare il trasferimento tramite
porte di I/O o quello tramite DMA diventa notevole.
Nel trasferimento con porte di I/O, la CPU deve leggere/scrivere
un byte alla volta, entrando in un loop che termina col
trasferimento. Gli svantaggi che si hanno sono:
- la CPU viene impegnata anche totalmente, impedendo l'esecuzione di
altri programmi. Questo si fa sentire specialmente in ambienti
multitasking.
- la frequenza del trasferimento dati dipende dalla CPU, e può non
arrivare alla capacità massima della periferica. Effettuare controlli o
usare segnali di IRQ, rallentano ulteriormente.
- se usando gli IRQ si verifica una situazione per cui una periferca ne
genera uno mentre un altra effettua un trasferimento, si possono verificare
perdite di dati.
D'altra parte un trasferimento tramite DMA comporta un lieve rallentamento
del sistema, poichè soltanto un dispositivo alla volta può accedere ai bus
di indirizzi e dati, ma sempre in maniera decisamente minore.
Un esempio pratico: il treferimento da/per memorie di massa quali gli Hard
Disk. Il metodo usato finora col DOS è il PIO, Polled I/O, ovvero quello
che fa uso delle porte di I/O. Per accellerare la capacità di trasferimento
dell'HD, si sono diminuiti i tempi necessari al singolo byte per essere
disponibile sulla porta, introducendo i vari PIO2, PIO3 e PIO4. Finchè si
sta in DOS, la cosa sembra essere meravigliosa. Non appena si passa a
sistemi multitask, ogni trasferimento di questo tipo rallenta notevolmente
tutto il sistema, e fortunatamente il recente diffondersi di sistemi
operativi multitasking (parlo di quelli veri) ha convinto i produttori di
hardware a rendere disponibile il trasferimento DMA anche per gli HD. Con
gioia di tutti noi, e con rabbia di chi usa gli SCSI, che ora non ha più
questo motivo per sfottere (ne ha sempre molti altri, però).
Per maggiori dettagli su questo argomento, fate riferimento all'articolo di Fernando apparso sul
numero 3 di Beta.
Bene, a questo punto ne sapete quanto può bastare per cominciare a
lavoricchiare. Un poco alla volta scenderemo nei dettagli, abbiate pazienza.
perifericamente,
Cthulhu
Copyright © 1996 Beta Working Group. Tutti i diritti riservati.
Beta [ << || Pagina Principale || Sommario || Redazione || Informazioni || Beta Browser || >> ]