Personal computer: differenze tra le versioni

Wikibooks, manuali e libri di testo liberi.
Contenuto cancellato Contenuto aggiunto
Pizeta (discussione | contributi)
Pizeta (discussione | contributi)
Riga 1 088: Riga 1 088:


Caricamento 21 %
Caricamento 21 %

Memorizzazione 12 %
Memorizzazione 12 %

ALU 37 %
ALU 37 %

Inizializzazione 6 %
Inizializzazione 6 %

Jump 2 %
Jump 2 %

Jump an link 0 %
Jump an link 0 %

Branch taken 12 %
Branch taken 12 %

Branch not taken 11 %
Branch not taken 11 %



Versione delle 00:41, 23 feb 2006

Wikiversità
Questo libro può essere utile per
il corso di Calcolatori Elettronici dell'area di Ingegneria

Un personal computer è un elaboratore elettronico per uso personale, realizzato con specifici componenti che possono essere assemblati tra loro poiché rispettano degli standard.

Premesse che hanno portato all'idea di personal computer

Storia dei calcolatori

La storia dei calcolatori è alquanto recente. Questo potrebbe apparire strano, considerato l'attuale boom tecnologico riguardante le tecnologie informatiche. Ma un calcolatore, almeno in origine, non prevedeva tutti gli usi che ne facciamo oggi. Il primo calcolatore elettronico, infatti, veniva impiegato per calcoli balistici durante la seconda guerra mondiale, progettato e costruito da J. P. Eckert e J. Mauchly venne denominato ENIAC, sigla per Electronic Numerical Integrator and Calculator, e la sua esistenza venne resa nota solo nel 1946. Lungo trenta metri, alto due e spesso uno, pesava trenta tonnellate per 120 metri cubi di volume su una superficie di 180 metri quadri, poteva eseguire 1900 somme al secondo e richiedeva una programmazione manuale attraverso fili ed interruttori in modo da riprodurre la rete logica dell'operazione da eseguire, i dati venivano poi introdotti tramite schede perforate.

Fu interessandosi al progetto ENIAC che John Von Neumann elaborò l'idea del calcolatore moderno, pensando alla memorizzazione dei programmi in forma numerica. Ne nacque la proposta di un calcolatore chiamato EDVAC, che, impropriamente attribuito al solo Von Neumann, vennere realizzato dagli ingegneri Eckert e Mauchly. La soluzione del calcolatore a programma memorizzato divenne subito la norma e distingue gli attuali calcolatori elettronici dalle macchine dedicate al calcolo. Il primo calcolatore ad avere un discreto successo fu in seguito l'EDSAC (1949) che rimase popolare fino agli anni settanta.

L'IBM che in precedenza trattava macchine a schede perforate da ufficio, iniziò a costruire calcolatori a partire dal 1952 (IBM 701 di cui furono venduti 19 esemplari), ma fu l'introduzione del sistema S/360 a determinare il dominio dell'IBM in questo campo. Per la prima volta si separavano il concetto di architettura da quello di realizzazione, questo permise all'azienda di definire un'organizzazione della macchina comune ad una famiglia di calcolatori che avrebbero potuto avere capacità, potenzialità ed anche dimensioni diverse pur rimanendo tra di loro compatibili, è il caso del sistema S/370 successore del precedente ma ad esso compatibile.

Tutti i calcolatori realizzati fra gli anni sessanta e settanta appartengono alla categoria dei mainframe, ovvero macchine enormi e costose equipaggiate con sistemi operativi che ne permettevano un uso condiviso da parte di più utenti. Solo nel 1965 la DEC introdusse il primo minicalcolatore, il PDP 8 al costo di 20.000 Dollari seguito nei primi anni settanta dal PDP 11, il primo minicalcolatore organizzato intorno ad un unico bus, un'organizzazione che diventerà uno standard per almeno vent'anni.

Il termine di microprocessore venne usato per la prima volta nel 1972 dalla Intel ed indicava un computer microprogammabile su un unico chip composto da una CPU (Central Processing Unit) integrata costituita da un sommatore parallelo a 4 bit, 16 registri, un accumulatore e uno stack. Questa CPU venne denomintata 4004 ed utilizzata dal sistema MCS-4, nel frattempo la stessa IBM lavorava anche ad un microprocessore ad 8 bit, l'8008 introdotto nel 1972, interamente realizzato in tecnologia PMOS. Fu però nel 1974, con l'introduzione dell'8080, che il microprocessore si mostrò in grado di essere utilizzato come elaboratore di uso generale (general purpose). Questo processore raggiungeva frequenze di clock di 2 MHz. Il successo dell'8080 generò due microprocessori concorrenti, il Motorola MC6800 e lo Zilog Z80, il 6800 fu il primo processore ad utilizzare un'alimentazione singola di +5V abbassando notevolmente il costo del prodotto.

Il primo microprocessore con bus dati a 16 bit fu il PACE nel 1974, ma fu l'8086 della Intel, che indirizzava 1Mbyte di memoria contro i 64kbyte degli altri processori, a segnare il passaggio alla seconda generazione di microprocessori, con 5MHz di clock e 0,33 Milioni di istruzioni al secondo (MIPS). Ovviamente seguirono le versioni a 16 bit di Motorola e Zilog, rispettivamente MC68000 e Z8000, che, nonostante avessero prestaioni migliori, non contrastarono lo strapotere dell'Intel poichè all'uscita di questi processori, con quasi due anni di ritardo, l'Intel aveva già pronto l'8088 con bus a 8 bit. L'Intel divenne quindi lo standard di fatto nel mondo dei PC mentre la Microsoft poneva le basi per divenrare la più grande compagnia software del pianeta. Il Motorola MC68000 tuttavia ebbe un ruolo importante perchè si affermò sulle workstation (sistemi di carattere professionale) con sistema operativo Unix, questo processore era infatti più adeguato a gestire la memoria virtuale di Unix.

Mentre i processori a 16bit entravano in una fase di grande crescita con l'aggiunta di nuovi componenti avanzati quali i gestori di memoria (MMU), le unità aritmetiche in virgola mobile (FPU) e i controllori di accesso alla memoria (DMA), si assisteva alla nascita di nuova generazione di macchine dette RISC (Reduced Instruction Set), i vecchi calcolatori vennero denominati CISC (Complex Instruction Set). La prima macchina RISC venne realizzata da IBM come prototipo (IBM 801) nel 1979 ma la prima realizzazione con un discreto successo è il RISC I nel 1982 seguita dal MIPS del 1983 realizzate rispettivamente dalle università di Berkeley e Stanford che convogliarono gli studi nello sviluppo delle CPU SPARC (Scalable Processor Architecture)

Intato nel 1984 Motorola introdusse il primo processore a 32 bit, l'MC68020 con frequenze di 25MHz. Questa volta fu Intel ad arrivare in ritardo introducendo il suo processore a 32 bit nel 1985, l'80386, ma questo non scalfì la sua egemonia, mantenuta grazie all'immenso patrimonio software ormai esistente. L'architettura 68000 rimaneva un'alternativa valida soltanto nel campo delle workstation, ma i processori RISC stravolsero questo segmento di mercato. Agli inizi degli anni novanta IBM, Apple e Motorola formarono un consorzio per la produzione di una nuova CPU RISC per battere anche sul camo dell'informatica di basso costo lo strapotere dell'Intel, nacque quindi l'architettura PowerPC che si dimostrò essere quanto di meglio si potesse realizzare all'epoca. Nonostante ciò il PowerPC non riuscirà mai a contrastare la presenza di Intel nel campo dei Personal Computer.

Architettura del calcolatore

La concezione che abbiamo oggi di calcolatore multifunzione di tipo generale è basata su un concetto teorico di circa cinquanta anni fa. Von Neumann la elaborò come una macchina digitale ad esecuzione sequenziale e programma memorizzato, questo permette di esprimere il concetto di funzionamento desiderato in termini di sequenza di istruzioni (il programma) memorizzate su un supporto di memoria, in modo da poter cambiare funzionamento semplicemente cambiando il programma in esecuzione.

A costituire la struttura di un calcolatore sono:

  • linguaggio macchina o Instruction Set Architecture - ISA ovvero un set di istruzioni che si pongono come interfaccia all'utente per le operazioni che svolge il calcolatore
  • struttura interna l'insieme di blocchi interconnessi, ognuno costituente un sottosistema logico della macchina
  • realizzazione circuitale ovvero la tecnologia microelettronica alla base del sistema

L'architetttura risulta adatta a trattare problemi molto pù complessi di quelli delle reti logiche, per questo motivo il calcolatore è suddiviso in blocchi più semplici collegati da una struttura ad hoc. Gli elementi indipendenti sono le strutture di

  • memoria principale, contiene le istruzioni del programma da eseguire e i risultati delle operazioni svolte. Istruzioni e dati sono codificati in forma binaria, questo comporta che non siano di per sè distinguibili le istruzioni dai dati, ma tutto dipende dal modo in cui un gruppo di bit viene letto e interpretato. Il fatto che dati e istruzioni sono diano distinguibili permetti di avere programmi, quali i compilatori, che generano dati che possono essere interpretati come istruzioni.
  • l' unità di elaborazione e controllo o CPU (Central Processing Unit) è quella che interpreta ed esegue il programma, sarà a sua volta suddivisa in sottosistemi più semplici quali PC (Program Counter), ALU (Arithmetic and Logic Unit), Registri, Cache e vari strumenti aggiuntivi,
  • Le Interfacce o registri di Input/Output con il compito di interfacciarsi ai dispositivi di input/output (memoria di massa, monitor, tastiera, stampante, ...); sono detti anche buffer.

A permettere la comunicazione, e quindi lo scambio dati, tra questi tre blocchi vi è il Bus di sistema. Fino agli anni novanta il bus era un unico canale di comunicazione, con l'enorme crescita delle prestazioni della CPU e l'impiego di memorie cache la struttara a bus unico venne abbandonata per far spazio alle attuali architetture che prevedono più bus. Vi è quindi un bus ad altissima velocità per il trasferimento di dati tra memoria cache, memoria centrare e CPU, un bus a prestazioni più basse che collega i dispositivi periferici.

Il moderno sviluppo dell'informatica sta avvenendo soprattutto nell'ambito dei processori. Resta infatti la struttura di comunicazione, detta BUS, una delle parti più lente della macchina. Approssimativamente, possiamo dire che mentre i più recenti processori hanno frequenze di Clock che vanno dai 4 ai 6 GHz, la frequenza del clock del BUS, non va, nei computer a più alte prestazioni, oltre gli 800 MHz. Una tale differenza provoca inevitabilmente dei colli di bottiglia. L'unica altra parte del computer che è più lenta è il disco rigido.

Abbiamo messo in un gruppo tutti i tipi di memoria, sia contenente dati che programmi. Questo perché se si prende un singolo byte, non si può dire se esso provenga da un programma o da un dato.

Da un punto di vista logico si può dividere il BUS di sistema in tre bus:

  • Bus Dati, ha il parallelismo della cpu e scambia istruzioni e dati con gli altri bus agent, ovvero memoria e I/O
  • Bus di controllo, contiene informazioni che permettono all'agente master (la CPU) il controllo degli agenti slave (memoria e interfacce), quali ad esempio il Memory Read Command, Memory Write Command, ...
  • Bus di indirizzi, ha la dimensione dello spazio di indirizzamento della memoria (l'8086 aveva 20 bit di indirizzo, gli attuali calcolatori hanno 32 o anche 36 bit)

CPU

Rappresentando la CPU con un diagramma compatto la si può dividere in due semplici stati, quello di: IF e quello di EX, dato che l'unico compito che la CPU deve svolgere è eseguire le istruzioni. I due stati sono quindi Instruction Fetch ed EXecute. Quando la CPU si trova nello stato IF legge dalla memoria l'istruzione che eseguirà al prossimo ciclo di clock nello stato di EX. L'esecuzione di un programma, ovvero una sequenza di istruzioni, richiede che esista un registro speciale con funzione di puntatore alla prossima istruzione da eseguire. Tale registro è il Program Counter (PC). Nello stato di Fetch la CPU legge nella cella di memoria indirizzata dal PC l'istruzione da eseguire e prima di passare allo stato di Execute aggiorna il PC con l'indirizzo della prossima istruzione da eseguire. Il PC può essere aggiornato anche quando la CPU si trova nello stato di Execute, è il caso dell istruzioni di trasferimento del flusso, ovvero di istruzioni che modificano il normale comportamento sequenziale della macchina per effettuare salti tra istruzioni non contigue (in linguaggi di programmazione più alti, quali il C, corrispondono concettualmente alle istruzioni di controllo condizionato).


La CPU è inoltre diviso in due unità fondamentali:

  • unità di calcolo
  • unità di controllo
Unità di controllo

L'unità di controllo è una rete sequenziale sincrona comandata dai comandi di ready ed interrupt che ha il compito di generare, in base alle istruzioni in ingresso dalla memoria, l'unità di calcolo, specificando una determinata micro-operazione, ovvero un'operazione eseguita all'interno dell'unità di calcolo in un ciclo di clock, quale ad esempio il trasferimento di un dato da un registro ad un altro o una elaborazione della ALU

Unità di calcolo

L'unità di calcolo, o anche Datapath contiene tutte le unità di elaborazione ed i registri necessari per l'esecuzione delle istruzioni della CPU, ogni operazione è una sequenza di operazioni elementari, le micro-operazioni.

L'unità di calcolo differisce molto tra diverse architetture ma gli elementi fondamentali sono:

  • Instruction Register IR, è il registro che contiene l'istruzione in corso di esecuzione, viene caricato nella fase di fetch e determina le azioni svolte durante la fase di esecuzione
  • Program Counter PC, il registro che tiene traccia dell'esecuzione del programma
  • Memory Address Register MAR è il registro che contiene l'indirizzo della locazione di memoria da leggere o scrivere. L'uscita di questo registro è sul Bus degli Indirizzi
  • Memory Data Register MDR è il registro attraverso la quale viene scambianta l'informazione tra la memoria e la CPU, la sua uscita è sul Bus Dati
  • Registri General Purpose di uso generale, sono impiegati per memorizzare dati su cui opera la ALU, sono quindi utilizzati sia di appoggio dati che per gestire l'indirizzamento. Nelle CPU più datate questi registri erano più specializzati, vi era in particolare il registro accumulatore che doveva essere necessariamente utilizzato in certe operazioni aritmetico logiche.


Quantifiche Prestazionali dei sistemi

Come abbiamo già visto esistono vari tipi di sistemi, ognuno con architetture specifiche e metodi di produzione diversi e ognuno con prestazioni differenti. Per poter fare confronti si deve cercare di creare una scala di misurazione. Su quest'argomento si dibatte costantemente. Ecco le principali unità di misurazione, ricordando sempre che i valori devono essere calcolati utilizzando dei benchmark comuni, ovvero dei benchmark sviluppati con un linguaggio di alto livello per poi essere compilati indipendentemente per processori diversi. Questo implica un diverso numero di istruzioni semplici.

CPU-time

Questo tipo di misurazione si basa sul mero tempo necessario per eseguire un programma.

con

  • pari al numero di istruzioni che compongono il programma in quella particolare architettura.
  • pari al numero di cicli di clock mediamente necessari per ogni istruzione semplice.
  • pari al tempo fisico di durata di un singolo ciclo di clock.

Il concetto di è piuttosto complesso. Infatti osservando che una certa istruzione può non essere eseguita nello stesso tempo di una'altra istruzione, si deve proprio calcolare il tempo medio di esecuzione dell'istruzione. In particolare se ne calcolerà la media ponderale sulle n istruzioni necessarie per l'esecuzione del programma.

Il valore di CPI medio, teoricamente, dovrebbe sempre essere maggiore di 1, ma non è proprio così, in quanto oltre all'esecuzione consecutiva, in un processore si hanno anche, soprattutto nelle ultime generazioni di processori, alti livelli di parallelismo. Questo significa che più istruzioni possono essere eseguite contemporaneamente. Perciò spesso si hanno pari a 0.5.

MIPS

Questo tipo di unità di misura piace molto ai giornalisti, ma non ha grande rilevanza scientifica. Infatti rappresenta i milioni di istruzioni al secondo, calcolate rispetto ad un generico basato su un benchmark. Quindi

Questo sarebbe un buon risultato se non fosse che a parità di benchmark e MIPS possono risultare CPU-time e N diversi, per la stessa architettura.

Per questi motivi l'acronimo MIPS è stato negli anni scherzosamente ridefinito come Meaningless Indication Provided by Salesman, ovvero Indicazione con scarso significato fornita dai venditori.

Speed-Up

Questa scala permette di osservare se a parità di benchmark un sistema è più veloce di un altro. Il problema sta nel fatto che il calcolo è talmente approssimativo che in realtà un valore basso di speedup non rappresenta una certezza da un punto di vista di velocità di esecuzione. Infatti si ha


che al variare di alcuni aspetti del benchmark e dell'uso di certe istruzioni può completamente ribaltare ogni risultato ottenuto con un tale tipo di calcolo.

Gli Standard alla base di un personal computer

Nozioni preliminari relative all'assemblaggio di un personal computer

Una struttura in cui montare tutto: il case

Tower, middle tower, mini tower, barebone, desktop, portabile, portatile o palmare?

Lo standard ATX

Il cuore del sistema: la mainboard

Il cervello del sistema: il chipset

Schemi alla base del funzionamento del chipset e dei controller ad esso collegati: BUS

Esistono tre tipi di bus:

  • Il bus dati trasporta i segnali contenenti operazioni ed operandi. (D[n-1, ..., 0]).
  • Il bus indirizzi trasporta, senza qualificare la locazione fisica dell'oggetto, l'indirizzo al quale portare o raccogliere informazioni.
  • Il bus segnali trasporta, in base al tipo di architettura, 2 o 4 dati: RDC#, WRC# oppure MRDC#, MWRC#, IORDC#, IOWRC#.
Schemi alla base del funzionamento del chipset e dei controller ad esso collegati: Agenti Master/Slave

In base all'uso che i vari componenti fanno del bus si possono dividere i singoli componenti in vari gruppi:

  • Master, se hanno il potere di controllare il bus
  • Slave se non hanno mai la possibilità di controllare il bus
  • Master/Slave se possono per brevi periodi controllare il bus, ad esempio per trasferire dati.

Come è facile supporre possono esistere sistemi con un solo master ed un solo slave, ma è più frequente avere molti master allo stesso livello. Questo tipo di configurazione è detta Multi-Master. Un tale tipo di configurazione necessita in genere di un particolare strumento detto Arbitro, che gestisce chi deve avere il controllo del bus per un certo periodo.

Parti del chipset: Northbridge
Parti del chipset: Southbridge

Lo standard PCI-Express

Lo standard PCI

Lo standard AGP

Lo standard ISA

Lo standard ATA

Parallelo (ATAPI)
Seriale (SATA)

La capacità di elaborare: il processore

Ogni CPU è dotata di una serie di istruzioni in linguaggio macchina che sa utilizzare. Questo insieme di istruzioni note è detto Instruction Set. In genere ogni tipo e marca di processori ha un instruction set proprio, e quasi sempre completamente retrocompatibile (anche a costo di perdere un po' di prestazioni). Generalmente un numero limitato di istruzioni implica una maggiore velocità di esecuzione, ma sono necessarie più istruzioni. Quindi da un punto di vista prestazionale si suppone che la soluzione più general purpose stia nel mezzo.

Ma la diversità di vedute a questo proposito ha dato origine a due grandi famiglie di processori: CISC e RISC, ovvero Complex Instruction Set Computer e Reduced Instruction Set Computer. I primi con sempre più istruzioni ad ogni generazione di processori, i secondi con un numero limitato ma costante di istruzioni.

Il posto dove elaborare: la memoria RAM

La RAM (Random Access Memory) è una memoria volatile molto veloce in cui vengono immagazzinate le informazioni da passare alla CPU per essere elaborate. Il vantaggio della RAM è quello di essere per l'appunto, molto veloce, i sui tempi si misurano nell'ordine dei nano secondi (1 miliardesimo di secondo), quindi le informazioni che contiene possono venir lette e scritte molte volte nell'arco di un secondo, ma dall'altro lato ha uno svantaggio da non sottovalutare, cioè le informazioni memorizzate sono volatili, cioè nel momento in cui manca l'energia elettrica che le alimenta, tutti i dati vengono irrimedibilmente persi. La grandezza con cui si misura è il MB (1048576 byte). Viene venduta in "banchi" di grandezza variabile a partire da 64 MB fino a 1 GB.

Esistono vari tipi di RAM a seconda della velocità a cui lavorano: Memorie SIMM, Memorie SDRAM, velocità max 66~133MHz, tagli da 32~512 MB Memorie DDR SDRAM, velocità max 266~533 MHz, tagli da 128~1024 MB (montate a partire dai primi Athlon XP e Pentium 4) Memorie RIMM o RAMBUS, in disuso, ne veniva equipaggiato il primo Pentium 4 ma dato l'alto costo e le basse prestazioni si preferì optare per le DDR. Di RAM DDR esistono anche quelle dette ECC, cioè capaci di controllare e correggere eventuali errori nel trascrivere dati da un dispositivo all'altro. Quando si acquistano le RAM bisogna fare molta attenzione all'inballaggio perché questi componenti sono molto sensibili all'elettricità statica e anche una piccola noncuranza ne potrebbe provocare il danneggiamento, quindi fate attenzione che siano inballate in buste apposite (di solito trasparenti con righe nere diagonali).

Schemi alla base del funzionamento della RAM: L'indirizzamento della memoria e dell'output

La RAM può essere di due tipi: statica o dinamica. Una ram dinamica è composta dai condensatori contenuti in transistori FET. Questo implica un fondamentale problema, ovvero che la memoria deve essere rinfrescata con una certa frequenza, poiché è esperienza comune che basta la misera conduttività dell'aria per scaricare in breve tempo un condensatore. Al contrario le RAM statiche sono costituite da Flip-Flop. Perciò sono più robuste, ma richiedono più controllo. In genere sono formate da blocchi di Flip-Flop uniti in una EEPROM.

Un processore può indirizzare un numero di blocchi di memoria, da 8 bit ciascuno, pari a 1/8 del livello di parallelismo del processore stesso. Se ad esempio un Pentium 4 ha 32 bit di parallelismo, può indirizzare dati su massimo 4 blocchi di memoria. E dallo stesso numero di blocchi può leggere, ovviamente. Osservando il processo di scrittura dei dati, si nota che la necessità di parallelismo implica che i dati devono essere scritti su blocchi fisici di memoria diversi, ma che rappresentano informazioni consecutive.

L'input-output può essere visto architetturalmente in due modi che hanno vari punti in comune: L'I/O può essere mappato sulla memoria, quindi accessibile come indirizzo di memoria ed indistinguibile da essa a livello di processore. Questa soluzione implica che il bus deve sapere in che modo sono organizzati i dati e le memorie. L'altra soluzione è quella di dotare il bus di un canale specifico nel quale sottolineare il tipo di dato che si cerca: dato in memoria o dato in I/O. Non esiste una soluzione migliore. A livello di sistema operativo in realtà non esiste differenza. E' solo un aspetto costitutivo. In genere i byte allocati per l'I/O sono 64 KiloBit.

Caratteristiche funzionali della RAM

La RAM, Random Access Memory, è il dispositivo di memoria rapida del calcolatore. Al contrario della EPROM deve essere sia leggibile che, soprattuttto, scrivibile in tempi molto ristretti. Esistono due tipi di RAM costruiti in modo completamente diverso. La SRAM, ovvero Static RAM, è composta da Flip-Flop che mantengono memorizzati i dati. Il tempo di accesso è minimo, ma la capacità è minore rispetto alle DRAM. Queste, Dynamic RAM, sono composte da transistor di tipo MOS. La capacità aumenta, ma la velocità di accesso è minore.

File:Ram logic.png

La struttura logica interna di una RAM è comunque comune ad entrambi i tipi di RAM. L'aspetto fondamentale è nel doppio uso del bus di dati che porta il dato da scrivere (in caso di scrittura), oppure il dato letto (in caso di lettura). Questo avviene attraverso un intelligente uso di un buffer tri-state.

Caratteristiche della RAM

  • Capacità a potenze pari di 2
  • Sigla: 62xxx

Porte del chip:

  • GND - a massa
  • VCC - Tensione di alimentazione
  • CE* - Chip Enable - accensione del chip di RAM
  • OE* - Output Enable - va a zero nel momento della lettura
  • WE* - Write Enable - va a zero nel momento della scrittura
  • A0 .. A16 - Indicatori della posizione della casella di memoria
  • I/O0 .. I/O7 - Dati in uscita o ingresso

Il posto dove conservare le informazioni: l'hard disk

Il Disco Rigido o Hard Disk, è una memoria di massa, a differenza delle RAM le sue informazioni non sono volatili ma rimangono anche dopo che si toglie l'alimentazione. Un vantaggio dell'HDD è il basso costo per MB, un disco rigido moderno da 120GB (120000 MB circa) ha un prezzo che si aggira intorno ai 60~70 Euro quindi il suo costo per MB si aggira intorno ai 0,0005417 Euro. Uno punto a sfavore dei dischi rigidi rispetto alle RAM è quello di essere molto più lento, quindi poco adatto a contenere informazioni in elaborazione. Esistono ad oggi 3 tipi di interfacce per dischi rigidi IDE, la più utilizzata, ha una capacità di trasferimento dati che va dai 33 (ATA 33) ai 133 (U-ATA 133) MB (teorici) per secondo, su ogni attacco del controller IDE è possibile installare un massimo di 2 unità (master e slave). SCSI (Small Computer System Interface), la tecnologia più veloce per questo tipo di periferica, si compone di un controller SCSI a cui è collegato un cavo che può supportare un massimo di 16 periferiche (Wide SCSI), ognuna con il proprio ID. S-ATA (Serial ATA), è la tecnologia più recente (arrivata da poco alla seconda versione) evolutasi dal Parallel ATA (IDE), permette il trasferimento seriale dei dati da e verso il controller del disco rigido ad un velocità max di 150 MB/S, su ogni connettore può essere collegato un solo dispositivo.

I dischi rigidi sono dei piatti metallici su cui viene spalmata una sostanza la cui magnetizzazione può essere modificata un numero molto grande di volte dalla testina di lettura/scrittura, questi piatti girano ad una velocità variabile dai 5400 ai 15000 Giri/min (come il motore di una moto!!!) a seconda del modello di disco preso in esame. La superficie del disco però non è eterna e dopo qualche anno, a causa del deteriorarsi della sostanza sui piatti potrebbero verificarsi errori con la conseguente perdita di dati. Una buona manutenzione del disco (scandisk, chkdsk, o altro) non allunga la vita del disco ma per lo meno fa in modo che ci si accorga subito se qualche cosa non va. Esiste anche una tecnologia implementata nelle schede di controllo di tutti i dischi rigidi, il suo nome è S.M.A.R.T. (Self Monitoring Analysis and Reporting Technology) e avvisa l'utente nel caso il disco rigido cominci a dare segni di malfunzionamento consigliando la sostituzione e di conseguenza evitando la perdita di dati.

Vedere le informazioni: la scheda video

Sentire le informazioni: la scheda audio

Scambiare informazioni: la scheda di rete

Connettersi al mondo: il modem

PSTN, ISDN, ADSL, HDSL, GSM, GPRS o UMTS?

Modem sta per MODulatore/DEModulatore, ha la funzione di trasformare i dati binari in uscita dal PC in impulsi elettrici e viceversa per essere adatti a transitare sulla linea telefonica. Il Modem di casa è solitamente a 56 Kbs (Kilobit per secondo), esistono poi Modem particolari Isdn e ADSL che hanno velocità molto maggiori (fino a 1280 Kbs).

Strumenti di interazione: la console (monitor, tastiera, mouse, diffusori audio e microfono)

Conservare altrove le informazioni: i supporti ottici

CD

DVD

I masterizzatori

Espandere il sistema: le porte di comunicazione

Lo standard USB e USB2

Lo standard Firewire (IEEE 1394 o DV)

La porta parallela

Dal bit alla carta: la stampante

Dalla carta al bit: lo scanner

L'OCR

Dare corrente al tutto: l'alimentatore

Componenti minori all'interno di un personal computer

EPROM

File:Eprom.png

Una Eprom è un dispositivo di memoria statica che deriva il suo nome dalle sue caratteristiche principali: Eraseable Progammable Read Only Memory. Ovvero cancellabile, programmabile, leggibile. La programmazione di una EPROM avveniva infatti una sola volta, e non era così facile aggiornare il programma in essa contenuto, poiché la cancellazione avveniva solo tramite l'uso di una luce a raggi ultravioletti. Oggi le cose sono molto diverse. Non esistono più solo EPROM ma anche EEPROM ovvero Electrically Eraseable PROM, cioè EPROM che possono essere cancellate e riprogrammate attraverso impulsi elettrici inviati ad alcune porte del chip.

Caratteristiche delle EPROM:

  • La capacità va a potenze di 2: 32k, 64k, 128k, 256k, ...
  • Le sigle sono del tipo 27xxx, con xxx indicante le dimensioni in Kbits

Porte del chip:

  • GND - porta a massa
  • VCC - porta da connettere all'alimentazione
  • A0 .. A16 - porte degli ingressi
  • D0 .. D7 - porte delle uscite
  • CE* - Chip Enable, porta che permette di accendere il chip solo quando serve.
  • OE* - Output Enable, porta che permette ai dati di essere letti
  • PGM* - Porta che consente ad un programmatore di inserire i dati nella EPROM. Spenta questa porta tutte le altre diventano porte programmabili.


Tipi di architettura

L'architettura dell'hardware di un calcolatore è costituita da una terna di elementi:

  • L'instruction set detto anche linguaggio macchina, costituisce la parte dell'architettura visibile agli sviluppatori dei compilatori o a chi programma in assembler, ed è in sostanza l'interfaccia utente con la macchina stessa.
  • La struttura interna ovvero la realizzazione logica del calcolatore, è un insieme di reti logiche combinatorie atte a svolgere le operazioni tipiche di un calcolatore.
  • La realizzazione circuitale ovvero la tecnologia microelettronica impiegata nella realizzazione dei circuiti integrati del processore.

Intruction Set

Diverse famiglie di processori avranno diverse realizzazioni logiche (386 - 486) ma possono avere lo stesso ISA (Istruction Set Architecture). Ad esempio tutti i processori Pentium hanno la stessa ISA ovvero l' IA32 (Intel Architecture 32 bit).

Il CPUtime è un parametro fondamentale per i processori ed è legato a tre variabili, di cui sia il numero di istruzioni che il CPImedio sono dipendenti dall'instruction set. Per questo motivo un linguaggio macchina viene valutato in base all'efficienza del codice generato dai compilatori: il codice deve essere capace di minimizzare il valore del CPUtime per il maggior numero di applicazioni possibili. Nascono quindi due tipi di architetture, denominate in seguito:

  • CISC
  • RISC
CISC

Storicamente i primi processori erano tutti basati su instruction set che successivamente sarebbero denominati CISC (Complex Instruction Set Computers).

L'approccio dei progettisti CISC era quello di ridurre il gap semantico tra linguaggio macchina e linguaggi ad alto livello, e ridurre così al minimo il numero di istruzioni che una macchina doveva compiere per eseguire un certo programma. Ciò è possibile aumentando la complessità del set di istruzioni che la cpu è in grado di gestire.

La complessità dell'ISA, soprattutto per i primi calcolatori risolveva il problema della memoria. Riducendo il numero di istruzioni da eseguire per ogni programma, era necessaria meno RAM per conservare le istruzioni.

Esempi di architetture CISC sono l'Intel e la Motorola

RISC

Quando il problema della memoria divenne meno stringente (sia per la riduzione dei costi dei blocchi di RAM, sia per la creazione della memoria virtuale), iniziò a venire fuori una nuova filosofia di programmazione, quella RISC (Reduced Instruction Set Computers) basata sulla semplicità del linguaggio macchina.

Questa filosofia pur pagando il prezzo di un più alto numero di istruzioni da eseguire per programma aveva il grosso vantaggio di diminuire notevolmente il tempo di esecuzione di qualsiasi istruzione dell'instruction set, con conseguente riduzione del CPImedio. La semplicità delle architetture RISC ha poi facilitato ed accelerato lo sviluppo di strutture in pipeline.

Esempi di architetture RISC sono il DLX (progetto esclusivamente didattico, non implementato in nessun calcolatore odierno), SPARC (la sua evoluzione UltraSPARC è attualmente molto usata), MIPS ed altre.

74xx244
File:74xx244.png

Questo Circuito integrato consiste in un insieme di 2 gruppi di three-state buffer da quattro bit ciascuno. Ogni gruppo è comandato indipendentemente dall'altro.

Porte dell'integrato:

  • ENx* - abilita il gruppo x di three-state buffer
  • xA1 .. xA4 - Bit in ingresso da abilitare o portare a stato di alta impedenza
  • xY1 .. xY4 - output del buffer three-state
74xx245
File:74xx245.png

Un integrato come il precedente è utile, ma spesso può essere necessario abilitare alternativamente sullo stesso canale sia ingresso che uscita. Per minimizzare lo spazio necessario per un tal genere di esigenza esiste l'integrato 245. Questo si compone di una coppia di three-state buffer in direzioni opposte aperti alternativamente attraverso un comando DIR. Una struttura come questa è detta transceiver. La struttura logica è per il resto sostanzialmete identica alla precedente.

373

Il corretto funzionamento di un personal computer

Configurare i parametri principali di funzionamento: il BIOS della mainboard

Dare un posto ad ogni programma e ad ogni dato: il partizionamento dell'hard disk

Installare e configurare correttamente i sistemi operativi

La perfetta messa a punto di un personal computer (modding)

Guadagnare prestazioni con l'overclocking

La corretta dissipazione del calore

Linguaggio Assembler

Il linguaggio macchina è una sequenza di bit e la sua rappresentazione simbolica è l'assembler, costituisce il livello dell'architettura visibile agli sviluppatori dei compilatori.

Le istruzioni del linguaggio macchina devono permettere di utilizzare le risorse interne del calcolatore, e quindi di accedere alla memoria, ai registri interni alla cpu e di eseguire delle operazioni, per le diverse implementazioni di questo aspetto, i linguaggi macchina sono classificabili in base a

  • Memorizzazione dell'operando nella CPU
  • Numero di chiamate esplicite agli operandi per istruzione
  • Collocazione degli operandi
  • Indirizzamento alla memoria
  • Operazioni
  • Tipologia e dimensione degli operandi

Supponiamo di voler eseguire una semplice operazione quale una somma tra due numeri (A e B) e di voler salvare il risultato in un registro interno alla cpu, il linguaggio macchina deve quindi fornire una codifica per l'operazione che voglio eseguire e gli operandi (indirizzo dei valori in ingresso e del registro in uscita) per cui si può generalizzare indicando il seguente formato per una istruzione assembler:

etichetta codice_mnemonico operandi.

L'etichetta è un parametro opzionale e rappresenta in modo simbolico l'indirizzo dell'istruzione; è utile per la gestione del flusso;

il codice_mnemonico è un identificativo per il codice operativo;

operandi è una lista di operandi separati di virgola, il primo dei quali è quello di destinazione

Memorizzazione dell'operando nella CPU

In generale tutte le architetture sono classificabili in base ai tre tipi di approccio:

  • Stack Architecture: Tutti gli operandi sono sullo stack; in particolare una qualsiasi istruzione usa come operandi sorgente gli ultimi due sullo stack, li cancella e mette l'operando risultato in cima allo stack
  • Accumulator Architecture: Uno dei due operandi sorgente è sempre il valore di un registro speciale detto accumulatore; il risultato dell'operazione viene messo di nuovo sull'accumulatore
  • General-Purpose Register (GPR) Architecture: gli operandi risiedono tutti su registri interni alla CPU oppure in memoria.

Vantaggi e svantaggi dei diversi tipi di approcci sono legati alla misura in cui la macchina si adatta alle necessità del compilatore ed a quanto risulta efficiente il codice rispetto alle altre metodologie. Per questo motivo tutte le macchine moderne utilizzano registri GPR, nel qual modo vengono velocizzate tutte le operazioni. Il tempo di accesso ad un registro è inferiore rispetto a quello della memoria e viene pure fornito uno strumento generale di memorizzazione più semplice da usare.

Da notare inoltre che gli altri due approcci non consentono l'accesso casuale e la gestione di pipeline, ad esempio l'esecuzione dell'operazione (A*B)-(C*D) deve essere eseguita sequenzialmente, mentre utilizzando i registri è possibile eseguire le operazioni tra parentesi in qualsiasi ordine e quindi anche in pipeline.

Va comunque detto che, nonostante l'affermazione delle macchine GPR, esistono degli "ibridi": proprio l'Intel 8086 è una via di mezzo tra una macchina GPR ed una ad accumulatore.

Numero di chiamate esplicite agli operandi per istruzione

Il numero degli operandi che sono chiamati in modo esplicito in una tipica istruzione dipende fortemente dal tipo di memorizzazione. Ad esempio l'istruzione C = A + B può essere tradotta nelle tre categorie di insiemi di istruzioni:

Pila

PUSH A Metti A nello stack

PUSH B Metti B nello stack

ADD Esegui la somma tra gli ultimi due valori nello stack

POP C Prendi C dallo stack


Accumulatore

LOAD A Carica A sull'accumulatore

ADD B Aggiungici B

STORE C Salva in C il valore dell'accumulatore


Registro

LOAD R1,A Inserisci A nel registro R1

ADD R1,B Somma il registro R1 con B e salva il valore in R1

STORE C,R1 Inserisci il valore di R1 in C


In questo esempio il numero di operandi espliciti per la sola operazione di ADD è rispettivamente 0,1,2 - ma nel caso di macchine GPR può anche essere tre. Infatti, nell'esempio considerato l'istruzione ADD R1,B esegue la somma tra R1 e B salvando il risultato nella posizione del primo operando. Ma per certi Instruction Set esistono anche operazioni del tipo ADD R1,R2,R3 a seguito della quale la somma tra i valori di R2 ed R3 viene salvata nel registro R1.

Riassumendo quindi il numero di operandi espliciti per un'istruzione della ALU è compreso tra 0 e 3.

Collocazione degli operandi

Oltre alla presenza di due o tre operandi in una istruzione ALU, un'altra caratteristica che differenzia le architetture GPR è il numero di operandi in memoria consentiti in una tipica istruzione che può variare da zero a tre.

Le possibili combinazioni di numero di operandi e numero di indirizzamenti a memoria sono sette, ma bastano tre per classificare quasi tutte le macchine esistenti:

  • register-register (3,0)
  • memory-register (2,1)
  • memory-memory (3,3)

La coppia tra parentesi indica il (numero di operandi espliciti di un'istruzione ALU), (numero di operandi risiedenti in memoria)

Le macchine R-R (register-register) hanno il vantaggio di codificare più semplicemente le istruzioni (in quanto a lunghezza fissa) che risultano anche essere più corte (lo spazio dei registri è indirizzabile con meno bit rispetto a quello della memoria) tuttavia questo comporta un più alto numero di istruzioni per riferimenti in memoria. D'altro canto le M-M non sprecano registri per memorizzare temporaneamente i dati ma presentano un collo di bottiglia nella velocita di accesso alla memoria.


Indirizzamento alla memoria

Indipendentemente dal tipo di architettura a registri o con riferimenti alla memoria, è necessario definire il metodo di interpretazione degli indirizzi di memoria e la loro specifica.

Interpretazione degli indirizzi di memoria

Esistono due diverse convenzioni per ordinare i byte all'interno di una parola:

  • Little Endian ordinamento a partire dal byte meno significativo, l'indirizzo di un dato è quello del suo byte meno significativo
  • Big Endian ordinamento a partire dal byte più significativo, l'indirizzo è quindi quello del suo byte più significativo.

La scelta di una delle due tecniche è del tutto convenzionale visto che nessuna presenta vantaggi/svantaggi rispetto all'altra, ed è possibile applicare la stessa tecnica di posizionamento anche ai bit nonostante poche architetture dispongano di istruzioni che accedono direttamente ad essi. Un esempio di microprocessore Little Endian è un qualsiasi Intel della famiglia 80x86; i microprocessori Motorola sono invece Big Endian.

Ben più importante è l'allineamento. Alcune macchine (ormai quasi tutte) richiedono che l'accesso ad un oggetto di s byte, collocato all'indirizzo A, sia allineato con l'indirizzo, ovvero la divisione tra A ed s dia resto 0. Ad esempio una parola da 4 byte richiede che il suo indirizzo sia multiplo di 4.

Sebbene possa sembrare una limitazione, l'allineamento rende l'esecuzione dei programmi più veloce.


Modalità di Indirizzamento

La modalità di indirizzamento è il modo in cui le architetture specificano l'indirizzo degli oggetti a cui accedere, che possono essere una costante, un registro o una locazione di memoria. Le modalità principali sono:

  • Registro ADD R4,R3

Il valore dell'indirizzo è un registro

  • Immediato ADDI R4,10

Il valore dell'operando sorgente è una costante

  • Offset ADD R4,100(R1)

Accede a variabili locali, l'indirizzo dell'operando sorgente è calcolato come somma di 100 ed il valore di R1.


Le modalità di indirizzamento possono ridurre anche sensibilmente il numero di operazioni da effettuare a discapito di una maggiore complessità della macchina.


Operazioni

Gli operatori supportati dalla maggior parte degli Instruction Set possono essere raggruppati nelle seguenti categorie:

  • Aritmetico / Logiche: Operazioni aritmetiche (somma, sottrazione...) o logiche (and, or...).
  • Trasferimenti di dati: Istruzioni di trasferimento per macchine con indirizzamento in memoria.
  • Controllo: Diramazione (branch), salto (jump), chiamata a procedura (call), trappole (trap), permettono il controllo del flusso di esecuzione di un programma modificando il valore del Program Counter (PC, contiene il valore dell'indirizzo della prossima istruzione da eseguire).
  • Sistema: Chiamate al sistema operativo, istruzioni per la gestione della memoria virtuale.
  • Virgola mobile: Operazioni con numeri rappresentati in virgola mobile (floating point).
  • Stringa: Spostamento di stringhe, confronto fra stringhe, ricerca su una stringa.

Tipologia e dimensione degli operandi

Solitamente il tipo stesso di un operando fornisce la sua dimensione. I tipi più comuni sono il carattere (1 byte, 8 bit), mezza parola (16 bit), parola (32 bit), virgola mobile in singola precisione (32 bit) o in doppia precisione (64 bit). I caratteri vengono rapresentati nel formato EBCDIC (IBM) o più frequentemente in ASCII (attualmente anche UNICODE). I numeri in virgola mobile sono ormai quasi tutti rappresentati seguendo lo standard IEEE 754 anche se in precedenza ogni costruttore sceglieva una propria rappresentazione.

I numeri naturali vengono rappresentati con numeri binari in complemento a due.

Rappresentazion in complemento a due

Dato un numero binario qualsiasi ad n bit (), il valore decimale lo si calcola come Tuttavia con questa rappresentazione sono rappresentabili soltanto numero positivi.

Una rappresentazione alternativa è quella in complemento a 2 che permette con un numero binario a n bit un numero decimale compreso tra . Con questa rappresentazione il bit di maggior peso è quello di segno (0 indica un numero positivo, 1 uno negativo) e il valore decimale può essere calcolato come: . Questa operazione permette di eseguire la sottrazione di due numeri qualsiasi con un sommatore, infatti A-B è equivalente alla somma tra A e il complemento a 2 di B. Un numero negativo si ottiene anche sommando 1 alla negazione del numero in valore assoluto, per cui se con n=4 bit posso rappresentare il numero 6 come 0110, -6 in complemento a due sarà 1 + not(0110) = 1 + 1001 = 1010.

DLX

L'architettura DLX è molto semplice, se confrontata con i moderni processori. E' di tipo MIPS, come lo erano i primi Sparc.

L'uso della memoria è molto semplice, in quanto il processore non possiede la Stack, ma un solo registro. Non ha nemmeno Flag, quindi sono necessari a livello di OpCode comandi che permettano di proporre condizioni sull'esecuzione di certi blocchi di codice. Non avendo nessuna struttura esterna per il mantenimento "on the fly" di dati importanti per il processore, non si può fare che un jump alla volta. L'indirizzo di partenza viene infatti salvato nell'ultima casella del registro: R31. (Ovviamente stiamo parlando di un processore Big-Endian, in quanto l'ultima casella è anche la più "grande" in indice).

Le istruzioni sono allineate a multipli di 4

La memoria è composta da un solo registro con 32 blocchi di 32 bit ciascuno, e il processore richiede l'allineamento. Ha anche 32 registri per numeri in virgola mobile.

Da un punto di vista operativo le operazioni possibili sono di tre tipi, considerando che è un processore a 32 bit fissi, ovvero ogni istruzione è composta da 32 bit, compresi OpCode e tutti gli eventuali argomenti.

Da un punto di vista logico, invece, i tipi di operazioni sono quattro:

  • aritmetico logiche
  • load e store
  • diramazione e salti
  • virgola mobile

Ogni registro può essere caricato e memorizzato ad esclusione del solo R0 che ha il valore costante 0.

L'unica modalità d indirizzamento possibile è quella tramite offset, ma con offset R0 è possibile ottenere l'indirizzamento diretto.

I caricamenti di mezze parole o byte mettono il valore nella parte bassa del registro ed azzerano la parte alta (oppure estendono il bit di segno).

Tutte le operazioni ALU sono di tipo Register-Register. Sono permessi gli operandi immediati, ovvero valori forniti direttamente dal codice Assembler e non presenti in registri o memorie, l'uso è limitato al terzo operando esclipito e viene indicato nello mnemonico dell'operazione con l'aggiunta del suffisso I al mnemonico dell'operazione da eseguire (ad esempio ADDI R3,R3,5)

Il controllo del flusso del programma avviene tramite salti e diramazioni, i primi possono essere con collegamento (memorizzano l'indirizzo dell'istruzione successiva a quella del salto per riprendere il flusso) o meno; le diramazioni sono tutte con condizione da verificare.


Formato operazioni

Ogni OpCode è composto di 6 bit, ogni indirizzo di 5, mentre i restanti bit sono eventualmente per offset o altri tipi di input. Le tre grandi famiglie di comandi sono:

Formato I
Formato I

Formato I: Questo formato è quello utilizzato per ogni operazione con operatori immediati. Come si nota l'offset è di soli 16 bit, il che significa che non si può passare come argomento direttamente un dato a 32 bit, bensì bisogna suddividerlo in due passaggi con in mezzo uno shift di 16 posizioni.

Formato R
Formato R

Formato R: Questo è il formato delle operazioni fra registri. Gli 11 bit finali vengono utilizzati per rendere più specifiche alcune operazioni (ricordiamo che essendoci solo 6 bit per le operazioni, il numero massimo di queste è )

Formato J
Formato J

Formato J: Quest'ultimo è il formato dei salti condizionati o meno.

Operazioni

  • Trasferimenti di dati
    • LB, LBU, SB Carica un byte, carica un byte senza segno, memorizza un byte
    • LH, LHU, SH Carica halfword, carica halfword senza segno, memorizza halfword
    • LW, SW Load word, store word (a/da registri integer)
    • LF, LD, SF, SD Load SP float, load DP float, store SP float, store DP float (SP - single precision, DP - double precision)
    • MOVI2S, MOVS2I Move from/to GPR to/from a special register
    • MOVF, MOVD Copy one floating-point register or a DP pair to another register or pair
    • MOVFP2I, MOVI2FP Move 32 bits from/to FP tegister to/from integer registers
  • Aritmetica/Logica
    • ADD, ADDI, ADDU, ADDUI Add, add immediate (tutti gli immediati sono a 16 bit); signed and unsigned
    • SUB, SUBI, SUBU, SUBUI Subtract, subtract immediate; signed and unsigned
    • MULT, MULTU, DIV, DIVU Multiply and divide, signed and unsigned; Gli operandi devono essere registri Floating-point; Tutte le operazioni richiedono valori a 32 bit e danno come risultato valori a 32 bit.
    • AND, ANDI And, And immediate
    • OR, ORI, XOP, XOPI Or, or immediate, exclusive or, exclusive or immediate
    • LHI Load high immediate - carica nella parte alta del registro il dato immediato
    • SLL, SRL, SRA, SLLI, SRLI, SRAI Shifts: sia immediato(S__I) che variabile (S__); gli shift sono Shift Left Logical, Right Logical, Right Arithmetic
    • S__, S__I, S__U Set condizionati: "__" può essere LT lesse than, GT greather than, LE less-equal, GE greater-equal, EQ equal, NE not equal
  • Controllo
    • BEQZ, BNEZ Branch GPR equal/not equal to zero; 16-bit offset from PC
    • BFPT, BFPF Test comparison bit in the FP status register and branch; 16-bit offset from PC
    • J, JR Jumps: 26-bit offset from PC(J) or target in register(JR)
    • JAL, JALR Jump and link: save PC+4 to R31, target is PC-relative(JAL) ot a register(JALR)
    • TRAP Transfer to operating system at a vectored address
    • RFE Return to user code From an Exception; restore user code
  • Virgola Mobile
    • ADDD, ADDF Add DP, numeri SP
    • SUBD, SUBF Subtract DP, numeri SP
    • MULTD, MULTF Multiply DP, SP floating point
    • DIVD, DIVF Divide DP, SP floating point
    • CVTF2D, CVTF2I, CVTD2F,
    • CVTD2I, CVTI2F, CVTI2D Istruzioni di Conversione: CVTx2y converte dal tipo x al tipo y, dove x e y sono I(Integer), D(Double precision), o F(Single precision). Entrambi gli operandi sono nel registro FP
    • __D, __F confronti DP e SP: "__" può essere LT, GT, LE, GE, EQ, NE; impostare il bit di paragone nel registro FP.

Istruzioni aritmetiche e logiche

Sono istruzioni a tre operandi, il primo è il registro destinazione, gli altri due registri sorgente

Ad esempio ADD R1, R2, R3 eseguel l'operazione R1 = R2 + R3 ADDI R1, R0, 100 esegue R1 = 100 (R0 vale sempre 0 e non è modificabile) ADD R1, R2, R0 esegue R1 <- R2 (assegna ad R1 il valore di R2)

Le istruzioni di set condizionato ( S__ ) eseguono un confronto tra i due operando sorgente ed assegnano il valore 0 oppure 1 a seconda del risultato del contronto, per cui

SNE R1, R2, R3 assegnerà il valore 1 ad R1 se R2 ed R3 non sono uguali, in caso contrario assegnerà il valore 0

Le operazioni di confronto possono essere eseguite anche tra un registro e un operando immediato

SLTI R1, R2, 10 assegna 1 ad R1 se R2 è più piccolo di 10

o tra operandi senza segno (e non in complemento a due)

SGTU R1, R2, R3 assegna 1 ad R1 se R2 è più grande di R3


Istruzioni di trasferimento dati

Dato che il DLX è un Instruction Set R-R prima di utilizzare dei valori presenti in memoria deve copiarli in un registro interno alla CPU per questo motivo esistono operazioni di prelievo e scrittura di dati da e verso la memoria.

Sono istruzioni codificate nel formato I per cui richiedono tre operandi espliciti, nella forma destinazione, offset(registro). L'indirizzo di memoria a cui accedere sarà calcolato come la somma del valore in registro e dell' offset, ad esempio

LW R1, 100(R2) preleva una parola ( Load Word ) di trentadue bit dall'indirizzo di memoria 100 + R2 e memorizzala in R1, operazione che si può anche scrivere come R1 <-32 M[100+R2]

Analogamente SW R1, 20(R3) salverà nell'indirizzo di memoria 20 + R3 la parola (Store Word) contenuta nel registro R1


Istruzioni di trasferimento del controllo

Nel DLX queste istruzioni sono di tre tipi:

  • Jump Effettua un salto, un trasferimento del controllo, incondizionato
  • Jump And Link Trasferisce il controllo salvando l'indirizzo di ritorno nel registro R31 (si parla anche di chiamata a procedura)
  • Branch Trasferisce il controllo soltanto dopo aver verificato una condizione ( salto condizionato )

Le istruzioni di Jump e Jump And Link possono essere sia di tipo I che J

Jump con istruzione di tipo I

J R3 Modifica il program counter con il valore del registro R3, PC <- R3

Jump And Link con instruzioni di tipo I

JALR R3 Salva l'indirizzo della prossima istruzione nel registro R31 e assegna al program counter il valore di R3, ovvero R31 <- (PC + 4) ; PC <- R3

Jump con istruzione di tipo J Le istruzioni di tipo J usano un solo operatore di offset da 26 bit

J alfa Salta all'operazione nell'indirizzo di memoria distante alfa dalla prossima istruzione da eseguire, PC <- (PC + 4) + alfa

Jump And Link con istruzione di tipo J

JAL alfa Si comporta come l'operazione di Jump, ma salvando l'indirizzo della prossima istruzione del registro R31, R31 <- (PC + 4); PC <- (PC + 4) + alfa


L'operazione di ritorno da una procedura è JR R31 Assegna al program counter il valore che un'istruzione di Jump And Link ha memorizzato in R31, PC <- R31


Le operazioni di Branch invece possono essere soltanto di tipo I, l'OP code definisce il tipo di controllo da eseguire prima di effettuare il salto, il primo operatore è il registro su cui fare questo controllo, il secondo è l'offset di 16 bit relativo, come nei casi precedenti, ad program counter, per cui

BNEZ R3, alfa Salta all'istruzione nell'indirizzo di memoria (PC + 4) + l'offset alfa soltanto se R3 non è uguale a zero (Branch Not Equal to Zero), in altri termini if (R3 != 0) : PC <- (PC + 4) + alfa


Esempi di codice in assembler per una macchina R-R

Somma degli elementi di un vettore A di 8 elementi

Se si utilizzano i seguenti registri per

  • R1 per la somma corrente
  • R2 per l’indice
  • R3 per il contatore delle iterazioni

Il codice si può scrivere

    ADD       R1, R0, R0             ; azzera la somma corrente
    ADD       R2, R0, R0             ; R2 vale indice * 4 (4 e’ numero byte per word)
    ADDI      R3, R0, 8              ; inizializza il contatore   
    
 CICLO   LW    R4, A(R2)             ; indirizzo dell’operando in memoria calcolato a run time
    ADD        R1, R1, R4            ; aggiorna somma corrente
    ADDI       R2, R2, 4      
    ADDI       R3, R3, -1
    BNEZ       R3, CICLO
    SW         Z(R0), R1             ; Z e’ la variabile con il risultato

Ovviamente si può sostituire ADDI R3,R3,-1 con SUBI R3,R3,1

Creazione di uno Stack pointer che supporti l'aanidamento

Abbiamo visto che il DLX non supporta l'annidamento ( nesting ) delle chiamate a procedura poichè non ha un stack ed utilizza come unito registro di rotorno R31, con questo codice si può implementare via software uno stack pointer con il registro R30. R30 rappresenta l'indirizzo dell'ultima word di 32 bit (4 byte) inserita nello stack, per cui decresce man mano che lo stack si riempie e cresce man mano che si svuota.

Le prime due istruzioni vanno aggiunte prima delle istruzioni della procedura e servono per memorizzare il valore di R31 (indirizzo di ritorno dalla procedura) nello stack implementato grazie al registro R30

  SUBI     R30, R30, 4             ; Decrementa lo stack
  SW       0(R30), R31             ; Salva nell'indirizzo di memoria il valore di R31

... istruzioni della procedura ...

Al termine della procedura sono necessarie alcune righe aggiuntive per permettere il ritorno all'istruzione mappana nell'ultimo indirizzo di memoria dello stack pointer

  LW       R31, 0(R30)             ; Preleva l'indirizzo a cui fare ritorno
  ADDI     R30, R30, 4             ; Incrementa lo stack visto che sto uscendo dalla procedura
  JR       R31


Gestione di word (32 bit)

Supponiamo di voler copiare un vettore di 1K word (32 bit) memorizzato all’indirizzo 1000H in un vettore di identico formato memorizzato all’indirizzo 40001000H. Le istruzioni del DLX permettono operandi (immediati) al massimo di 16 bit per cui si usino le istruzioni

LHI Rx, IMMEDIATE (Load High Immediate), che carica nella parte alta (16 bit più significativi) del registro destinazione Rx una costante a 16 bit ed azzera la parte bassa (16 bit meno significativi) di tale registro

ORI Rx, IMMEDIATE (OR Immediate) scrive in Rx il valore IMMEDIATE senza estenderlo (corrispondere a scrivere soltanto i 16 bit meno significativi)


    ADDI      R1,R0,1000H        ; Inizializza R1 per leggere il vettore dal suo ultimo elemento ( 1000H - 4 )
    LHI       R2,4000H           ; Costruisci R2 come l'indirizzo di memoria su cui salvare il vettore
    ORI       R2,R2,2000H        ; che andrà da 40001000H a (40002000H -4 )essendo da 1K word
 LOOP: SUBI   R1,R1,4            ; decrementa R1
    LW        R3,1000H(R1)       ; carica la parola all'ultimo indirizzo del vettore
    SUBI      R2,R2,4            ; decrementa anche R2
    SW        0(R2),R3           ; Memorizza la parola nell'indirizzo di R2
    BNEZ      R1,LOOP            ; Dopo 1K word il valore di R1 è decrementato fino ad arrivare a 0


Massimo di un vettore di unsigned-word (32 bit)

Si scriva una procedura che ricevendo in ingresso i parametri R1 : registro con l'indirizzo del vettore R2 : dimensione del registro (numero di elementi) R3 : registro usato dalla procedura per memorizzare il valore massime del vettore di unsigned-word


 PROC: ADD     R3,R0,R0     ; inizializzazione del massimo corrente, per ora a 0
 LOOP: LW      R4,0(R1)     ; lettura dalla memoria dell’i-esima word
       SGTU    R5,R4,R3     ; confronto con il massimo corrente
       BEQZ    R5,SKIP      ; “skip” se word corrente è minore del massimo corrente
       ADD     R3,R4,R0     ; aggiornamento del massimo corrente ( solo se BEQZ non effettua il salto di "skip")
 SKIP: ADDI    R1,R1,4      ; incremento del puntatore alla word successiva ( 1 word = 4 byte )
       SUBI    R2,R2,1      ; decremento del contatore delle iterazioni
       BNEZ    R2,LOOP      ; verifica che ci siano altri elementi da processare
       JR      R31          ; ritorno al programma chiamante


Datapath sequenziale

La funzione fondamentale dell'unità di controllo è la lettura degli operandi dal banco dei registri (R0 - R31), la loro trasformazione all'interno della ALU e la rimemorizzazione del risultato.

Il processore DLX utilizza tre bus: S1, S2, e Dest, i primi due sono di ingresso per la alu e sono pilotati dai registri dell'unità di calcolo, il bus Dest, invece, funziona come uscita per la ALU e ingresso per i registri.

Dato che il banco dei registri non viene letto o scritto ad ogni ciclo di clock per velocizzare queste operazioni nell'unità di controllo sono presenti degli elementi di memoria alle due uscite del banco di registri (elementi A e B) ed uno in ingresso ( C )

Oltre ai 32 registri già visti vi sono anche i registri:

  • PC: Program counter o contatore di programma
  • IAR: registro di indirizzamento delle interruzioni, registro che fa parte dello stato della macchina
  • MAR: registro di indirizzamento della memoria,
  • MDR: registro di lettura e scrittura della memoria,
  • IR: registro delle istruzioni
  • Temp: registro temporaneo detto a perdere perchè è disponibile per la memorizzazione dei dati intermedi durante l'esecuzione di alcune istruzioni del DLX.


Fasi di esecuzione delle istruzioni

Le istruzioni tipiche del DLX viste nei paragrafi precedenti sono tutte eseguite in più cicli di clock, volendo scomporre ogni istruzione in micro-operazioni si osserva come tutte le operazioni del DLX ( ad esclusione di quelle in virgola mobile) siano scomponibili in cinque fasi findamentali:

  • prelievo dell'istruzione
  • decodifica
  • esecuzione ed indirizzamento
  • accesso alla memoria
  • scrittura del risultato

Prelievo dell'istruzione

Il Datapath, a partire dal valore del PC, preleva l'istruzione da eseguire dalla memoria scrivendola nel registro delle istruzioni:

  MAR <- PC;  
  IR <- M[MAR]

Il contenuto del PC deve essere trasferito nel MAR visto che soltanto quest'ultimo è collegato alla memoria, mentre il PC non lo è

Decodifica

Viene decodificata l'istruzione e contemporaneamente si accede al banco dei registri per leggerli, i valori dei registri saranno salvati nei due elementi di memoria, viene inoltre incrementato il PC

  A <- Rs1;
  B <- Rs2;
  PC <- PC + 4

La decodifica dell'operazione può avvenire in parallelo con la lettura dai registri soltanto perchè la posizione dei registri sorgente all'interno di una istruzione DLX è fissa dopo i 6 bit del codice operativo, si parla di decodifica a campi fissi. Per lo stesso motivo anche l'estensione in segno del valore immediato viene effettuata in questa fase qualora l'istruzione contenga un valore immediato

Esecuzione e indirizzamento

L'ALU elabora gli operandi decodificati nella fase precedente eseguendo una delle possibili funzioni:

Riferimento alla memoria

L'ALU calcola l'indirizzo effettivo della cella di memoria e viene inizializzato il registro MDR per un'operazione di memorizzazione

  MAR <- A + (IR16)16##IR16..31
  MDR <- Rd

Funzione dell'ALU

L'ALU esegue l'operazione specificata dal codice operativo con operandi Rs1 (A) e Rs2 (B) oppure con il valore immediato esteso di segno

 C <- A op ( B or (IR16)16##IR16..31 )


Diramazione o salto

L'ALU calcola l'indirizzo del salto sommando al PC il valore immediato esteso in segno, viene anche controllato un registro per decidere se l'indirizzo va caricato o meno nel PC ( è il caso delle diramazioni )

  C <- PC + (IR16)16##IR16..31;
  cond <- (A op 0)

op è l'operatore di relazione specificato dal codice operativo ( BEQZ -> op = EQual ovvero "==" ) Le istruzioni JAL e TRAP sono simili a qualla descritta ma in più memorizzano l'indirizzo di ritorno rispettivamente in R31 e IAR.


Accesso alla memoria

Questa fase è attraversata soltanto dalle istruzioni di caricamento, memorizzazione, salti e diramazioni.

Caricamento

Se richiesto l'accesso in memoria il datapath preleva i dati all'indirizzo calcolato in precedenza

  MDR <- M[MAR]

Memorizzazione

Se l'istruzione è una memorizzazione i dati vengono scritti

  M[MAR] <- MDR

Diramazione / Salto

Se si verifica la condizione calcolata nella fase precedente il contenuto del PC viene sostituito con l'indirizzo di destinazione della diramazione

  if (cond) PC <- C

Per i salti incondizionati cond è sempre vera


Scrittura del risultato

Il risultato in uscita alla ALU viene scritto nel banco dei registri, sia che provenga dalla memoria

  Rd <- MDR

che dalla ALU

  Rd <- C

Unità di controllo per il DLX

L'unità di controllo è la parte della CPU che si occupa di indicare all'unità di calcolo le micro-operazioni da eseguire ad ogni ciclo di clock durante l'esecuzione delle istruzioni.


Solitamente si usa un diagramma a stati finiti per specificare le attività svolte dall'unità di calcolo, in questo diagramma ogni stato corrisponde ad un ciclo di clock e le operazioni eseguite sono inserite all'interno dello stato.



La prima fase di esecuzione di una istruzione è distribuita nei primi tre stati del diagramma.

La seconda fase viene eseguita nel terzo stato


  • durante il primo ciclo di clock il valore del PC viene caricato nel registro di indirizzamento della memoria,
  MAR <- PC
  • nel secondo stato il registro delle istruzioni viene caricato dalla memoria
  IR <- M[MAR]
  • nel terzo stato viene incrementato il PC e vengono, durante lo stesso ciclo di clock, caricati i due operandi dei registri Rs1 e Rs2 in A e B
  PC <- PC + 4
  A <- Rs1
  B <- Rs2

Lo stato successivo del diagramma differisce a seconda che si stia facendo un trasferimento dati, un'operazione ALU, una inizializzazione un salto o diramazione

Si possono anche rappresentare i primi due stati con uno solo

  IR <- M[PC]

ricordando che in condizioni ideali l'operazione richiede due cicli di clock.

I clock necessari per eseguire l'operazione di caricamento del registro IR dipendo fortemente dai tempi di accesso alla memoria, che possono richiedere più di un clock, per cui si indica il primo stato come stabile su se stesso fintanto che l'accesso alla memoria è incompleto


Controller per le istruzioni di memoria

Sia per le istruzioni di caricamento che memorizzazione il primo stato (dopo i tre comuni a tutti i controller visti prima) è

  MAR <- A + (IR16)16 ## IR16..31

viene quindi calcolato il registro di indirizzamento alla memoria, la fase successiva differisce a seconda che si tratti di

controller Caricamento

  MDR <- M[MAR]

Viene prelevata l'informazione dalla memoria e

  C <- MDR

inserita nell'elemento di memoria C, quest'ultima operazione si riferisce al casi di Load Word, infatti il MDR conterrà 32 bit, se l'operazione di caricamento opera con Half Word, Byte o dati diversi si selezionano dal MDR soltanto i bit richiesti

  LB     C <- (MDR24)24 ## MDR24..31
  LBU    C <- (0)24 ## MDR24..31
  LH     C <- (MDR16)16 ## MDR16..31
  LHU    C <- (0)16 ## MDR16..31

Al successivo clock il valore dell'elemento di memoria riempie il registro di destinazione

  Rd <- C

Dopo questa micro-operazione il diagramma degli stati ritorno all'inizio con il prelevamento di una istruzione dalla memoria

controller Memorizzazione

  MDR <- B

Il dato da memorizzare viene inserito nell'apposito registro

  M[MAR] <- MDR

e scritto in memoria all'indirizzo precedentemente calcolato, questo stato è stabile fino a che l'accesso in memoria non sia completo, può quindi richiedere più clock

Controller per le istruzioni ALU

Nelle istruzioni ALU l'operazione indicata dall'op code viene eseguita tra l'elemento di memoria A e il registro Temp, per cui il primo blocco consiste nel riempire questo registro con il secondo elemento di memoria ( B ) se si tratta di una operazione tra registri, andrà invece riempito con l'immediato (esteso di segno a 32 bit) se l'operazione da eseguire è di tipo I

  Registro                Temp <- B
  Immediato               Temp <- IR0..15##(IR15)16
  Immediato senza segno   Temp <- IR0..15 ## (0)16

Dopo di che viene eseguita la micro-operazione corrispondente al codice operativo specificato

  ADD    C <- A + Temp
  AND    C <- A & Temp
  SUB    C <- A - Temp
  OR     C <- A | Temp

Ed il risultato viene scritto sul registro destinazione

  Rd <- C

Controller per l'istruzione di salto

JR

  PC <- A

Essendo un'istruzione di ritorno deve solo aggiornare il PC

J

  PC <- PC + IR0..25 ## (IR25)6

Modifica il program counter con l'immediato

JAL

  C <- PC
  PC <- PC + IR0..25 ## (IR25)6
  R31 <- C

Prima di sovrascrivere il PC ne salva il valore in R31

JALR

  C <- PC
  PC <- A
  R31 <- C

Controller per l'istruzione di inizializzazione

O anche istruzioni di set

La prima micro-operazione è la copia nel registro Temp del valore del secondo operando

  Registro    Temp <- B
  Immediato   Temp <- IR0..15 ## (IR15)16

Al successivo ciclo di clock viene eseguita l'operazione di confronto, per cui

  SEQ      A == Temp
  SNEQ     A != Temp
  SLT      A < Temp
  SGE      A >= Temp
  SGT      A > Temp
  SLE      A <= Temp

Nel diagramma degli stati a questo punto si ha una diramazione a seconda del risultato del precedente confronto

  vero     C <- 1
  falso    C <- 0

L'ultima operazione è quella di scrivere il contenuto di C nel registro destinazione

  Rd <- C

Controller per l'istruzione di branch

I branch sono di due tipi

  BEQZ    A == 0
  BNEZ    A != 0

E la diramazione che ne segue comporta il ritorno all'inizio del datapath in caso di esito negativo, oppure di aggiornamento del PC in caso di esito positivo

  PC <- PC + IR0..15 ## (IR15)16

Altri esempi di controller

Supponiamo di voler creare una nuova istruzione DLX del tipo

  CMPS Rx, Ry, Rz

L'istruzione confronta il dato di tipo unsigned byte situato in memoria all'indirizzo Rx con quello all'indirizzo Ry e pone Rz a 1 se i due dati sono uguali

Una descrizione RTL delle operazioni svolte dalla nuova istruzione è data da:

 if (M[Rx] = M[Ry])
    then Rz <- 1
    else Rz <- 0;

Il controller (datapath) di questa nuova istruzione, compresi gli stati di fetch e decodifica, sarà

  IR <- M[PC]                ; fetch dell'istruzione
  A <- Rx
  B <- Ry                    ; decodifica
  PC <- PC + 4               
  MAR <- A                   ; preparo il registro di accesso alla memoria
  MDR <- M[MAR]              ; ed accedo
  Temp <- MDR0..7 ## (0)24   ; Salvo soltanto i primi 8 bit (unsigned byte) nel registro temporaneo
  MAR <- B                   ; e mi preparo a prelevare anche B
  MDR <- M[MAR]              ; lo prelevo
  Temp == MDR0..7 ## (0)24   ; e lo confronto con temp
  uguali   C <- 1      ; se i dati prelevati dalla memoria sono uguali
  diversi  C <- 0      ; oppure diversi, l'unità di calcolo eseguirà solo una delle due istruzioni
  Rz <- C                    ; scrivo il valore calcolato nel registro destinazione

Ogni blocco rappresenta un ciclo di clock, ad esclusione di quelli che accedono alla memoria per i quali la durata dipende dal tempo di accesso alla memoria

Numero di clock necessari per eseguire le istruzioni

Il numero di cicli di clock per eseguire una qualsiasi istruzione del DLX si ottiene contando gli stati del controller per ogni istruzione, il valore reale dipende poi dal numero e dalla durata degli accessi alla memoria, la seguente tabella riassume il numero di cicli di clock e il numero degli accessi alla memoria per le istruzioni del DLX nel caso in cui l'accesso alla memoria duri 1 clock


Istruzione Numero minimo

di clock

Accessi alla

memoria

Caricamento
6
2
Memorizzazione
5
2
ALU
5
1
Inizializzazione
6
1
Jump
3
1
Jump and link
5
1
Branch taken

(eseguito)

4
1
Branch not taken
3
1

Qualora l'accesso alla memoria duri più cicli di clock, questi andrebbero moltiplicati al numero di accessi alla memoria e sommati al numero minimo di cicli di clock, in questo caso si parla di cicli di stallo della memoria o stati di attesa o wait. In macchine dotate di cache i cicli di wait valgono zero ( l'accesso alla memoria cache richiede quindi un solo clock )

Calcolo del CPI

Supponiamo di avere un programma che esegue le seguenti operazioni con frequenza relativa:

Caricamento 21 %

Memorizzazione 12 %

ALU 37 %

Inizializzazione 6 %

Jump 2 %

Jump an link 0 %

Branch taken 12 %

Branch not taken 11 %

Il CPI medio, ricordando la formula data nel primo capitolo, si ottiene sommando i prodotti tra il CPI di ogni istruzione (secondo la tabella sopra riportata e gli stati di wait) e la sua frequenza relativa, in questo esempio il CPI medio risulta 6,28

8086

L'Intel 8086 nasce come un'estensione del 8080, una macchina ad accumulatore. E' quindi sostanzialmente un ibrido, perché pur avendo 14 registri, nessuno di questi è ad uso generale in quanto ognuno ha un uso ben specifico.

L'architettura è a 16 bit così come i registri, ma per ottenere un'indirizzabilità maggiore i progettisti hanno aggiunto dei segmenti che estendono lo spazio di indirizzamento a 20 bit.

Fanno parte della stessa famiglia, sono quindi molto simili, i processori 80186, 80286 (indirizzamento a 24 bit), 80386 (indirizzamento e parallelismo a 32 bit), 80486 (poche novità rispetto all'80386 ma con prestazioni notevolmente migliorate).


Registri e indirizzamento

Un indirizzo a 20 bit si ottiene da un indirizzo effettivo a 16 bit (offset, registro di indirizzo) sommandogli un indirizzo base a 20 bit, con lo scorrimento verso sinistra di quattro posizioni del contenuto di un registro segmento a 16 bit.


I 14 registri dell'8086 sono raggruppabili in 4 categorie: Dato, Indirizzo, Segmento e Controllo.

  • Dato: Usati per mantenere dati o per operare su di essi:
    • AX Usato per moltiplicazioni, divisioni, I/O o operando implicito.
    • BX Può essere un registro per contenere l'indirizzo base.
    • CX Usato per le operazioni tra stringhe o istruzioni di ciclo.
    • DX Usato per moltiplicazioni, divisioni e I/O.
  • Indirizzo: Usati per formare un indirizzo effettivo di memoria a 16 bit (interno al segmento):
    • SP Puntatore alla sommità dello stack.
    • BP Registro base: usato nell'indirizzamento tramite base.
    • SI Registro indice: usato anche come base per l'indirizzo di una stringa.
    • DI Registro indice: usato anche come base per l'indirizzo di destinazione di una stringa.
  • Segmento: Usati per costruire indirizzi di memoria a 20 bit:
    • CS Segmento di codice: è usato per gli accessi alle istruzioni.
    • SS Segmento dello stack: è usato per i riferimenti allo stack.
    • ES Segmento aggiuntivo: usato per le operazioni destinate a una stringa.
    • DS Segmento dati: usato per tutti gli altri casi.
  • Controllo: Usati per il controllo dello stato e del programma:
    • IP Instruction Pointer: fornisce l'offset dell'istruzione corrente in esecuzione (16 bit meno significativi del PC).
    • FLAGS Contiene 6 bit relativi alle condizioni (riporto, zero, segno, prestito, parità e overflow) e 3 bit per il controllo dello stato.


Le istruzioni ALU sono di tipo Memory-Register (2,1) e consentono l'uso di un operando immediato.

Le modalità di indirizzamento sono

  • Registro indiretto: BX, SI, DI.
  • Base + offset a 8 o 16 bit: BP, BX, SI, DI.
  • Indicizzato: l'indirizzo è la somma di due registri BP+SI, BP+DI, BX+SI, BX+DI.
  • Indicizzato + offset a 8 o 16 bit: l'indirizzo è la somma dell'offset con il contenuto di due registri.

Operazioni

Possono essere suddivise in quattro categorie:

  • Trasferimento dati, comprendono spostamenti (move), inserimento (push) ed estrazione (pop) di dati dallo stack.
  • Istruzioni ALU
  • Istruzioni di controllo del flusso, comprendono le diramazioni con e senza condizione, le chiamate e i ritorni dalle chiamate (l'utilizzo dello stack piuttosto che un registro come nel DLX permette il nesting-annidamento delle chiamate a procedura)
  • Istruzioni su stringhe, come spostamento e confronto.

Alcune delle istruzioni tipiche sono:

  • Trasferimento dati
    • MOV Sposta un dato tra due registri o tra un registro e la memoria
    • PUSH Metti un operando nello stack
    • POP Leggi un operando dallo stack e mettilo in un registro
    • LES Carica ES e uno dei GPR dalla memoria
  • Istruzioni ALU
    • ADD Addizione tra operando sorgente e operando destinazione
    • SUB Sottrazione dell'operando sorgente da quello di destinazione
    • CMP Confronto tra operando sorgente e destinazione
    • SHL,SHR Scorrimento logico rispettivamente a sinistra e a destra
    • RCR Rotazione a destra attraverso il riporto
    • CBW Conversione di un byte in AL in una parola AX
    • TEST And logico tra le configurazione dei flag sorgente e distinazione
    • INC,DEC Incremento o decremento dell'operando destinazione
    • OR OR logico
    • XOR OR esclusivo
  • Controllo
    • JNZ,JZ Salta se è verificata la condizione IP + 8 bit di offset (in alternativa anche JN e JE)
    • JMP,JMPF Salto non condizionato
    • CALL,CALLF Chiamata a subroutine, l'indirizzo di ritorno è inserito nello stack
    • RET,RETF Leggi dallo stack l'indirizzo di ritorno e salta ad esso
    • LOOP Diramazione di ciclio: decrementa CS, se diverso da zero salta a IP + 8 bit di offset.
  • Istruzioni su stringhe
    • MOVS Copia la stringa sorgente in quella destinazione
    • LODS Carica un byte o una parola di stringa nel registro A.

Per le istruzioni di stringa esiste un prefisso di ripetizione, questo significa che l'operazione deve essere ripetuta tante volte quanto indicato dal valore nel registro CX.

Le istruzioni di controllo di flusso devono essere in gradi di gestire sia trasferimenti vicini (all'interno del segmento di memoria indirizzabile con i 16 bit del registro) sia trasferimenti lontani (suffisso F, segmenti che richiedono indirizzi a 20 bit). Nei salti lontani all'OpCode seguono due quantità da 16 bit, una di queste è il puntatore all'istruzione, l'altra è caricata in CS e diventa il nuovo codice di segmento. Un ritorno lontano legge dalla cima dello stack sia il puntatore all'istruzione, sia il codice di segmento.

La codifica delle istruzione dell'8086 è piuttosto complessa e presenta diversi formati che possono variare a da uno a sei byte. Inoltre molte delle istruzioni contengono un campo da un bit w che specifica se l'operazione è di un byte o di una parola (2 byte). Alcune istruzioni contengono insieme con l'OpCode la modalità di indirizzamento e il registro, altre istruzioni ancora usano un byte aggiuntivo, il postbyte, con le informazioni sulla modalità di indirizzamento (è usato spesso per le istruzioni che indirizzano la memoria)


Appendici

Le velocità di ogni tipo di connessione interna ed esterna al personal computer

Riassunto

Componenti notevoli

EPROM
File:Eprom.png

Una Eprom è un dispositivo di memoria statica che deriva il suo nome dalle sue caratteristiche principali: Eraseable Progammable Read Only Memory. Ovvero Cancellabile, programmabile, leggibile. La programmazione di una EPROM avveniva infatti una sola volta, e comunque non era così facile aggiornare il programma contenuto in una EPROM, poiché la cancellazione avveniva solo tramite l'uso di una luce a raggi ultravioletti. Oggi le cose sono molto diverse. Non esistono più solo EPROM ma anche EEPROM ovvero Electrically Eraseable PROM, che sarebbero EPROM che possono essere cancellate e riprogrammate atraverso impulsi elettrici inviati ad alcune porte del chip.

Caratteristiche delle EPROM:

  • La capacità va a potenze di 2: 32k, 64k, 128k, 256k, ...
  • Le sigle sono del tipo 27xxx, con xxx indicante le dimensioni in Kbits

Porte del chip:

  • GND - porta a massa
  • VCC - porta da connettere all'alimentazione
  • A0 .. A16 - porte degli ingressi
  • D0 .. D7 - porte delle uscite
  • CE* - Chip Enable, porta che permette di accendere il chip solo quando serve.
  • OE* - Output Enable, porta che permette ai dati di essere letti
  • PGM* - Porta che consente ad un programmatore di inserire i dati nella EPROM. Spenta questa porta tutte le altre diventano porte programmabili.
Ram

La Ram, Random Access Memory, è il dispositivo di memoria rapida del calcolatore. Al contrario della EPROM deve essere sia leggibile che, soprattutto, scrivibile in tempi molto ristretti. Esistono due tipi di RAM costruiti in modo completamente diverso. La SRAM, ovvero Static RAM, è composta da Flip-Flop che mantengono memorizzati i dati. Il tempo di accesso è minimo, ma la capacità è minore rispetto alle DRAM. Queste, Dynamic RAM, sono composte da transistor di tipo MOS. La capacità aumenta, ma la velocità di accesso è minore.

File:Ram logic.png

La struttura logica interna di una RAM è comunque comune ad entrambi i tipi di RAM. L'aspetto fondamentale è nel doppio uso del bus di dati che in caso di scrittura porta il dato da scrivere, mentre in caso di lettura porta il dato letto. Questo attraverso un intelligente uso di un buffer tri-state.

Caratteristiche della RAM

  • Capacità a potenze pari di 2
  • Sigla: 62xxx

Porte del chip:

  • GND - a massa
  • VCC - Tensione di alimentazione
  • CE* - Chip Enable - accensione del chip di RAM
  • OE* - Output Enable - va a zero nel momento della lettura
  • WE* - Write Enable - va a zero nel momento della scrittura
  • A0 .. A16 - Indicatori della posizione della casella di memoria
  • I/O0 .. I/O7 - Dati in uscita o ingresso
74xx244
File:74xx244.png

Questo Circuito integrato consiste in un insieme di 2 gruppi di three-state buffer da quattro bit ciascuno. Ogni gruppo è comandato indipendentemente dall'altro.

Porte dell'integrato:

  • ENx* - abilita il gruppo x di three-state buffer
  • xA1 .. xA4 - Bit in ingresso da abilitare o portare a stato di alta impedenza
  • xY1 .. xY4 - output del buffer three-state
74xx245
File:74xx245.png

Un integrato come il precedente è utile, ma spesso può essere necessario abilitare alternativamente sullo stesso canale sia ingresso che uscita. Per minimizzare lo spazio necessario per un tal genere di esigenza esiste l'integrato 245. Questo si compone di una coppia di three-state buffer in direzioni opposte aperti alternativamente attraverso un comando DIR. Una struttura come questa è detta transceiver. La struttura logica è per il resto sostanzialmete identica alla precedente.

DLX

Formato operazioni

Ogni OpCode è composto di 6 bit, ogni indirizzo di 5, mentre i restanti bit sono eventualmente per offset o altri tipi di input. Le tre grandi famiglie di comandi sono:

Formato I
Formato I

Formato I: E' quello utilizzato per ogni operazione con operatori immediati. Come si nota l'offset è di soli 16 bit, il che significa che non si può passare come argomento direttamente un dato a 32 bit, bensì bisogna suddividerlo in due passaggi con in mezzo uno shift di 16 posizioni.

Formato R
Formato R

Formato R: Questo è il formato delle operazioni fra registri. Gli 11 bit finali vengono utilizzati per rendere più specifiche alcune operazioni (ricordiamo che essendoci solo 6 bit per le operazioni, il numero massimo di queste è )

Formato J
Formato J

Formato J: Quest'ultimo è il formato dei salti condizionati o meno.

Operazioni
  • Trasferimenti di dati
    • LB, LBU, SB Load byte, load byte unsigned, store byte
    • LH, LHU, SH Load halfword, load halfword unsigned, store halfword
    • LW, SW Load word, store word (a/da registri integer)
    • LF, LD, SF, SD Load SP float, load DP float, store SP float, store DP float (SP - single precision, DP - double precision)
    • MOVI2S, MOVS2I Move from/to GPR to/from a special register
    • MOVF, MOVD Copy one floating-point register or a DP pair to another register or pair
    • MOVFP2I, MOVI2FP Move 32 bits from/to FP tegister to/from integer registers
  • Aritmetica/Logica
    • ADD, ADDI, ADDU, ADDUI Add, add immediate (tutti gli immediati sono a 16 bit); signed and unsigned
    • SUB, SUBI, SUBU, SUBUI Subtract, subtract immediate; signed and unsigned
    • MULT, MULTU, DIV, DIVU Multiply and divide, signed and unsigned; Gli operandi devono essere registri Floating-point; Tutte le operazioni richiedono valori a 32 bit e danno come risultato valori a 32 bit.
    • AND, ANDI And, And immediate
    • OR, ORI, XOP, XOPI Or, or immediate, exclusive or, exclusive or immediate
    • LHI Load high immediate - carica nella parte alta del registro il dato immediato
    • SLL, SRL, SRA, SLLI, SRLI, SRAI Shifts: sia mmediato(S__I) che variabile (S__); gli shift sono Shift Left Logical, Right Logical, Right Arithmetic
    • S__, S__I Set condizionati: "__" può essere LT, GT, LE, GE, EQ, NE
  • Controlli
    • BEQZ, BNEZ Branch GPR equal/not equal to zero; 16-bit offset from PC
    • BFPT, BFPF Test comparison bit in the FP status register and branch; 16-bit offset from PC
    • J, JR Jumps: 26-bit offset from PC(J) or target in register(JR)
    • JAL, JALR Jump and link: save PC+4 to R31, target is PC-relative(JAL) ot a register(JALR)
    • TRAP Transfer to operating system at a vectored address
    • RFE Return to user code From an Fxception; restore user code
  • Floating point
    • ADDD, ADDF Add DP, numeri SP
    • SUBD, SUBF Subtract DP, numeri SP
    • MULTD, MULTF Multiply DP, SP floating point
    • DIVD, DIVF Divide DP, SP floating point
    • CVTF2D, CVTF2I, CVTD2F,
    • CVTD2I, CVTI2F, CVTI2D Istruzioni di Conversione: CVTx2y converte dal tipo x al tipo y, dove x e y sono I(Integer), D(Double precision), o F(Single precision). Entrambi gli operandi sono nel registro FP
    • __D, __F confronti DP e SP: "__" può essere LT, GT, LE, GE, EQ, NE; impostare il bit di paragone nel registro FP.