Assembly Base con MASM

Capitolo 7: L'architettura generale del computer


Come è stato spiegato in un precedente capitolo, sin dall'antichità gli esseri umani hanno cercato di realizzare macchine capaci di svolgere in modo automatico calcoli più o meno complessi; un esempio famoso è rappresentato dalla calcolatrice meccanica di Pascal (1642) che attraverso un sistema di ingranaggi era in grado di eseguire semplici addizioni. Un altro esempio famoso è rappresentato dalle macchine calcolatrici realizzate dal matematico Charles Babbage a partire dal 1822; queste macchine, formate da ingranaggi, cinghie, pulegge, catene di trasmissione, etc, divennero via via sempre più evolute sino a permettere il calcolo di equazioni differenziali. Il caso delle macchine di Babbage assume una importanza enorme nella storia del computer in quanto questo scienziato aveva capito che se una macchina è in grado di svolgere un determinato calcolo, allora può essere progettata in modo da svolgere qualsiasi altro calcolo; il ragionamento di Babbage venne dimostrato matematicamente parecchi anni dopo da Alan Turing. Si può dire che Babbage aveva intuito con più di un secolo di anticipo l'idea fondamentale su cui si basano gli odierni calcolatori elettronici; questo scienziato non riuscì però a mettere in pratica le sue teorie in quanto la tecnologia disponibile nel XVIII secolo per la realizzazione di queste macchine era esclusivamente di tipo meccanico.

Le considerazioni appena esposte ci fanno capire che le prime macchine di calcolo automatico presentavano una architettura piuttosto rigida che permetteva loro di eseguire un numero limitato di operazioni; le istruzioni di elaborazione, infatti, venivano incorporate (cablate) direttamente nei meccanismi della macchina stessa e ogni volta che si presentava la necessità di eseguire un calcolo differente, bisognava progettare una nuova macchina o, nella migliore delle ipotesi, bisognava modificarne la struttura interna.
Le macchine calcolatrici di questo tipo vengono definite a logica cablata e presentano come principale difetto la scarsissima flessibilità; il pregio fondamentale di una macchina a logica cablata è rappresentato, invece, dalla elevatissima velocità di calcolo.

7.1 La macchina di Von Neumann

All'inizio del XIX secolo, nel mondo delle macchine di calcolo automatico è iniziata una autentica rivoluzione legata principalmente al nome dello scienziato John Von Neumann; come è stato spiegato nel Capitolo 2, Von Neumann ha osservato che nella risoluzione di un problema attraverso una macchina, si possono individuare tre fasi principali: Queste considerazioni hanno portato Von Neumann alla conclusione che i calcolatori dovessero avere una struttura come quella schematizzata in Figura 7.1. In questa struttura, chiamata Macchina di Von Neumann, notiamo la presenza di un dispositivo di Ingresso o Input attraverso il quale vengono inseriti i dati da elaborare; il dispositivo chiamato Memoria può essere visto come una sorta di "magazzino" all'interno del quale vengono sistemati temporaneamente i dati appena immessi. L'Unità Centrale di Elaborazione o Central Processing Unit (CPU) è il cuore di tutto il sistema ed ha il compito di elaborare i dati immagazzinati nella memoria; infine, il dispositivo di Uscita o Output ha il compito di presentare i risultati delle elaborazioni appena effettuate.
Gli studi di Von Neumann hanno permesso la realizzazione di macchine di calcolo automatico caratterizzate da semplicità costruttiva, potenza e flessibilità al punto che ancora oggi, moltissime famiglie di computer (piattaforme hardware) si ispirano proprio a questo tipo di architettura; in particolare, possiamo citare i PC basati sulla famiglia dei processori Intel 80x86 e compatibili.

7.2 Il programma

L'aspetto veramente rivoluzionario che caratterizza una macchina di Von Neumann è dato dal fatto che la memoria è destinata a contenere non solo i dati da elaborare, ma anche le relative istruzioni di elaborazione; nel loro insieme i dati da elaborare e le istruzioni di elaborazione formano un cosiddetto programma.
Si può immaginare la memoria come un grande contenitore suddiviso in tanti scomparti ciascuno dei quali rappresenta una cosiddetta cella di memoria; per individuare in modo univoco le celle, assegnamo a ciascuna di esse un numero progressivo 0, 1, 2, 3, etc, chiamato indirizzo di memoria. Grazie agli indirizzi di memoria, possiamo accedere ad ogni cella, sia per immagazzinare in essa un dato (accesso in scrittura), sia per leggere il suo contenuto (accesso in lettura).
Vediamo ora come avviene l'esecuzione di un programma in una macchina come quella di Figura 7.1.
Riserviamo un'area della memoria ai dati in ingresso e a quelli in uscita; quest'area rappresenta il blocco dati del programma. Riserviamo un'altra area della memoria alle istruzioni di elaborazione; quest'altra area rappresenta il blocco codice del programma. Inizializziamo poi un apposito contatore caricando in esso l'indirizzo di memoria dove si trova la prima istruzione da eseguire; a questo punto il controllo passa alla CPU che può iniziare la fase di elaborazione del programma.
Supponiamo, ad esempio, di avere in memoria il programma mostrato in Figura 7.2, con il contatore che inizialmente contiene l'indirizzo 0000. La CPU va all'indirizzo 0000 dove trova una istruzione che consiste nella lettura del dato (3500) che si trova in memoria all'indirizzo 0005; mentre la CPU esegue questa istruzione, il contatore viene incrementato di 1 e il suo contenuto diventa quindi 0001.
La CPU va all'indirizzo 0001 dove trova una istruzione che consiste nella lettura del dato (2300) che si trova in memoria all'indirizzo 0006; mentre la CPU esegue questa istruzione, il contatore viene incrementato di 1 e il suo contenuto diventa quindi 0002.
La CPU va all'indirizzo 0002 dove trova una istruzione che consiste nel calcolo della somma dei due dati appena letti dalla memoria; mentre la CPU esegue questa istruzione, il contatore viene incrementato di 1 e il suo contenuto diventa quindi 0003.
La CPU va all'indirizzo 0003 dove trova una istruzione che consiste nel salvare il risultato della somma (5800) nella cella di memoria 0007; come si può notare, la cella 0007 è inizialmente vuota ed è destinata a contenere il risultato delle elaborazioni effettuate dalla CPU. Mentre la CPU esegue questa istruzione, il contatore viene incrementato di 1 e il suo contenuto diventa quindi 0004.
La CPU va all'indirizzo 0004 dove trova una istruzione che segnala la fine delle elaborazioni; a questo punto la CPU entra in pausa in attesa di ulteriori richieste di elaborazione.

Non ci vuole molto a capire che il sistema appena descritto presenta una elevatissima flessibilità; se vogliamo sostituire, ad esempio, l'addizione con una sottrazione, ci basta modificare le apposite istruzioni del programma appena illustrato. Naturalmente, le varie istruzioni devono appartenere ad un insieme riconosciuto dalla CPU; questo insieme viene definito set di istruzioni della CPU.
Una macchina di calcolo automatico come quella appena descritta viene definita a logica programmabile e presenta l'eccezionale caratteristica di poter svolgere praticamente un numero illimitato di compiti differenti; naturalmente, le macchine di questo tipo sono enormemente più complesse e quindi più lente rispetto alle macchine a logica cablata.

7.3 Il microprocessore

Un'altra rivoluzione che ha letteralmente sconvolto il mondo delle macchine di calcolo automatico è stata provocata dall'invenzione del microprocessore, avvenuta nel 1970; questa invenzione è legata anche al nome dell'italiano Federico Faggin che all'epoca lavorava come progettista in una piccola e giovane società della Silicon Valley chiamata Intel. Insieme ai suoi colleghi, Faggin si rese conto che l'evoluzione tecnologica aveva raggiunto ormai un livello tale da permettere la possibilità di miniaturizzare le porte logiche e di inserirle in grande quantità in uno spazio estremamente ristretto; in particolare, i progettisti della Intel riuscirono a fabbricare interi circuiti logici direttamente all'interno di un piccolo blocco di materiale semiconduttore chiamato chip. In questo modo ottennero un microcircuito che integrava al suo interno numerose R.C. come quelle presentate nel precedente capitolo; attraverso un apposito sistema di controllo esterno, questo microcircuito, che venne chiamato appunto microprocessore, poteva essere pilotato in modo da fargli svolgere una numerosa serie di operazioni logico aritmetiche.
Il termine microprocessore è sinonimo quindi di micro CPU; nel caso generale comunque il termine CPU indica una rete logica complessa capace di eseguire una serie più o meno numerosa di operazioni logico aritmetiche.
La prima CPU realizzata dal gruppo di progettisti di cui faceva parte anche Faggin è stata chiamata 4004 ed aveva una architettura a 4 bit; nel 1972 è nata la CPU 8008 con architettura a 8 bit. Nel 1974 Faggin, prima di uscire dalla Intel, progettò la CPU 8080 che aveva sempre una architettura a 8 bit, ma garantiva prestazioni notevolmente superiori rispetto alla 8008; successivamente Faggin nel 1975 fondò la società Zilog e progettò la fortunatissima CPU Z80 a 8 bit che andò ad equipaggiare i famosissimi micro computer Sinclair ZX Spectrum.
A partire dagli anni 80 sono comparse sul mercato CPU sempre più potenti ed avanzate; in particolare, la famiglia 80x86 si è evoluta con la nascita di nuove CPU a 16 bit e a 32 bit, sino alle attuali CPU a 64 bit. La Figura 7.3 mostra, ad esempio, un ingrandimento della struttura interna della CPU Intel Pentium I; questa CPU (che viene considerata ormai vecchia) integra al suo interno circa 3100000 transistor! Cerchiamo ora di capire meglio il principio di funzionamento di una CPU; a tale proposito analizziamo la Figura 7.4 che mostra una R.C. già presentata nel precedente capitolo. Come già sappiamo, attraverso le due linee di selezione possiamo far svolgere a questo circuito 4 funzioni differenti; in particolare, si nota che: Si può paragonare il circuito di Figura 7.4 ad una sorta di rudimentale CPU a 4 bit, dotata di 4 linee per il dato in ingresso, 4 linee per il dato in uscita e 2 linee di selezione (linee di controllo) che permettono di specificare una tra le 22=4 istruzioni eseguibili; ciascuna istruzione per essere capita dalla CPU deve essere espressa come al solito sotto forma di segnali logici e cioè, sotto forma di codice binario. Nel caso, ad esempio, di S0=0 e S1=0, il circuito di Figura 7.4 esegue l'istruzione NOT che consiste in questo caso nella inversione dei 4 bit del dato in ingresso; possiamo dire allora che in questa CPU l'istruzione NOT viene codificata con il codice binario 00b. Il valore binario che codifica una determinata istruzione prende il nome di codice macchina; l'insieme di tutti i codici macchina riconosciuti da una CPU rappresenta, come è stato già anticipato, il set di istruzioni della CPU stessa.
A questo punto appare chiaro il principio di funzionamento di una CPU; ciascuna istruzione appartenente al programma da eseguire, viene codificata attraverso il relativo codice macchina. L'esecuzione di una determinata istruzione consiste nell'invio alla CPU della sequenza di segnali logici che codificano l'istruzione stessa; questi segnali selezionano all'interno della CPU l'apposita R.C. che esegue l'istruzione desiderata.
Tornando al circuito di Figura 7.4, supponiamo, ad esempio, di eseguire un programma che ad un certo punto prevede una istruzione per l'inversione dei bit del nibble che si trova in memoria all'indirizzo 01001111b; il codice macchina di questa istruzione può essere allora:
00b 01001111b
L'esecuzione di questa istruzione si svolge in diverse fasi. Prima di tutto, l'istruzione viene decodificata da un apposito circuito di controllo; il circuito di controllo dice alla CPU di leggere dalla memoria un nibble che si trova all'indirizzo 01001111b; una volta che il nibble è stato caricato (attraverso le 4 linee di ingresso), il circuito di controllo invia il codice 00b alle linee di selezione della CPU in modo da abilitare l'istruzione NOT. Alla fine si ottiene in uscita il nibble in ingresso con i bit invertiti.

Le considerazioni appena esposte evidenziano anche il fatto che l'unico linguaggio capito dalla CPU è, naturalmente, il codice macchina; nei capitoli successivi vedremo però che fortunatamente la CPU può essere programmata anche attraverso linguaggi molto più semplici e allo stesso tempo più evoluti.

7.4 La struttura generale di un computer

In base a ciò che è stato appena detto a proposito della macchina di Von Neumann e del principio di funzionamento di una CPU, possiamo subito dedurre una serie di considerazioni generali relative alla organizzazione interna di un computer; l'aspetto più evidente riguarda il fatto che la CPU ha la necessità di comunicare con tutti gli altri dispositivi del computer, che vengono chiamati periferiche. Tra le varie periferiche, la più importante di tutte è senza dubbio la memoria del computer che viene anche chiamata memoria centrale; proprio per questo motivo, quando si parla di cuore del computer ci si riferisce all'insieme formato dalla CPU e dalla memoria centrale.
Tutte le altre periferiche vengono trattate come secondarie e vengono anche chiamate dispositivi di I/O (input/output); tra i vari dispositivi di I/O che usualmente risultano collegati al computer si possono citare: tastiere, mouse, monitor, stampanti, plotter, scanner, schede audio, schede video, joystick, hard disk, lettori di floppy disk, lettori CD, etc. Esistono dispositivi accessibili, sia in lettura che in scrittura (memoria centrale, hard disk, floppy disk), altri accessibili solo in lettura (mouse, joystick) e altri ancora accessibili solo in scrittura (stampanti, plotter).
La CPU dialoga con una qualsiasi periferica attraverso un interscambio di dati; questo accade, ad esempio, quando la CPU deve accedere in lettura o in scrittura alla memoria, oppure quando la CPU deve leggere le coordinate del cursore del mouse sullo schermo, oppure quando la CPU deve visualizzare una immagine sullo schermo, etc. Affinché sia possibile l'interscambio di dati, la CPU viene connessa a tutte le periferiche attraverso una serie di linee elettriche che nel loro insieme formano il cosiddetto Data Bus (bus dei dati); su ciascuna linea elettrica del Data Bus transita uno dei bit del dato da trasferire.

Un altro aspetto abbastanza evidente riguarda il fatto che la CPU per poter dialogare con una periferica deve chiaramente conoscerne l'indirizzo; nel caso della memoria abbiamo già visto che le varie celle vengono identificate attraverso un indirizzo rappresentato da un numero intero. Per tutte le altre periferiche si utilizza lo stesso procedimento; ad ogni periferica viene associato quindi un determinato numero intero che rappresenta l'indirizzo che identifica in modo univoco la periferica stessa.
Possiamo dire quindi che nel momento in cui la CPU vuole dialogare con una determinata periferica, deve prima di tutto specificare l'indirizzo a cui vuole accedere; come al solito, questo indirizzo deve essere rappresentato sotto forma di segnali logici e cioè, sotto forma di codice binario. A tale proposito la CPU viene connessa a tutte le periferiche attraverso una serie di linee elettriche che nel loro insieme formano il cosiddetto Address Bus (bus degli indirizzi); su ciascuna linea elettrica dell'Address Bus transita uno dei bit del numero binario che rappresenta l'indirizzo a cui la CPU vuole accedere.

Tutto il sistema appena descritto non potrebbe assolutamente funzionare se non venisse coordinato da un apposito circuito di controllo; questo circuito rappresenta la cosiddetta logica di controllo o Control Logic (CL) del computer. Il compito fondamentale svolto dalla CL consiste nel gestire i vari dispositivi che formano il computer stabilendo istante per istante quali dispositivi devono essere attivati e quali, invece, devono essere disattivati.
Per avere un'idea dell'importanza della CL, supponiamo, ad esempio, che la CPU debba leggere un dato dalla memoria per poi applicare ad esso l'istruzione NOT; in questo caso la CL carica sull'Address Bus l'indirizzo di memoria a cui si deve accedere e predispone la memoria stessa per una operazione di lettura. Terminata questa fase la CL autorizza la CPU a leggere il dato dalla memoria attraverso il Data Bus; una volta che la lettura è stata effettuata, la CL autorizza l'invio alla CPU del codice macchina che abilita l'esecuzione dell'istruzione NOT sul dato appena letto.
Per la corretta gestione di tutta questa situazione, la CPU viene connessa a tutte le periferiche attraverso una serie di linee elettriche che nel loro insieme formano il cosiddetto Control Bus (bus di controllo); sul Control Bus transitano dei valori binari che codificano i vari segnali di controllo necessari per il coordinamento di tutto il sistema.

Raccogliendo le considerazioni appena esposte, possiamo definire la struttura generale che assume un classico computer appartenente alla piattaforma hardware basata sulle CPU Intel 80x86 e compatibili; la Figura 7.5 illustra uno schema a blocchi che comprende anche diverse periferiche collegate al computer. Analizziamo innanzi tutto l'Address Bus che in Figura 7.5 è stato evidenziato con il colore rosso; l'ampiezza dell'Address Bus e cioè, il numero di linee da cui è composto, determina la quantità massima di memoria fisicamente indirizzabile dalla CPU. Osserviamo, infatti, che su un Address Bus a n linee possono transitare numeri binari formati da n bit (un bit per ogni linea); con n bit possiamo rappresentare 2n numeri interi positivi distinti e cioè, tutti i numeri compresi tra 0 e 2n-1. Complessivamente quindi possiamo specificare gli indirizzi relativi a 2n celle di memoria distinte; per conoscere la quantità massima di memoria fisica indirizzabile dalla CPU dobbiamo quindi definire l'ampiezza in bit di ogni cella di memoria. Nelle piattaforme hardware basate sulle CPU 80x86 è stato deciso di adottare l'ampiezza di 8 bit (1 byte) per ogni cella di memoria; in definitiva, possiamo dire che con un Address Bus a n linee, la CPU è in grado di accedere ad un massimo di 2n byte di memoria fisica.
Le varie linee che compongono l'Address Bus vengono indicate per convenzione con i simboli A0, A1, A2, A3, etc; il simbolo A0 indica ovviamente la linea lungo la quale transita il bit meno significativo del numero binario che codifica l'indirizzo a cui vogliamo accedere.
La tabella di Figura 7.6 illustra una serie di casi che si riferiscono a CPU realmente esistenti; il codice 80586 indica in modo generico i vari modelli di CPU riconducibili alla classe Pentium I. Le considerazioni appena esposte si riferiscono all'indirizzamento della memoria centrale del computer; ci si può chiedere come avvenga, invece, l'indirizzamento delle altre periferiche. Come è stato già anticipato, anche i vari dispositivi di I/O vengono indirizzati con la stessa tecnica utilizzata per la memoria centrale; ad ogni dispositivo di I/O quindi viene assegnato un numero intero che ne rappresenta in modo univoco l'indirizzo. La tastiera del computer, ad esempio, si trova all'indirizzo esadecimale 60h; è compito della CL fare in modo che l'indirizzo di una periferica secondaria non venga confuso con l'indirizzo di una cella della memoria centrale. Nel caso in cui la CPU debba comunicare con la tastiera, la CL abilita questa periferica e disabilita la memoria centrale; in questo modo l'indirizzo 60h inviato attraverso l'Address Bus mette in comunicazione la CPU con la tastiera e non con la cella 60h della memoria centrale.
Ciascuna periferica secondaria è dotata di una memoria propria che nella gran parte dei casi ammonta a pochi byte; questa piccola area di memoria viene chiamata porta hardware. Un normale joystick a due assi e due pulsanti, ad esempio, utilizza una memoria di appena 1 byte; attraverso questo byte il joystick fornisce alla CPU tutte le informazioni relative allo stato (on/off) dei due pulsanti e alla posizione x, y della leva.
Per indirizzare questa categoria di periferiche secondarie la CPU utilizza una parte delle linee dell'Address Bus; con le vecchie CPU come l'8086 venivano utilizzate solo le prime 8 linee dell'Address Bus (da A0 a A7) con la possibilità quindi di gestire sino a 28=256 periferiche differenti. A partire dalle CPU 80386 vengono, invece, utilizzate le prime 16 linee dell'Address Bus (da A0 a A15); in questo caso è possibile gestire sino a 216=65536 periferiche differenti.
Esistono però anche periferiche secondarie particolari come la scheda video; anche le schede video di vecchia generazione arrivano ad avere una memoria propria (memoria video) che ammonta a qualche centinaio di Mb. Questa memoria ovviamente non può essere indirizzata con la stessa tecnica delle porte hardware utilizzata per un joystick o per un mouse; nel caso della memoria video (e nei casi analoghi) si ricorre allora ad una tecnica che prende il nome di I/O memory mapped (input/output mappato nella memoria centrale). Come si intuisce dal nome, questa tecnica consiste nel mappare nella memoria centrale la porzione di memoria della periferica secondaria a cui si vuole accedere; in sostanza, in una precisa area della memoria centrale viene creata una immagine della porzione di memoria della periferica secondaria. Per accedere alla memoria della periferica la CPU non deve fare altro che accedere all'immagine presente nella memoria centrale; tutte le operazioni di I/O compiute dalla CPU su questa immagine si ripercuotono istantaneamente sulla memoria della periferica.

Gli indirizzi di memoria inviati attraverso l'Address Bus vengono ricevuti da un apposito circuito decodificatore che provvede a mettere in collegamento la CPU con la cella di memoria desiderata; a questo punto può iniziare l'interscambio di dati che naturalmente si svolge attraverso il Data Bus, evidenziato in Figura 7.5 con il colore verde.
Le varie linee che compongono il Data Bus vengono indicate per convenzione con i simboli D0, D1, D2, D3, etc; il simbolo D0 indica ovviamente la linea lungo la quale passa il bit meno significativo del dato binario che sta transitando sul Data Bus.
L'ampiezza del Data Bus e cioè, il numero di linee da cui è composto, determina l'ampiezza massima in bit che possono avere i dati gestiti via hardware dalla CPU; osserviamo, infatti, che su un Data Bus formato, ad esempio, da 16 linee possono transitare numeri binari formati al massimo da 16 bit.
In base allora a quanto è stato esposto nei precedenti capitoli, possiamo dire che l'ampiezza del Data Bus è un parametro importantissimo in quanto definisce la cosiddetta architettura della CPU; una CPU con architettura a n bit (cioè con Data Bus a n linee) è dotata di R.C. in grado di eseguire via hardware operazioni logico aritmetiche su numeri binari a n bit.
Nel caso, ad esempio, della CPU 80486, il Data Bus a 32 bit permette la gestione via hardware di dati binari formati al massimo da 32 bit; se vogliamo gestire dati binari a 64 bit, dobbiamo procedere via software scrivendo un apposito programma che scompone ogni dato a 64 bit in gruppi da 32 bit.
Come conseguenza pratica delle cose appena dette, segue anche il fatto che l'ampiezza in bit del Data Bus influisce sulle caratteristiche dei vari tipi di dati che possiamo simulare via hardware con la CPU; nei precedenti capitoli abbiamo visto, infatti, che con n bit possiamo rappresentare, ad esempio, tutti i numeri interi senza segno compresi tra:
0 e 2n-1
e tutti i numeri interi con segno compresi tra:
-(2n-1) e +(2n-1-1)
La tabella di Figura 7.7 illustra una serie di casi che si riferiscono a CPU realmente esistenti; in questa tabella vengono mostrati i limiti inferiore e superiore dei numeri interi di ampiezza massima, con e senza segno, rappresentabili dalla CPU in funzione del numero di linee del Data Bus. Nel caso della 80586, il Data Bus è internamente a 64 linee, mentre esternamente alla CPU è formato da 32 linee. Come si nota dalla Figura 7.7, raddoppiando il numero di linee del Data Bus si verifica un enorme aumento dei numeri binari rappresentabili; osservando, infatti, che con n bit possiamo formare 2n numeri binari diversi e con 2n bit possiamo formare 22n numeri binari diversi, possiamo dire che passando da un Data Bus a n linee ad un Data Bus a 2n linee, i numeri binari rappresentabili crescono di un fattore pari a:
22n / 2n = 2n
Naturalmente, tutto ciò comporta un notevole aumento della complessità circuitale in quanto bisogna ricordare che una CPU con Data Bus a n linee deve essere in grado di gestire numeri binari a n bit e, in particolare, deve essere in grado di eseguire operazioni logico aritmetiche su numeri binari a n bit; aumentare quindi il numero di linee del Data Bus significa dover aumentare in modo considerevole le porte logiche delle R.C. che eseguono queste operazioni. Il problema fondamentale che i progettisti devono affrontare, consiste nel riuscire ad inserire nello spazio ristretto della CPU un numero di componenti elettronici (transistor) che ormai supera abbondantemente i dieci milioni; la CPU AMD Athlon, ad esempio, integra al suo interno circa 22000000 di transistor!

Torniamo ora alla Figura 7.5 per chiarire il significato dei termini che indicano i vari dispositivi presenti nel computer.

7.4.1 Memoria RAM

Il dispositivo indicato in Figura 7.5 con la sigla RAM rappresenta la memoria centrale del computer; la sigla RAM sta per Random Access Memory (memoria ad accesso casuale). Il termine casuale si riferisce al fatto che il tempo necessario alla CPU per accedere ad una qualsiasi cella di memoria è indipendente dalla posizione (indirizzo) della cella stessa; la CPU quindi per accedere ad una qualsiasi cella impiega un intervallo di tempo costante. Questa situazione che si presenta nelle memorie ad accesso casuale è opposta al caso delle memorie ad accesso sequenziale (come le memorie a nastro) dove il tempo di accesso dipende dalla posizione in cui si trova il dato; nel caso, ad esempio, delle memorie a nastro (come le cassette che si utilizzavano con i micro computer Amiga e ZX Spectrum), per accedere ad un dato registrato nella parte iniziale del nastro è necessario un tempo brevissimo, mentre per accedere ad un dato registrato nella parte finale del nastro è necessario un tempo lunghissimo dovuto alla necessità di far scorrere l'intero nastro.
La memoria RAM è accessibile, sia in lettura, sia in scrittura; come vedremo nel prossimo capitolo, anche le memorie RAM vengono realizzate con i transistor. Il contenuto della memoria RAM permane finché il computer rimane acceso; non appena il computer viene spento, viene a mancare l'alimentazione elettrica e il contenuto della RAM viene perso.

7.4.2 Memoria ROM

Il dispositivo indicato in Figura 7.5 con la sigla ROM è una memoria del tutto simile alla RAM e si differenzia per il fatto di essere accessibile solo in lettura; la sigla ROM, infatti, sta per Read Only Memory (memoria a sola lettura). Il contenuto della memoria ROM viene inserito in modo permanente in un apposito chip montato sul computer; questo significa che quando si spegne il computer, la memoria ROM conserva le sue informazioni.
All'interno della ROM troviamo una serie di programmi scritti in Assembly che assumono una importanza vitale per il computer; vediamo, infatti, quello che succede ogni volta che un PC viene acceso. Non appena si accende il computer, una parte della memoria ROM contenente svariati programmi viene mappata nella memoria RAM; il contatore della CPU viene inizializzato con l'indirizzo della RAM da cui inizia uno di questi programmi, chiamato POST. Possiamo dire quindi che all'accensione del computer, la prima istruzione in assoluto eseguita dalla CPU è quella che avvia il programma POST; la sigla POST sta per Power On Self Test (autodiagnosi all'accensione) e indica un programma che esegue una serie di test diagnostici all'accensione del computer, per verificare che tutto l'hardware sia funzionante. Qualsiasi problema incontrato in questa fase, viene segnalato attraverso messaggi sullo schermo o (se il problema riguarda proprio lo schermo) attraverso segnali acustici; se, ad esempio, si accende il computer con la tastiera staccata (o danneggiata), il POST stampa sullo schermo un messaggio del tipo:
Keyboard or System Unit Error
Se il POST si conclude con successo, vengono raccolte una serie di importanti informazioni sull'hardware del computer che vengono poi memorizzate in una apposita area della RAM e in una particolare memoria chiamata CMOS Memory; tutti questi argomenti vengono trattati in dettaglio nella sezione Assembly Avanzato.
Al termine del POST vengono inizializzati diversi dispositivi hardware e vengono caricati in RAM una serie di "mini programmi" (procedure) scritti in Assembly, che permettono di accedere a basso livello alle principali risorse hardware del computer; nel loro insieme queste procedure rappresentano il BIOS o Basic Input Output System (sistema primario per l'input e l'output). Le procedure del BIOS permettono, ad esempio, di formattare hard disk e floppy disk, di inviare dati "grezzi" alla stampante, di accedere alla tastiera, al mouse, etc; tutte queste procedure assumono una importanza fondamentale in quanto vengono utilizzate dai sistemi operativi (SO) come il DOS, per implementare numerosi servizi che permettono agli utenti di lavorare con il computer. I moderni SO come Windows, Linux, MacOSX, etc, usano propri servizi, molto più sofisticati, in quanto quelli del BIOS risultano insufficienti.
L'ultimo importantissimo compito svolto in fase di avvio dai programmi contenuti nella ROM, consiste nel bootstrap e cioè, nella ricerca di un particolare programma contenuto nel cosiddetto boot sector (settore di avvio); il termine boot sector indica i primi 512 byte di un supporto di memoria come un floppy disk, un hard disk o un CD-ROM. Nei moderni PC il bootstrap cerca il boot sector scandendo in sequenza il primo lettore floppy disk, il primo lettore CD e infine l'hard disk; se la ricerca fornisce esito negativo, il computer si blocca mostrando un messaggio di errore che indica l'assenza del SO. La ricerca si conclude, invece, con esito positivo se nei primi 512 byte di uno dei supporti di memoria citati in precedenza viene trovato un programma chiamato boot loader (caricatore di avvio); in questo caso il boot loader viene caricato in memoria e viene fatto eseguire dalla CPU. Il compito fondamentale del boot loader consiste nel caricare nella memoria RAM il SO installato sul computer; a questo punto i programmi di avvio della ROM hanno concluso il loro lavoro e il controllo passa al SO.

7.4.3 Interfaccia tra la CPU e le periferiche

Analizzando la Figura 7.5 si nota che mentre, ad esempio, la RAM è connessa in modo diretto alla CPU, altrettanto non accade per molte altre periferiche secondarie; questa situazione è dovuta al fatto che esistono periferiche di tipo digitale e periferiche di tipo analogico. La RAM è una periferica di tipo digitale in quanto gestisce direttamente segnali logici che rappresentano dati binari; anche la CPU è ovviamente un dispositivo di tipo digitale e quindi possiamo dire che la CPU e la RAM parlano lo stesso linguaggio. Tutto ciò rende possibile un interscambio diretto di dati tra CPU e RAM attraverso il Data Bus; questo aspetto è fondamentale in quanto la RAM deve essere in grado di fronteggiare l'elevatissima velocità operativa della CPU.
Esistono, invece, numerose periferiche di tipo analogico che in quanto tali non possono essere collegate direttamente alla CPU; una periferica di tipo analogico parla, infatti, un linguaggio differente da quello binario parlato dalla CPU.

Consideriamo, ad esempio, un normale joystick dotato di due assi (x, y) e due pulsanti; lo stato on/off di ciascun pulsante viene rappresentato attraverso una tensione elettrica. Possiamo associare il valore di tensione V0 allo stato off e il valore di tensione V1 allo stato on; questi valori analogici di tensione per poter essere letti dalla CPU devono essere prima convertiti in livelli logici compatibili con quelli usati dalla CPU stessa. Possiamo convertire, ad esempio, il valore V0 nel valore di tensione GND utilizzato dalla CPU per rappresentare il livello logico 0; analogamente, possiamo convertire il valore V1 nel valore di tensione +Vcc utilizzato dalla CPU per rappresentare il livello logico 1.
Per gli assi del joystick la situazione è più complessa; le coordinate x, y che esprimono la posizione della leva, sono rappresentate dai valori assunti da due resistenze elettriche variabili (reostati). È chiaro che la CPU non può essere in grado di leggere direttamente i valori analogici in ohm di queste due resistenze; per poter effettuare questa lettura bisogna prima convertire i due valori di resistenza in due numeri binari.

Un esempio ancora più emblematico è rappresentato dal modem che, come si sa, viene utilizzato per permettere a due o più computer di comunicare tra loro attraverso le linee telefoniche; il problema che si presenta è dato dal fatto che molte linee telefoniche sono ancora di tipo analogico e quindi possono accettare solamente segnali elettrici analogici. Per gestire questa situazione viene utilizzato appunto il modem che ha il compito di effettuare le necessarie conversioni da digitale ad analogico e viceversa.
In fase di trasmissione il modem converte i segnali logici che arrivano dalla CPU in segnali analogici da immettere nelle linee telefoniche; in fase di ricezione il modem converte i segnali analogici che arrivano dalle linee telefoniche in segnali logici destinati alla CPU. La conversione in trasmissione viene chiamata modulazione, mentre la conversione in ricezione viene chiamata demodulazione; dalla unione e dalla contrazione di questi due termini si ottiene il termine modem. Per effettuare queste conversioni vengono utilizzati diversi metodi; la Figura 7.8 illustra, ad esempio, un metodo di conversione che viene chiamato modulazione di ampiezza. La Figura 7.8a mostra la rappresentazione logica del numero binario 01010011b; la Figura 7.8b mostra, invece, la rappresentazione analogica dello stesso numero, ottenuta attraverso la modulazione di ampiezza; in pratica, i vari livelli logici che formano il numero binario, vengono convertiti in un segnale elettrico oscillante, con l'ampiezza (altezza) delle varie oscillazioni che è funzione dei livelli logici stessi. Come si può notare, il livello logico 0 viene convertito in una oscillazione avente una determinata ampiezza; il livello logico 1 viene convertito in una oscillazione avente ampiezza maggiore.

Tutte le periferiche di tipo analogico devono essere collegate alla CPU attraverso appositi dispositivi che provvedono alle necessarie conversioni da analogico a digitale e viceversa; questi dispositivi vengono genericamente chiamati interfacce hardware. L'obiettivo che i produttori di hardware si prefiggono è quello di realizzare periferiche di tipo digitale che evitando queste conversioni, semplificano enormemente le comunicazioni con la CPU; è chiaro, infatti, che eliminando la complessa fase di conversione dei segnali, si ottiene un notevole aumento delle prestazioni generali del computer.

7.5 Un esempio reale: la CPU Intel 8080

Per chiarire il significato degli altri dispositivi visibili in Figura 7.5 e per capire meglio il funzionamento di un computer, analizziamo un esempio reale rappresentato da un computer basato sulla CPU Intel 8080; questa CPU appartiene ormai alla preistoria, ma come vedremo nei capitoli successivi, il suo "fantasma" aleggia ancora persino sulle CPU di classe Pentium. La Figura 7.9 illustra uno schema a blocchi con la cosiddetta piedinatura della CPU 8080; la piedinatura rappresenta l'insieme dei terminali elettrici che collegano una CPU (o un generico chip) al mondo esterno. Osserviamo subito che questa CPU è formata da tre chip che rappresentano il generatore di clock 8224, la CPU vera e propria (8080) e la logica di controllo 8228; si nota anche la presenza sui tre chip del terminale di massa GND e delle tensioni di alimentazione +5V, -5V e +12V.
Come è stato già detto in precedenza, l'8080 è una CPU con architettura a 8 bit e dispone di un Address Bus a 16 linee con la possibilità quindi di indirizzare fino a 216=65536 byte di RAM fisica; in Figura 7.9 si nota, infatti, in modo evidente la presenza delle 8 linee del Data Bus (da D0 a D7) e delle 16 linee dell'Address Bus (da A0 a A15).
Nella parte inferiore del lato destro del chip 8228 (System Control) notiamo la presenza del Control Bus a 5 linee; su queste 5 linee transitano i segnali di controllo chiamati INTA, MEMR, MEMW, I/OR e IO/W. La linea MEMR abilita una operazione di lettura in RAM; la sigla MEMR significa, infatti, Memory Read. La linea MEMW abilita una operazione di scrittura in RAM; la sigla MEMW significa, infatti, Memory Write. La linea I/OR abilita una operazione di lettura da un dispositivo di I/O; la sigla I/OR significa, infatti, I/O Read. La linea I/OW abilita una operazione di scrittura in un dispositivo di I/O; la sigla I/OW significa, infatti, I/O Write.

7.5.1 Le interruzioni hardware

Passiamo ora alla linea di controllo INTA che svolge un ruolo veramente importante; questa linea opera in combinazione con l'uscita INTE e l'ingresso INT visibili sul lato sinistro del chip 8080. I segnali che transitano su queste linee hanno lo scopo di permettere alle varie periferiche di richiedere la possibilità di comunicare con la CPU; per permettere alle periferiche di poter dialogare con la CPU, si possono utilizzare due tecniche principali che vengono chiamate polling (sondaggio) e hardware interrupts (interruzioni hardware).
Con la tecnica del polling la CPU interroga (sonda) continuamente tutte le periferiche per sapere se qualcuna di esse vuole intervenire; l'eventuale richiesta di intervento viene inviata da ogni periferica attraverso appositi segnali logici. Il vantaggio fondamentale della tecnica del polling consiste nella sua semplicità che si traduce quindi in una conseguente semplificazione circuitale; lo svantaggio evidente è rappresentato, invece, dal grave rallentamento generale del sistema dovuto al fatto che la CPU è costantemente impegnata nelle operazioni di sondaggio delle varie periferiche. La tecnica del polling veniva largamente utilizzata nei vecchi computer; in effetti, in passato questa tecnica si rivelava vantaggiosa grazie anche al fatto che esistevano pochissime periferiche da collegare ai computer.

Nei moderni computer e, in particolare, in tutti i PC appartenenti alla piattaforma hardware 80x86 viene utilizzata, invece, la sofisticata tecnica delle hardware interrupts; questa tecnica consiste semplicemente nel fatto che se una periferica vuole dialogare con la CPU, deve essere essa stessa a segnalare la richiesta.
A tale proposito, su qualsiasi PC basato sulle CPU 80x86 è presente almeno un chip chiamato 8259 PIC; la sigla PIC sta per Programmable Interrupts Controller (controllore programmabile delle interruzioni). Il compito fondamentale del PIC è quello di ricevere tutte le richieste di intervento che arrivano dalle varie periferiche; il PIC provvede anche a disporre queste richieste in una apposita coda di attesa. Per abilitare la gestione delle hardware interrupts la CPU 8080 si serve dell'apposita linea INTE visibile in Figura 7.9; la sigla INTE sta, infatti, per interrupts enable (abilitazione delle interruzioni).
In fase di avvio del computer vengono installate in RAM una serie di procedure scritte in Assembly che vengono chiamate ISR; la sigla ISR sta per Interrupt Service Routine (procedura per la gestione di una interruzione). Come si deduce dal nome, il compito delle ISR è quello di rispondere alle richieste di intervento che arrivano dalle varie periferiche; gli indirizzi di memoria relativi alle varie ISR vengono sistemati in una apposita area della RAM e formano i cosiddetti Interrupt Vectors (vettori di interruzione). Diverse ISR vengono installate da un apposito programma della ROM e rappresentano le procedure del BIOS citate in precedenza; numerose altre ISR vengono installate dai SO.
In base alle considerazioni appena esposte, analizziamo ora quello che succede quando una periferica vuole dialogare con la CPU; vediamo, in particolare, quello che succede quando l'utente preme un tasto sulla tastiera mentre la CPU sta eseguendo un programma: Come si può facilmente intuire, il metodo delle Hardware Interrupts è sicuramente più complesso della tecnica del polling, ma presenta il vantaggio di garantire una gestione enormemente più efficiente delle periferiche; è chiaro, infatti, che grazie alla tecnica delle interruzioni hardware, la CPU dialoga con le periferiche solo quando è strettamente necessario evitando in questo modo inutili perdite di tempo.

7.5.2 L'accesso diretto alla memoria RAM

Nel caso generale, qualsiasi elaborazione svolta dal computer deve avvenire rigorosamente sotto la supervisione della CPU; esiste però un caso per il quale l'intervento della CPU è del tutto superfluo e provoca anche un notevole rallentamento delle operazioni. Questo caso si verifica quando dobbiamo semplicemente trasferire un grosso blocco di dati dalla RAM ad una periferica di I/O o viceversa; in una situazione del genere, non viene eseguita alcuna operazione logico aritmetica, per cui l'intervento della CPU è del tutto inutile.
Queste considerazioni hanno spinto i progettisti dei computer a prevedere l'eventualità di far comunicare determinate periferiche direttamente con la RAM, aggirando in questo modo la CPU; l'interscambio diretto di dati tra RAM e periferiche rende questa operazione nettamente più veloce ed efficiente.
Nelle piattaforme hardware 80x86 l'accesso diretto alla RAM da parte delle periferiche viene gestito da un apposito chip chiamato 8237 DMAC; la sigla DMAC sta per Direct Memory Access Controller (controllore per l'accesso diretto alla memoria). Questo chip è una vera e propria mini CPU che è in grado però di eseguire esclusivamente trasferimenti di dati tra RAM e periferiche; nei moderni PC il chip 8237 è stato integrato direttamente nei circuiti del computer.
In Figura 7.5 vediamo il controllore DMA che si trova posizionato nel computer proprio come se fosse una CPU; quando una periferica vuole scambiare dati direttamente con la RAM, deve comunicarlo al DMAC. In altre parole, è necessario innanzi tutto programmare il DMAC in modo da fornirgli le necessarie informazioni che riguardano la periferica che vuole accedere direttamente in RAM, quanti byte di dati devono essere trasferiti, etc; il DMAC una volta programmato invia la necessaria richiesta alla CPU attraverso la linea DMA Request visibile in Figura 7.9 sul lato sinistro del chip 8080 (questa richiesta viene anche chiamata HOLD). Se la CPU accetta la richiesta, invia un segnale di via libera attraverso la linea HLDA (HOLD Acknowledgement) visibile in Figura 7.9 sul lato destro del chip 8080; a questo punto la CPU si disattiva e cede il controllo del Data Bus al DMAC.
Generalmente il DMAC suddivide il Data Bus in gruppi di 8 linee chiamati DMA Channels (canali DMA); sulle CPU con Data Bus a 32 linee, ad esempio, abbiamo 4 canali DMA chiamati: channel 0 (linee da D0 a D7), channel 1 (linee da D8 a D15), channel 2 (linee da D16 a D23) e channel 3 (linee da D24 a D31).
Solamente alcune periferiche sono predisposte per l'accesso diretto in RAM; tra queste periferiche si possono citare gli hard disk, i lettori di floppy disk, i lettori di CD/DVD e le schede audio. Per avere un'idea della notevole efficienza del DMA, si può considerare proprio il caso della visione di un film in DVD sul computer; in presenza di un lettore DVD con supporto per il DMA è possibile avere una riproduzione estremamente fluida del film anche su computer relativamente lenti. Molti SO permettono all'utente la disattivazione del DMA sul proprio lettore DVD; in questo modo si può constatare che la riproduzione dei film in DVD subisce un notevole rallentamento con evidenti salti tra un fotogramma e l'altro.

7.5.3 Il segnale di clock

Il funzionamento del computer sarebbe impossibile se non si provvedesse a sincronizzare perfettamente tutti i suoi componenti; la logica di controllo del computer, infatti, non sarebbe in grado di sapere, ad esempio, se una determinata operazione aritmetica è già stata eseguita dalla CPU, se un dato inviato alla RAM è già stato memorizzato, se una periferica ha eseguito un determinato compito, etc.
Per ottenere la sincronizzazione tra tutti i componenti del computer viene utilizzato un apposito segnale al quale viene affidato in pratica il compito di scandire il ritmo di lavoro; i segnali più adatti per svolgere questa funzione sono i cosiddetti segnali periodici. La Figura 7.10 illustra due esempi di segnali periodici; in Figura 7.10a vediamo un segnale periodico di tipo analogico, mentre in Figura 7.10b vediamo un segnale periodico di tipo logico. Si definisce periodico un segnale i cui valori si ripetono ciclicamente nel tempo; in pratica, un segnale periodico varia assumendo dei valori che si ripetono identicamente ad intervalli regolari di tempo. Ciascuno di questi intervalli regolari di tempo viene chiamato periodo; come si vede in Figura 7.10, il periodo di un segnale periodico viene convenzionalmente indicato con la lettera T.
Ciascuna sequenza di valori che si sviluppa in un periodo T viene chiamata ciclo; il numero di cicli completi che si svolgono nel tempo di 1 secondo rappresenta la frequenza del segnale (f). Utilizzando le proporzioni possiamo dire allora che:
1 ciclo sta a T secondi come f cicli stanno a 1 secondo
Da questa proporzione si ricava:
f = 1 / T
La frequenza quindi è l'inverso del periodo e di conseguenza la sua unità di misura è sec-1; in onore del fisico tedesco Hertz, scopritore delle onde radio, l'unità di misura della frequenza è stata chiamata hertz ed ha per simbolo Hz. In elettronica si usano spesso i multipli: kHz (migliaia di Hz), MHz (milioni di Hz), GHz (miliardi di Hz).

La sincronizzazione tra tutti i componenti che formano un computer viene ottenuta attraverso un segnale periodico di tipo logico come quello visibile in Figura 7.10b; questo segnale viene anche chiamato clock (orologio). Possiamo dire quindi che il segnale di clock di una CPU è un segnale periodico che oscilla continuamente tra il livello logico 0 e il livello logico 1. La frequenza di oscillazione del segnale di clock di una CPU viene definita frequenza di clock; come molti sanno, la frequenza di clock è un parametro fondamentale per una CPU in quanto determina la cosiddetta frequenza di lavoro della CPU stessa. Quando si parla, ad esempio, di CPU Athlon a 1800 MHz, ci si riferisce al fatto che questa particolare CPU riceve un segnale di clock che compie 1800000000 cicli al secondo (Hz); se si considera il fatto che tutte le CPU, a partire dall'80386 a 33 MHz, sono in grado di compiere una operazione di I/O in RAM in un solo ciclo di clock, si può capire che in linea di principio, maggiore è la frequenza di clock, maggiore sarà la velocità operativa del computer.

Il segnale di clock che sincronizza il computer deve avere come caratteristica fondamentale una perfetta stabilità nel tempo; il modo migliore per ottenere questa caratteristica consiste nello sfruttare una proprietà naturale del quarzo (e di altri materiali) chiamata piezoelettricità. In pratica, tagliando in modo opportuno un cristallo di quarzo, si ottiene una lamina che, sottoposta a pressione lungo una precisa direzione, sviluppa una differenza di potenziale elettrico (tensione); sottoponendo la lamina di quarzo a trazione lungo la stessa direzione, si sviluppa una differenza di potenziale elettrico con polarità invertite rispetto al caso precedente. In generale, sottoponendo la lamina a continue pressioni e trazioni (vibrazioni), si produce nella lamina stessa una tensione elettrica alternata; l'aspetto importante è che questo fenomeno è reversibile, nel senso che sottoponendo la lamina ad una tensione elettrica alternata (la cui polarità si inverte cioè ad intervalli di tempo regolari), si produce nella lamina stessa una vibrazione ad altissima frequenza, perfettamente stabile nel tempo. Appositi circuiti elettronici, chiamati oscillatori al quarzo, convertono queste vibrazioni in un segnale periodico altamente stabile; nel caso del computer, l'oscillatore produrrà un segnale periodico di tipo logico, che oscillerà continuamente tra i valori 0 e 1, compatibili con i livelli logici della CPU. In Figura 7.5 e in Figura 7.9 si può osservare il simbolo grafico che rappresenta il cristallo di quarzo utilizzato dall'oscillatore; negli schemi elettrici questo cristallo viene sempre indicato con la sigla XTAL.

Nel caso più generale i computer dispongono di un clock generator (generatore di segnale di clock) che produce in uscita un unico segnale di clock da inviare alla CPU; in alcuni casi, invece, il clock generator produce due segnali di clock che hanno la stessa frequenza, ma risultano sfasati tra loro. Questo è proprio quello che accade con la CPU 8080 visibile in Figura 7.9; in ogni caso, il segnale di clock singolo o doppio viene utilizzato per ricavare altri segnali periodici destinati a svolgere diversi compiti di sincronizzazione.
Per chiarire meglio questi concetti, facciamo riferimento proprio al doppio segnale di clock prodotto in uscita dal clock generator 8224 della CPU 8080 di Figura 7.9; in questo caso si viene a creare la situazione mostrata in Figura 7.11. I due segnali indicati con CLK1 e CLK2 vengono generati dal chip 8224 ed hanno la funzione di segnali di riferimento; come si può notare, questi due segnali hanno la stessa frequenza f0 (e quindi lo stesso periodo T0), ma risultano sfasati tra loro di mezzo periodo (180 gradi). Sovrapponendo questi due segnali (applicandoli, ad esempio, ad una porta OR a due ingressi) la CPU ricava un nuovo segnale che in Figura 7.11 viene indicato con CLKe; questo segnale ha quindi frequenza:
fe = 2 * f0
e di conseguenza il suo periodo è:
Te = T0 / 2
Questo significa che nell'intervallo di tempo impiegato da CLK1 per compiere un ciclo completo, CLKe compie due cicli completi.
CLKe ha un significato molto importante in quanto il suo periodo rappresenta il cosiddetto intervallo di tempo elementare della CPU; si tratta cioè dell'intervallo di tempo minimo, necessario alla CPU per eseguire le operazioni hardware di base come l'abilitazione della memoria, l'abilitazione di un bus etc. È chiaro che in teoria sarebbe vantaggioso spingere il più in alto possibile il valore della frequenza fe; nella pratica però bisogna fare i conti con il tempo di risposta delle porte logiche che limita il valore massimo di fe.
Sempre dalla Figura 7.11 si nota che a partire ugualmente dai due segnali di riferimento, la CPU ricava un ulteriore segnale periodico CLKm; nel caso di Figura 7.11 questo segnale ha una frequenza di clock:
fm = f0 / 2
e ovviamente, periodo:
Tm = 2 * T0
Anche CLKm ha una grande importanza per la CPU in quanto ogni suo ciclo rappresenta il cosiddetto ciclo macchina e più cicli macchina formano il ciclo istruzione, cioè il numero di cicli macchina necessari alla CPU per eseguire una determinata istruzione; ogni istruzione appartenente ad una CPU viene eseguita in un preciso numero di cicli macchina e questo permette alla logica di controllo di sincronizzare tutte le fasi necessarie per l'elaborazione dell'istruzione stessa.

Nei manuali e nella documentazione tecnica relativa ai vari modelli di CPU, il numero di cicli del segnale CLK1 (o CLK2) necessari per eseguire una determinata istruzione, viene indicato con la definizione di clock cycles (cicli di clock).
Con il passare degli anni il progresso tecnologico sta portando alla realizzazione di dispositivi elettronici sempre più veloci che permettono alle nuove CPU di lavorare con frequenze di clock sempre più elevate; attraverso poi l'individuazione di algoritmi di calcolo sempre più efficienti, è possibile realizzare R.C. capaci di eseguire le istruzioni in un numero sempre minore di cicli di clock.
Per fare un esempio pratico, l'8086 ha una frequenza di clock di circa 5 MHz ed esegue una moltiplicazione tra numeri interi in oltre 100 cicli di clock pari a:
100 / 5000000 = 0.00002 secondi = 20000 nanosecondi
(1 nanosecondo = 1 miliardesimo di secondo).

L'80486 ha una frequenza di clock di 33 MHz e per la stessa operazione richiede poco più di 10 cicli di clock pari a:
10 / 33000000 = 0.0000003 secondi = 300 nanosecondi
In sostanza, l'80486 esegue una moltiplicazione 83 volte più velocemente rispetto all'8086!