Laboratorio di Architettura degli Elaboratori
Dott. Massimo Tivoli
Set di istruzioni del MIPS32: istruzioni aritmetiche e di trasferimento
Istruzioni • (Alcune) Categorie di istruzioni in MIPS
– Istruzioni aritmetico/logiche
• Queste istruzioni effettuano operazioni aritmetico‐
logiche sui registri del processore
– Istruzioni “Load and Store”
• Queste istruzioni spostano dati fra la memoria e i registri generali del processore
– Istruzioni decisionali
• Queste istruzioni effettuano il confronto fra i valori contenuti nei registri
Istruzioni Aritmetiche
●
add a, b, c
#a=b+c
●
sub a, b, c
#a=b-c
–
TRE operandi
●
●
OPERATORE operando1, operando2, operando3
NOTE:
–
Ciascuna linea puo’ contenere solo una istruzione;
–
# viene usato per commenti
●
add a, b, c # Questa istruzione esegue la somma
a=b+c
Istruzioni Aritmetiche
• Note:
– Tutte le istruzioni aritmetiche hanno esattamente tre operandi
(numero fisso) per mantenere l’Hw semplice
– L’hardware necessario per un numero variabile di operandi è più complesso di quello richiesto per un numero fisso di operandi
⇓
PRINCIPIO DI PROGETTO 1: semplicita’ e regolarita’ sono strettamente correlate
– Ordine fissato (destinatario per primo)
• OPERATORE operando1, operando2, operando3
⇓
• operando1 = operando2 OPERATORE operando3
*
Esercizio
•
Scrivere la seguente istruzione in assembler MIPS:
a = (b+c) – (d‐f) + g
add x, b, c
sub y, d, f
sub x, x, y
add a, x, g
• Quante operazioni aritmetiche ci vogliono per sommare/sottrarre/etc. n numeri?
Registri (continua…)
• Data una istruzione aritmetica:
– Operandi = Registri
– MIPS32 ha 32 registri, di uso generale, a 32 bit • Variabili ≠ Registro:
– Variabili in un LP‐alto‐livello sono infinite
– I registri nell’Hw sono finiti
– In un LP‐alto‐livello le variabili posso far riferimento sia a registri che a locazioni di memoria che non sono registri (in modo trasparente al programmatore)
• Un numero di registri elevato aumenterebbe la durata del ciclo di clock
– i segnali elettrici devono coprire una distanza maggiore
• Maggiore è il numero dei registri e maggiore è il numero di bit necessari per indirizzarli all’interno di una istruzione
– ricordate sempre che per la macchina add x, b, c = 1000110010100000…
PRINCIPIO DI PROGETTO 2: Minori sono le dimensioni, maggiore e’ la velocita’
Registri e loro uso
• Notazione per l’assembler del MIPS32
– nome costituito da due caratteri preceduti dal carattere ‘$’
– $s0, $s1, … per i registri che corrispondono a variabili nei programmi scritti in un LP‐alto‐livello da compilare in linguaggio assembly per MIPS32
– $t0, $t1, … per i registri temporanei necessari alla compilazione di programmi in istruzioni MIPS32
• a = (b+c) – (d‐f) + g
add $t0, $s0, $s1
sub $t1, $s2, $s3
sub $t0, $t0, $t1
add $s5, $t0, $s4
# il reg. temp. $t0 contiene il ris. di b+c (i.e., $s0+$s1)
# il reg. temp. $t1 contiene il ris. di d‐f (i.e., $s2‐$s3)
# il reg. temp. $t0 contiene il ris. di (b+c) – (d‐f)
# il reg. $s5 contiene il ris. di (b+c) – (d‐f) + g
(parte della) Architettura del MIPS32
MAR
Abbiamo solo 32 registri… come facciamo a gestire
strutture dati
complesse (es. vettori)???
32 Registri,
ognuno a 32 bit
Memoria
R1
R32
MBR
MEMORIA
oppure
cosa facciamo se
32 var. non mi
bastano???
32 bit
R1 R2 … Rn
ALU
CONTROLLO
CPU
32 registri
Istruzioni di Trasferimento
• lw $s1, 10($s2) # carica in $s1 l’undicesimo “valore” del vettore che inizia alla
# locazione, in memoria, il cui indirizzo è il valore di $s2
–
lw = Load word (si ricordi che 1 word = 32 bit per il MIPS32)
• sw $s1, 100($s2)
–
●
sw = Store word
NOTE e delucidazioni:
–
Memoria vista come un VETTORE
–
Le istruzioni aritmetiche richiedono che gli operandi
siano memorizzati nei registri
●
Istruzioni di “Trasferimento”
–
“ Indirizzo di base (e.g., $2,$3) + offset (e.g., 10,100)
–
“ Memoria indirizzata a singolo byte (vedi slides succ.)
Attenzione
•
La memoria è indirizzata al singolo byte
– la mem. è vista come una sequenza lineare di celle (o locazioni)
da 8 bit = 1 byte
(da 0x00000000 a 0xFFFFFFFF, fino a 4GB di mem. indirizzabili)
MEM
…
mentre
•
•
I registri sono indirizzati a 32 bit e un registro
contiene un dato a 32 bit (= 4 byte = 4 locazioni)
=> l’indirizzo di una word, semanticamente valida,
in memoria è sempre l’indirizzo, di una locazione,
che è multiplo di 4
Vogliamo caricare il 3° elemento del vettore A:
ovvero vogliamo prelevare il valore di A[2]
(iniziamo a numerare gli elementi di un
vettore da 0, cioè A[0] è il primo elemento
del vettore)
Cosa vuol dire??
0x1000 000F
0x1000 000E
0x1000 000D
0x1000 000C
0x1000 000B
0x1000 000A
0x1000 0009
0x1000 0008
0x1000 0007
0x1000 0006
0x1000 0005
0x1000 0004
0x1000 0003
0x1000 0002
0x1000 0001
0x1000 0000
Word i+3
Word i+2
Word i+1
Word i
1 byte
(8 bit)
…
Attenzione
•
Vogliamo caricare il 3° elemento (ovvero la 3° word)
del vettore A: ovvero vogliamo prelevare il valore di A[2] dove MEM
– A è memorizzato a partire dalla locazione 0x1000 0000
– supponiamo che $s2 contenga proprio il numero 0x10000000
A
– lw $s1, 2($s2)
– lw $s1, 8($s2)
…
Word i+3
Word i+2
A[2]
– Indirizzo di base (a 32 bit) + offset (a 16 bit)
Word i+1
– “Big end” e “Little end”
Word i
– Che succede quando il numero di variabili
nel LP‐alto‐livello supera il numero di
registri?
• “Spilling” dei registri
1 byte
(8 bit)
…
perchè 16 bit sarà chiaro
più avanti nel corso
0x1000 000F
0x1000 000E
0x1000 000D
0x1000 000C
0x1000 000B
0x1000 000A
0x1000 0009
0x1000 0008
0x1000 0007
0x1000 0006
0x1000 0005
0x1000 0004
0x1000 0003
0x1000 0002
0x1000 0001
0x1000 0000
Little Endian e Big Endian (continua…)
•
Come viene rappresentata una word del MIPS32 (quindi un numero a 32 bit) in 4 byte di memoria?
– 0001 0010 0011 0100 0101 0110 0111 1000 = 0x12345678
•
Esistono due schemi:
– Little Endian: memorizza a partire dalla "little end" (ovvero a partire dai bit meno significativi) della word
• cioe’, 0111 1000
registro:
0x12
0x34
0x56
0x78
byte 3
byte 2
byte 1
byte 0
– Big Endian: memorizza a partire dalla "big end" (ovvero dai bit più significativi) della word
• cioe’, 0001 0010
registro:
•
MIPS lavora in Big Endian
0x78
0x56
0x34
0x12
byte 3
byte 2
byte 1
byte 0
– Infatti, l’indirizzo di base 0x10000000, in memoria, viene specificato tramite il
contenuto di un registro a 32 bit, $s2 nell’esempio precedente, che contiene
proprio il numero 0x10000000 che però è memorizzato come
byte3: 00 byte2: 00 byte1: 00 byte0: 10
Little Endian e Big Endian
• Nell’esempio precedente avevamo:
– indirizzo di base + offset
ovvero:
– 8($s2) = $s2 + 8 = 0x10000000 + 0x0008 =
0x10000000 + 0x00000008 = 0x10000008
ovvero (in formato Big Endian):
$s2:
0x00
0x00
0x00
0x10
byte 3
byte 2
byte 1
byte 0
+
8:
0x08
0x00
0x00
0x00
byte 3
byte 2
byte 1
byte 0
0x08
0x00
0x00
0x10
byte 3
byte 2
byte 1
byte 0
=
Spilling
• In memoria si mettono le variabili meno usate
• Ricorda: gli operandi aritmetici sono registri, non celle di memoria
– tempo accesso ai registri e’ minore
– 1 ciclo di clock:
• lettura due registri, • esecuzione operazione • scrittura risultato
*
Organizzazione della memoria
Global pointer
‐ offset a 16bit (4 cifre hex)
‐ permette di prelevare dati
con un sola lw
‐ (0x10010020 = 0x8020($gp))
Static Data
Dati statici
Text
Codice del programma (“text”)
Esempio
• Scrivere in assembly la seguente assegnazione
– A[14] = b + A[6] con bÆ $s1, base(A) Æ $s0
lw $t0, 24($s0)
add $t0, $s1, $t0
sw $t0, 56($s0)
Vettori con indici variabili
•
Consideriamo
$s3
$s1
a = b + A[i]
•
Informalmente: $s4
$s2
– Carica A[2] = lw $t0, 8($s3)
– Carica A[i] = 4*$s4 + $s3 – = $s4+$s4+$s4+$s4+$s3
– b+A[i] = $s2+$s4+$s4+$s4+$s4+$s3
•
Formalmente:
–
–
–
–
–
add $t1, $s4, $s4
add $t1, $t1, $t1
add $t1, $t1, $s3
lw $t0, 0($t1)
add $s1, $s2, $t0
ricordate che
per esprimere
l’offset si hanno a
disposizione solo
16 bit
•
Esercizio
Scrivere in assembly la seguente istruzione:
– A[4] = b + A[i]
• Base A Æ $s1
• b Æ $s2
• i Æ $s3
•
Scrivere in pseudo‐C il seguente codice Assembly:
–
–
–
–
–
–
–
add $t1, $s2, $s2
add $t1, $t1, $t1
add $t1, $t1, $s1
lw $t0, 0($t1) lw $t1, 16($s1)
add $t1, $t1, $t0
sw $t1, 12($s1)
Esercizio
• Cominceremo la prossima lezione realizzando insieme (voi!) gli esercizi precedenti