Il calcolatore
I tipi di calcolatori e le loro caratteristiche
I personal computer (PC) sono dei calcolatori progettati per essere utilizzati da un unico utente alla volta; solitamente comprendono un monitor grafico, una tastiera e un mouse. I server sono dei calcolatori progettati per l'esecuzione di programmi di grosse dimensioni e per servire più utenti spesso simultaneamente. I server offrono potenza di calcolo, velocità di input/output e una grande capacità della memoria.
I calcolatori embedded sono dei calcolatori posti all'interno di un altro dispositivo e usati esclusivamente per eseguire una predeterminata applicazione o un insieme di programmi. I dispositivi mobili sono piccoli dispositivi wireless che vengono collegati a Internet. Sono alimentati da un accumulatore e il software viene installato scaricando delle applicazioni, dette app dalla rete. I personal mobile devices utilizzano una connessione wireless, ovvero una connessione radio tra un dispositivo elettronico e un altro o Internet senza uso di cavi elettrici.
I server tradizionali sono stati sostituiti dal cloud computing, termine che si riferisce a un insieme di molti server che forniscono servizi attraverso Internet; alcuni provider noleggiano dinamicamente un numero variabile di questi server a terze parti che forniscono servizi agli utenti.
Che cosa c'è dietro un programma
Una tipica applicazione è costituita da milioni di linee di codice e si serve di sofisticate librerie software che implementano funzioni complesse di supporto all'applicazione stessa. Il calcolatore può eseguire istruzioni di basso livello estremamente semplici; passare da un'applicazione complessa (scritta in un linguaggio di alto livello C/Java) alle semplici istruzioni che possono essere comprese dal calcolatore è un processo che coinvolge diversi strati di software che interpretano e traducono le operazioni. Questo è un esempio di astrazione.
Il software di sistema fornisce servizi di comune utilità; i due componenti essenziali per tutti i calcolatori sono il sistema operativo e il compilatore. Il sistema operativo permette di interfacciare i programmi utente con l'hardware del calcolatore, fornendo un gran numero di servizi e funzioni di supervisione.
- Gestire le operazioni base di input/output
- Allocare spazio nella memoria principale e nei dispositivi di memoria di massa
- Consentire a più applicazioni di utilizzare simultaneamente lo stesso calcolatore
I compilatori eseguono come funzione principale la traduzione di un programma scritto in un linguaggio ad alto livello, come per esempio C, Java o Visual Basic, in istruzioni eseguibili dall'hardware.
Processo di traduzione: da un linguaggio di alto livello al linguaggio dell'hardware
Per poter parlare con una macchina elettronica è necessario inviare segnali elettrici; i segnali che un calcolatore può comprendere sono on e off. Questi due stati sono rappresentati rispettivamente dai numeri 1 e 0; il linguaggio macchina può essere visto come una composizione di numeri in base 2, detti numeri binari, dove ogni "lettera" è una cifra binaria, detta bit. Un'istruzione è una stringa di bit comprensibile dal calcolatore.
Assembler (assemblatore) è un programma che converte una versione simbolica delle istruzioni (linguaggio assembler) in una versione binaria comprensibile alla macchina. In questo contesto, i compilatori dei linguaggi di programmazione ad alto livello si occupano di tradurre i programmi scritti in tali linguaggi nel corrispondente in linguaggio assembler.
I componenti di un calcolatore
Chip: dispositivo costituito da decine di milioni di transistor. Processore (CPU, Central Process Unit): è la parte attiva del calcolatore; contiene le unità di controllo e di elaborazione dati. È in grado di effettuare la somma di numeri, test su di essi, inviare segnali per attivare dispositivi di I/O ecc.
Datapath (unità di elaborazione dati): è il componente della CPU che provvede a eseguire le operazioni aritmetico-logiche. Unità di controllo: è il componente del processore che invia i comandi all'unità di elaborazione dati, alla memoria e ai dispositivi di I/UO secondo le istruzioni del programma. Memoria: è il luogo in cui vengono tenuti i programmi quando vengono eseguiti, assieme ai dati richiesti dalla loro esecuzione.
DRAM (Dynamic Random Access Memory): memoria costruita con circuiti integrati che permette l'accesso a ogni locazione nello stesso tempo. Memoria Cache: memoria piccola e veloce che agisce come un buffer per una memoria più grande e più lenta.
SRAM (Static Random Access Memory): memoria costruita con circuiti integrati, più veloce ma meno densa delle memorie DRAM. Memoria volatile: memoria in grado di mantenere i dati solamente se è alimentata (es. DRAM).
Memoria non volatile: memoria che conserva i dati anche quando viene a mancare l'alimentazione; viene usata per conservare i dati fra un'esecuzione e la successiva. Memoria principale: utilizzata per contenere i programmi durante la loro esecuzione (DRAM). Memoria di massa: è una memoria non volatile utilizzata per conservare i programmi e i dati fra un'esecuzione e la successiva. È tipicamente una memoria flash, mentre dei Personal Mobile è costituita da dischi magnetici nei server.
Hard disk: è una memoria secondaria non volatile, costituita da piatti rotanti ricoperti da materiale magnetico in grado di memorizzare informazioni binarie. Memoria flash: è una memoria non volatile a semiconduttori (silicio). È più lenta e meno costosa delle DRAM, più veloce e più costosa dei dischi rigidi.
Comunicare con altri calcolatori
- Comunicazione: le informazioni vengono scambiate fra i calcolatori
- Condivisione delle risorse: i vari calcolatori collegati alla rete possono condividere gli stessi dispositivi di I/O, invece di possederne ciascuno una copia privata
- Accesso non locale: collegando fra loro elaboratori posti a grande distanza, gli utenti non devono più essere fisicamente vicini al calcolatore che stanno utilizzando
LAN (Local Area Network): le reti locali sono progettate per trasportare dati in un'area geograficamente limitata, e forniscono sia il corretto instradamento della trasmissione sia la sicurezza nella comunicazione stessa.
WAN (Wide Area Network): sono le reti geograficamente più estese e sono l'ossatura di Internet, che supporta il web. Sono tipicamente realizzate con fibre ottiche.
Prestazioni
Il singolo utente di un calcolatore è interessato a ridurre il più possibile il tempo di esecuzione (risposta), cioè il tempo totale necessario al calcolatore per completare un task. I gestori dei centri di calcolo invece sono spesso interessati ad aumentare il throughput o la larghezza di banda, cioè il numero di task eseguiti nell'unità di tempo.
Quasi tutti i calcolatori sono costruiti utilizzando un segnale che sincronizza le varie funzioni implementate nell'hardware; questo segnale è periodico nel tempo e i relativi intervalli di tempo sono denominati cicli di clock. Dato che il compilatore genera delle istruzioni da eseguire e il calcolatore esegue le singole istruzioni per eseguire il programma, il tempo di esecuzione dovrà necessariamente dipendere dal numero delle istruzioni che compongono il programma.
È possibile esprimere il tempo di esecuzione totale come il risultato del prodotto del numero di istruzioni da eseguire per il tempo medio di esecuzione di ciascuna istruzione.
Numero di clock della CPU = Numero di istruzioni del programma × Numero medio di cicli clock per istruzione
Le istruzioni
Gli operandi dell'hardware del calcolatore
Scendendo di livello, diventiamo meno astratti e più concreti; il livello astratto omette dettagli, ma ci permette di trattare una maggiore complessità.
- Linguaggio ad alto livello: produttività e portabilità
- Linguaggio assembler: rappresentazione testuale
- Linguaggio macchina: dati in binario
Il passaggio dal codice sorgente all'esecuzione del programma richiede 3 fasi:
- Compilazione
- Linker
- Caricamento ed esecuzione
Studieremo l’ISA (Instruction Set Architecture) del MIPS, il cui obiettivo è massimizzare le prestazioni minimizzando i costi e riducendo i tempi di progetto. Parola (word): il numero di bit a cui si accede naturalmente in un calcolatore, tipicamente è un gruppo di 32bit.
I programmi e i dati sono codificati in binario e caricati in memoria per l’esecuzione; la CPU legge le istruzioni e i dati dalla memoria (Ciclo Fetch & Execute).
- CPU legge l’istruzione corrente, indirizzata dal Program Counter
- CPU usa i bit dell’istruzione per controllare le azioni da svolgere ed esegue l’istruzione
- CPU determina la prossima istruzione e ripete il ciclo.
Istruzioni aritmetico-logiche
A differenza dei programmi scritti nei linguaggi ad alto livello, gli operandi delle istruzioni aritmetiche devono essere scelti tra un numero limitato di locazioni, chiamate registri. Un'istruzione aritmetico-logica possiede tre operandi: i due registri contenenti i valori da elaborare (registri sorgente) e il registro contenente il risultato (registro destinazione). L'ordine è fisso: prima il registro contenente il risultato dell'operazione e poi i due operandi.
- Addizione
a = b + c; add $s0, $s1, $s2
addi $s1, $s2, 100 # add immediate – somma una costante
addu $s0, $s1, $s2 # add unsigned – evita overflow sommando numeri senza segno
addiu $s0, $s1, 100 # add immediate unsigned – somma costante evitando overflow - Moltiplicazione
Nella moltiplicazione il registro di destinazione è implicito; il risultato viene sempre posto in due registri dedicati denominati ehi lo. Il risultato va prelevato dai due registri utilizzando una speciale istruzione.
mult rs rt # moltiplica il contenuto di rs per il contenuto di rt
mfhi rd # move from hi – sposta il contenuto del registro hi nel registro rd
mflo rd # move from lo – sposta il contenuto del registro lo nel registro rd - Divisione
Come nella moltiplicazione, anche nella divisione il registro destinazione è implicito. Il quoziente della divisione è posto nel registro mentre il resto è posto nel registro lo, hi.
div rs rt # divide rs per rt - And e Or
- Array
L'elemento i-esimo di un array di troverà nella locazione di memoria dove è il br + 4*i br registro base, è l'indice ad alto livello e il fattore 4 dipende dall'indirizzamento al byte della memoria nel MIPS.
a = A[i];
Si assuma che i sia salvato in l'indirizzo del primo elemento dell'array (base address) sia $s1, contenuto nel registro (base register) e a sia in $s3 $s2.
sll $t1, $s1, 2 # registro $t1 contiene i*4
add $t2, $t1, $s3 # registro $t2 contiene A + i*4, ovvero $t2 = A[i]
lw $s2, 0($t2) # carico in $s2 il valore di A[i], a = $s2 = A[i] = $t2
Trasferimenti con la memoria
I linguaggi di programmazione possono utilizzare variabili semplici che sono composte da un singolo elemento, ma possono utilizzare anche strutture di dati più complesse, come i vettori e le strutture dati. Queste strutture complesse possono contenere un numero di elementi molto maggiore del numero di registri presenti nel calcolatore. Benché il processore possa contenere un limitato numero di dati nei registri, la memoria può contenere miliardi di dati; di conseguenza le strutture dati vengono allocate in memoria.
Nel linguaggio assembler le istruzioni aritmetiche richiedono che gli operandi siano memorizzati nei registri; l'assembler MIPS deve quindi contenere delle istruzioni di trasferimento dati che trasferiscono dati fra la memoria e i registri. La costante in un'istruzione di trasferimento si chiama offset (spiazzamento) e il registro usato per costruire l'indirizzo è detto registro base.
- Istruzione lw
L'istruzione di trasferimento che sposta un dato dalla memoria a un registro viene chiamata (carica). Ha tre argomenti: il registro destinazione in cui caricare la parola letta dalla memoria, una costante detta spiazzamento, e un registro base che contiene il valore dell'indirizzo base da sommare alla costante.
lw $s1, 100($s2) # Mem[$s2+100] -> $s1
Il registro destinazione è assegnato al valore contenuto all'indirizzo di memoria contenuto il $s1 (base register) sommato a 100 (offset). - Istruzione sw
L'istruzione di trasferimento che sposta un dato da un registro alla memoria viene chiamata (archivia). Possiede argomenti analoghi alla load word.
sw $s1, 100($s2) # $s1 -> Mem[$s2+100]
Alla parola di memoria con indirizzo è assegnato il valore contenuto nel registro $2 + 100 $s1.
Istruzioni di modifica del flusso di controllo
Normalmente, l'esecuzione è sequenziale:
- Il program counter (PC) indica dove si trova la prossima istruzione da eseguire
- Il flusso standard è: esegui l'istruzione all'indirizzo indicato dal PC e avanza all'istruzione successiva, incrementando il PC = PC+4
Le istruzioni per la modifica del flusso servono a forzare la modifica del PC rispetto al flusso standard sequenziale. Si può modificare il flusso con istruzioni di salto condizionato (branch) e incondizionato (jump).
- Salti condizionati
beq reg1, reg2, ind_salto # salta a ind_salto se reg1==reg2
bne reg1, reg2, ind_salto # salta a ind_salto se reg1!=reg2 - Salti incondizionati
j indirizzo # salta a indirizzo
jal indirizzo # salta a indirizzo, ma si ricorda come tornare indietro salvando PC+4 (istruzione successiva) nel registro speciale $ra
jr reg # salta all'indirizzo specificato nel registro PC = reg
jr $ra – implementa la return da una procedura
Esempio: If – Then - Else
Nel seguente frammento di codice C ci sono cinque variabili che corrispondono ai registri: f - $s0, g - $s1, h - $s2, i - $s3, j - $s4.
if ( i==j ) f = g + h; else f = g – h; bne $3, $s4, Else # se $s3 != $s4 (i!=j) vai a Else add $s0, $s1, $s2 # f = g + h (saltata se i!=j) j Esci # vai a Esci Else: sub $s0, $s1, $s2 # f = g - h (saltata se i==j) Esci: …
Esempio: Ciclo while
Supponiamo che e corrispondano ai registri e e che l'indirizzo base del vettore salva i k $s3 $s5 sia contenuto in $s6.
while ( salva[i] == k ) i += 1;
Il primo passo consiste nel caricare in un registro temporaneo, esempio salva[i] $t1. Ciclo: sll $st1, $s3, 2 # $t1 = i * 4, moltiplico x4 per ottenere byte corretto. Per ottenere l'indirizzo di è sufficiente sommare all'indirizzo base di salva in $t1 $s6 add $t1, $t6, $t1 # $t1 = indirizzo di salva[i]. A questo punto si può usare questo indirizzo per caricare il valore di salva[i] lw $t0, 0($t1) # $t0 = salva[i]
Adesso si esegue il controllo di uscita dal ciclo bne $t0, $s5, Esci # se salva[i] != k vai a Esci. L'istruzione successiva somma 1 a i addi $s3, $s3, 1 # i = i + 1. Alla fine del ciclo, c'è un salto indietro all'inizio del ciclo j Ciclo Esci:
Etichette
Nelle istruzioni in linguaggio macchina si usano gli indirizzi: per un programmatore assembler non è possibile conoscere esplicitamente l'indirizzo numerico di dati/istruzioni, per questo si usano etichette (label) che si associano a specifici punti del programma. Sarà poi compito dell'assemblatore tradurre le etichette nei corrispondenti indirizzi.
Funzioni
Una funzione (procedura) è un sottoprogramma memorizzato che svolge un compito specifico basandosi sui parametri che gli vengono passati in ingresso. Le funzioni costituiscono uno degli strumenti utilizzati dai programmatori per organizzare i programmi in modo da renderli più comprensibili e per permettere il riutilizzo del codice. L'interfaccia fra la procedura e il resto del programma e dei dati è costituita dai parametri, i quali permettono di passare dei valori alla procedura e di restituire i risultati alla porzione di programma in cui essa è stata chiamata.
- Quattro registri argomento per il passaggio dei parametri $a0 - $a3
- Due registri valore per la restituzione dei valori calcolati $v0 - $v1
- Un registro contenente l'indirizzo di ritorno per tornare al punto di origine $ra
L'istruzione jump-and-link permette di eseguire un salto ad un dato indirizzo e contemporaneamente salvare nel registro l'indirizzo dell'istruzione successiva a quella di $ra salto (indirizzo di ritorno). jal indirizzo_funzione L'indirizzo di ritorno consente a una procedura di restituire il controllo al punto corretto del programma chiamante, ed è necessario perché la stessa procedura può essere chiamata da diversi punti del programma.
I calcolatori utilizzano l'istruzione jump-register che comanda un salto incondizionato all'indirizzo specificato in un registro; salta all'indirizzo memorizzato nel registro $ra. jr $ra Il programma chiamante, ovvero un programma che invoca una funzione e le fornisce i parametri necessari, mette i valori dei parametri da passare alla funzione nei registri da $a0 e utilizza l'istruzione per saltare alla funzione X. $a3 jal X La funzione chiamata, ovvero una procedura che esegue una serie di istruzioni...
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
-
Architettura web/Architettura internet
-
Tesina Architettura dei calcolatori
-
Architettura dei Calcolatori
-
Appunti Architettura dei calcolatori