Assembler MIPS
Assembler MIPS
Architettura MIPS
Architettura RISC sviluppata da John Hennessy nel 1981 Usata da NEC, Nintendo, Silicon Graphics, Sony (Playstation), ecc. Architettura load-store Simile ad altre architetture RISC
Notazione
Operazioni aritmetiche: Somma add a, b, c fa la somma di b e c e il risultato posto in a Ciascuna istruzione aritmetica MIPS esegue una sola operazione e contiene 3 operandi Es. sommare b, c, d, e e porre il risultato in a add a, b, c # a = b+c add a, a, d # a = a + d (=b+c+d) add a, a, e # a = a + e (= b+c+d+e) Ogni linea contiene unistruzione; i commenti sono preceduti da #
3
Notazione
Sottrazione sub a, b, c #a=b-c Esempio: frammento di programma a=b+c d=ae viene tradotto in assembler MIPS come: add a, b, c sub d, a, e
Esempio
Compilare listruzione C seguente f = (g + h) (i + j) dove le variabili f, g, h, i, j vengono fatte corrispondere ai registri $s0, $s1, $s2, $s3, $s4 Il programma compilato sar: add $t0, $s1, $s2 # $t0 contiene g+h add $t1, $s3, $s4 # $t1 contiene i+j sub $s0, $t0, $t1 # $s0 assume $t0-$t1 cio f =(g+h) (i+j)
6
Indirizzi virtuali
Gli indirizzi di memoria che incontriamo non sono indirizzi fisici, ma indirizzi virtuali, in quanto larchitettura MIPS, come molte altre, implementa la memoria virtuale. La memoria virtuale una tecnica che permette di simulare una grande quantit di memoria avendo a disposizione una piccola quantit di memoria fisica (RAM). Con indirizzi virtuali di 32 bit si possono indirizzare fino a 4GB di memoria virtuale (da 0x00000000 a 0xFFFFFFFF). Un meccanismo di traduzione implementato via hardware e software (S.O.) traduce gli indirizzi virtuali in indirizzi fisici.
9
La memoria virtuale
Uno spazio dindirizzamento virtuale permette di raggiungere i seguenti obiettivi: Condivisione in maniera efficiente sicura della memoria e della CPU tra molti programmi. Eliminazione delle difficolt di programmazione legate ad una quantit piccola e limitata di memoria principale.
Un programma, compilato in uno spazio di indirizzamento virtuale, ha quindi un proprio spazio di indirizzamento separato da quello degli altri programmi consentendo la condivisione e protezione di cui sopra. Pu superare le dimensioni della memoria principale e non necessario che occupi un blocco contiguo di memoria. La gestione della memoria da assegnare ai programmi quindi semplificata (es.: problemi di rilocazione, overlay).
10
Indirizzamento a byte
Il MIPS indirizza il singolo byte (8 bit) Lindirizzo punta al primo byte della parola (in una parola ci sono 4 byte). Gli indirizzi di due parole consecutive differiscono di 4 unit Nel MIPS le parole iniziano sempre ad indirizzi multipli di 4 (vincolo di allineamento) Quindi, nellistruzione precedente, occorreva fare lw $t0, 32($s3)
11
Indirizzi
8 7 6 5 4 3 2 1 0
00001010 10000100 01011100 01000001 11001000 00000110 11001110 00110101 10100110 byte
word / parola
word / parola
12
14
15
Indice variabile
Si supponga che laccesso a un vettore avvenga con indice variabile Es. : g = h + A[i] Lindirizzo base di A sia in $s3 e alle variabili g, h, i siano associati i registri $s1, $s2, $s4 mul $t1, $s4, 4 # i = i*4 add $t1, $t1, $s3 # indirizzo di A[i] in $t1 lw $t0, 0($t1) # carica A[i] in $t0 add $s1, $s2, $t0 # g = h + A[i]
16
In pratica useremo la pseudoistruzione mul mul rdest, rsrc1, rsrc2 che mette il prodotto fra rsrc1 e rsrc2 nel registro rdest
17
La traduzione di mul
18
Salti condizionati
Istruzioni beq e bne sono utilizzate per tradurre gli if dei linguaggi di alto livello beq registro1, registro2, L1 Vai allistruzione etichettata con L1, se il valore contenuto in registro1 uguale al valore contenuto in registro2 (beq = branch on equal) bne registro1, registro2, L1 Vai allistruzione etichettata con L1, se il valore contenuto in registro1 diverso dal valore contenuto in registro2 (bne = branch on not equal)
19
Esempio
Frammento di codice C (goto deprecato!): if (i = = j) goto L1; f = g + h; L1: f = f i; Supponendo che f, g, h, i, j corrispondano ai registri $s0, $s1, $s2, $s3, $s4, la traduzione la seguente
beq add L1: sub $s3, $s4, L1 $s0, $s1, $s2 $s0, $s0, $s3 # va a L1 se i uguale a j #f=g+h #f=f-i
20
Salto incondizionato
Istruzione j (jump)
J LABEL
Vai allistruzione etichettata con LABEL. Lassemblatore sostituir letichetta con lindirizzo appropriato.
21
Cicli
Frammento di codice C: Ciclo: g = g + A[i]; i = i + j; if (i != h) goto Ciclo; Supponiamo che le variabili g, h, i, j siano associate ai registri $s1, $s2, $s3, $s4 e lindirizzo di partenza del vettore A sia in $s5. La traduzione la seguente: Ciclo: mul $t1, $s3, 4 # $t1 = i * 4 add $t1, $t1, $s5 # $t1 = indirizzo di A[i] lw $t0, 0($t1) # $t0 = A[i] add $s1, $s1, $t0 # g = g + A[i] add $s3, $s3, $s4 #i=i+j bne $s3, $s2, Ciclo # salta a Ciclo se i j
23
Ciclo while
Frammento di codice C: while (salva[i] = = k) i = i + j; Supponendo che i, j, k corrispondano ai registri $s3, $s4, $s5 e lindirizzo base di salva sia in $s6. La traduzione la seguente: Ciclo: mul $t1, $s3, 4 # $t1 = i * 4 add $t1, $t1, $s6 # $t1 = indirizzo di salva[i] lw $t0, 0($t1) # $t0 = salva[i] bne $t0, $s5, Esci # vai a Esci se salva[i] k add $s3, $s3, $s4 # i = i + j j Ciclo # vai a Ciclo Esci: Si usano 1 salto condizionato e 1 salto incondizionato
24
Ottimizzazione
Codice ottimizzato (con un solo salto condizionato)
Ciclo: mul add lw add beq sub $t1, $s3, 4 $t1, $t1, $s6 $t0, 0($t1) $s3, $s3, $s4 $t0, $s5, Ciclo $s3, $s3, $s4 # $t1 = i * 4 # $t1 = indirizzo di salva[i] # $t0 = salva[i] #i=i+j # vai a Ciclo se salva[i]==k #i=ij
25
slt
Istruzione slt (set on less than): poni a 1 il valore di registro1 se il valore di registro2 minore del valore di registro3, in caso contrario poni a 0 il valore di registro1 Inoltre, il registro $zero che contiene sempre il valore 0, un registro di sola lettura che pu essere usato nelle condizioni relazionali Esempio:
slt bne $t0, $s0, $s1 $t0, $zero, Minore # $t0 diventa 1 se $s0 < $s1 # vai a Minore se $t0 0
26
Ciclo for
Frammento di programma C: for (i=0; i<k; i++) f = f + A[i]; siano i, k, f corrispondenti a $s1, $s2, $s3, supponendo che $s1 valga 0 allinizio, e lindirizzo base di A in $s4. La traduzione : Ciclo: slt beq mul add lw add addi j $t2, $s1, $s2 $t2, $zero, Esci $t1, $s1, 4 $t1, $t1, $s4 $t0, 0($t1) $s3, $s3, $t0 $s1, $s1, 1 Ciclo # poni $t2 a 1 se i < k # se $t2 = 0 vai a Esci # $t1 = i * 4 # $t1 = indirizzo di A[i] # $t0 = A[i] # f = f + A[i] #i=i+1
Esci:
27
Case/switch
Frammento di programma C:
switch (k) { case 0: f = i + j; break; case 1: f = g + h; break; case 2: f = g h; break; case 3: f = i j; break; }
Si potrebbe trasformare in una catena di if-then-else e quindi tradurre di conseguenza con salti condizionati A volte per le diverse alternative possono essere specificate memorizzandole in una tabella di indirizzi in cui si trovano le diverse sequenze di istruzioni (tabella degli indirizzi di salto o jump address table) Il programma deve riconoscere un indice per saltare alla sequenza di codice opportuna La tabella un vettore di parole che contiene gli indirizzi corrispondenti alle etichette presenti nel codice
28
Istruzione jr
Istruzione jr (jump register): istruzione di salto tramite registro: effettua un salto incondizionato allindirizzo specificato in un registro Premessa per la traduzione del case/switch Si assuma che f, g, h, i, j, k corrispondano ai registri da $s0 a $s5 e che $t2 contenga il valore 4 La variabile k usata per indicizzare la tabella degli indirizzi di salto Sia in $t4 lindirizzo di partenza della tabella dei salti Si supponga che la tabella contenga in sequenza gli indirizzi corrispondenti alle etichette L0, L1, L2, L3
29
30
Le procedure
Durante lesecuzione di un procedura il programma deve seguire i seguenti passi:
1. Mettere i parametri della procedura in un luogo accessibile alla procedura 2. Trasferire il controllo alla procedura 3. Acquisire le risorse necessarie alla memorizzazione dei dati 4. Eseguire il compito richiesto 5. Mettere il risultato in un luogo accessibile al programma chiamante 6. Restituire il controllo al punto di origine
31
Listruzione jal
Il MIPS alloca i seguenti registri per le chiamate di procedura: $a0-$a3: 4 registri argomento per il passaggio dei parametri $v0-$v1: 2 registri valore per la restituzione dei valori $ra: registro di ritorno per tornare al punto di origine Istruzione jal (jump-and-link): listruzione apposita per le procedure, che salta a un indirizzo e contemporaneamente salva lindirizzo dellistruzione successiva nel registro $ra jal IndirizzoProcedura In pratica jal salva il valore di PC+4 nel registro $ra (cio il valore del Program Counter + 4, che contiene lindirizzo della prossima istruzione) Questo crea un collegamento allindirizzo di ritorno dalla procedura Lindirizzo di ritorno necessario perch la stessa procedura pu essere richiamata in pi parti del programma
32
jr
$ra
Il programma chiamante mette i valori dei parametri da passare alla procedura nei registri $a0-$a3 e utilizza listruzione jal X per saltare alla procedura X (programma chiamato) Il programma chiamato esegue le operazioni richieste, memorizza eventualmente i risultati nei registri $v0-$v1 e restituisce il controllo al chiamante con listruzione jr $ra
33
Lo stack
Spesso, sono necessari pi registri per i parametri di una procedura e i valori da restituire Lo stack (pila) una struttura del tipo last-in first-out (LIFO) dove una procedura pu memorizzare i registri e dove pu recuperare i vecchi valori dei registri In generale il processo di allocare in memoria le variabili usate meno frequentemente o usate in fasi successive del programma, si chiama riversamento (spilling) dei registri. Si usa un puntatore allo stack (stack pointer) che contiene lindirizzo del dato introdotto pi recentemente nello stack Per ragioni storiche lo stack cresce a partire da indirizzi di memoria alti verso indirizzi di memoria bassi: quando vengono inseriti dei dati nello stack il valore dello stack pointer diminuisce, viceversa, quando sono estratti dati dallo stack, il valore dello stack pointer aumenta Il registro allocato dal MIPS come stack pointer $sp I termini push e pop sono comunemente usati per indicare rispettivamente la memorizzazione e lestrazione di un dato dallo stack.
34
400000hex
Reserved
35
36
Procedure annidate
Il programma principale chiama una certa procedura A passandole dei parametri, la procedura A chiama a sua volta una procedura B passandole dei parametri Occorre salvare nello stack tutti i registri che devono essere preservati: Il programma chiamante (caller) memorizza nello stack i registri argomento $a0 - $a3 o i registri temporanei $t0 - $t9 di cui ha ancora bisogno dopo la chiamata Il programma chiamato (callee) salva nello stack il registro di ritorno $ra, se chiama altre procedure, e gli altri registri $s0 - $s7 che utilizza, nel caso non siano sufficienti i registri temporanei $t0 - $t9.
Una procedura che chiama unaltra procedura sia chiamato che chiamante. Lutilizzo dei registri e la gestione dello stack illustrata dallesempio seguente.
37
Esercizio: scrivere una procedura in assembler MIPS, che riceva in ingresso lindirizzo di una stringa ed un numero che, se pari a 0, determina la conversione dei caratteri in minuscolo altrimenti i caratteri vengono convertiti in maiuscolo. Per la conversione del singolo carattere si supponga di utilizzare le funzioni toupper e tolower.
Scrivere una bozza del corpo del programma:
move $t0, $zero loop: addu $t1, $t0, $a0 lb $t2, 0($t1) beq $t2, $zero, esci move $a0, $t2 #err. si perde a0 beq $a1, $zero, tolow jal toupper j skip tolow: jal tolower skip: sb $v0, 0($t1) #err. t1 variato addi $t0, $t0, 1 #err. t0 variato j loop esci:
38
Procedere correggendo i registri: in particolare le chiamate alle funzioni possono modificare i registri $a0, $a1 e $t0, per cui bisogna utilizzare dei registri s. Apportare inoltre delle migliorie.
move $s0, $a0 move $s1, $a1 loop: lb $t0, 0($s0) beq $t0, $zero, esci move $a0, $t0 beq $s1, $zero, tolow jal toupper j skip tolow: jal tolower skip: sb $v0, 0($s0) addiu $s0, $s0, 1 j loop esci:
39
Completare il programma gestendo il salvataggio tramite lo stack dei registri s utilizzati e del registro ra che viene modicato dalle funzioni annidate. Gestire infine il ritorno al programma chiamante.
p: subu $sp, $sp, 12 sw $ra, 0($sp) sw $s0, 4($sp) sw $s1, 8($sp) [corpo del programma] esci: lw $ra, 0($sp) lw $s0, 4($sp) lw $s1, 8($sp) addiu $sp, $sp, 12 jr $ra
40
$sp
In caso di procedure ricorsive bisogna considerare che programma chiamato e chiamante coincidono.
42
$sp, $sp, 8 $ra, 4($sp) $a0, 0($sp) $t0, $a0, 1 $t0, $zero, L1 $v0, $zero, 1 $sp, $sp, 8 $ra $a0, $a0, 1 fatt $a0, 0($sp) $ra, 4($sp) $sp, $sp, 8 $v0, $a0, $v0 $ra
# aggiornamento dello stack per fare # spazio a 2 elementi # salvataggio del registro di ritorno (come # programma chiamato) # salvataggio del parametro n (come # programma chiamante) # test per n < 1 # se n >= 1 salta a L1 # restituisce 1 (per n<1) # aggiornamento dello stack # ritorno allistruzione successiva a jal # n > 1: largomento diventa n-1 Modifica # chiamata a fatt con (n-1) di $a0 # ritorno da jal: ripristino di n # ripristino del registro di ritorno # aggiornamento dello stack # restituzione di n * fatt (n-1) # ritorno al programma chiamante
43
3. 4.
5.
44
Indirizzamento immediato
stato pensato per rendere veloce laccesso a costanti di piccole dimensioni (216 o 215) I programmi usano spesso costanti, ad esempio per: incrementare un indice di un vettore, contare il numero di iterazioni in un ciclo, aggiornare il puntatore allo stack Con le istruzioni viste, sarebbe necessario caricare la costante in memoria prima di poterla utilizzare Ad esempio, listruzione add $sp, $sp, 4 in realt non esatta. Assumendo che IndCostante4 sia lindirizzo di memoria in cui si trova la costante 4, occorrerebbe fare lw $t0, IndCostante4($zero) # $t0 = 4 add $sp, $sp, $t0
45
Indirizzamento immediato
In pratica, si usano versioni particolari delle istruzioni aritmetiche in cui uno degli operandi una costante La costante contenuta dentro listruzione Il formato di queste istruzioni lo stesso di quelle di trasferimento dati e dei salti condizionati: cio formato-I (dove I sta per immediato) Listruzione precedente diventa quindi addi $sp, $sp, 4 Il codice macchina in formato decimale, dove il codice operativo di addi 8 e il numero corrispondente al registro $sp 29, il seguente
op 8 rs 29 rt 29 immediato 4
Per controllare se il valore nel registro $s2 minore di 10 si pu scrivere slti $t0, $s2, 10 # $t0 = 1 se $s2 < 10
46
Istruzione branch on not equal bne $s0, $s1, Esci # vai Esci se $s0 diverso da $s1
5 6 bit 16 5 bit 17 5 bit Esci 16 bit
Lindirizzo PC-relative si riferisce al numero di parole che lo separano dalla destinazione Significa quindi che nellistruzione bne la destinazione del salto si ottiene sommando 2x4=8 byte allindirizzo dellistruzione successiva (poich il PC contiene gi lindirizzo dellistruzione successiva: stato infatti incrementato nella fase preliminare dellesecuzione dellistruzione corrente)
49
Indirizzamento pseudo-diretto
Se lindirizzo specificato in un salto condizionato ancora troppo lontano, lassembler risolve il problema inserendo un salto incondizionato al posto di quello condizionato invertendo la condizione originale beq $s0, $s1, L1 diventa bne $s0, $s1, L2 j L1 L2: I 26 bit allinterno dellistruzione jump contengono un indirizzo in parole, equivalgono quindi a 28 bit che vengono concatenati con i 4 bit pi significativi del PC (indirizzamento pseudo-diretto).
50
Indirizzamento pseudo-diretto
Con 28 bit riesco ad indirizzare 228 byte ovvero 256MB equivalenti a 64M istruzioni, allinterno per del blocco di memoria i cui indirizzi hanno i 4 bit pi significativi pari ai 4 bit pi significativi dellindirizzo in cui contenuta listruzione jump. Il loader ed il linker devono fare in modo che il programma stia allinterno di un tale blocco di 256MB, diversamente si ricorre ad una jump register, che pu indirizzare 4GB con la necessit di un istruzione aggiuntiva che carichi lindirizzo desiderato in un registro.
51
I 5 modi di indirizzamento
1. Immediate addressing op rs rt Immediate 2. Register addressing op rs rt rd ... funct Registers Register
Register
Byte
Halfword
Word
PC
Word
PC
Word
52
op
rs
rt
rd
shamt
funct
op
rs
rt
address
op
address
53
rs
5 bit
rt
5 bit
rd
5 bit
shamt
5 bit
funct
6 bit
op: codice operativo rs: primo operando sorgente (registro) rt: secondo operando sorgente (registro) rd: registro destinazione shamt: shift amount (per operazioni di scalamento) funct: seleziona una variante specifica delloperazione base definita nel campo op
op
rs
rt
address
rs: registro base al cui contenuto va sommato address rt: primo registro che compare nellistruzione (registro destinazione per lw e registro sorgente per sw)
54
32
Pseudoistruzioni
Lassemblatore pu anche trattare versioni modificate delle istruzioni in linguaggio macchina come se fossero istruzioni vere e proprie Queste istruzioni sono dette pseudoistruzioni e permettono di semplificare le fasi di traduzione e di programmazione Consentono allassembler MIPS di avere un insieme di istruzioni pi ricco Esempio: istruzione move move $t0, $t1 # il registro $t0 assume il valore del registro $t1 questa istruzione viene accettata dallassemblatore e convertita in: add $t0, $zero, $t1 Listruzione blt (branch on less than) viene convertita nelle due istruzioni slt e bne; e una cosa simile succede per bgt (branch on greater than), bge (branch on greater/equal than), ble (branch on less/equal than)
57
SPIM
SPIM (MIPS letto al contrario) un simulatore software che permette lesecuzione di programmi scritti per i processori MIPS R2000/R3000. Contiene un debugger e fornisce servizi analoghi a quelli di un sistema operativo. Esegue direttamente programmi scritti in assembler. Utilizza lordinamento dei byte proprio dellhardware su cui gira, per cui PCSpim, la versione per larchitettura Intel 80x86, little-endian. Utile per studiare i calcolatori ed i programmi eseguiti su di esso.
58
Risultato
intero (in $v0) virgola mobile (in $f0) doppia precisione (in $f0) $a0=buffer, $a1=lunghezza $a0=quantit indirizzo (in $v0)
Direttive allassemblatore
I nomi che iniziano con un punto specificano allassemblatore come tradurre un programma ma non generano istruzioni macchina Esempi: .data (indica che le linee seguenti contengono dati) .text (indica che le linee seguenti contengono istruzioni) .asciiz (copia in memoria una stringa terminandola con Nul) I nomi seguiti dai due punti sono etichette che associano un nome alla locazione di memoria successiva Esempi: str: main:
62
2. Caricare in $v0 il codice della chiamata di sistema per la stampa di una stringa, che 4, e caricare in $a0 lindirizzo della stringa (str) da stampare, e infine chiamare una system call
li $v0, 4 la $a0, str syscall # codice della chiamata di sistema per print_string # indirizzo della stringa da stampare # stampa della stringa
3. Caricare in $v0 il codice della chiamata di sistema per la stampa di un intero, che 1, e caricare in $a0 il numero intero da stampare che stato accumulato in $s1, e infine chiamare una system call
li $v0, 1 move $a0, $s1 syscall # codice della chiamata di sistema per print_int # numero intero da stampare
64
ciclo:
li $v0, 4 la $a0, str syscall li $v0, 1 move $a0, $s1 syscall .data str:
I numeri vengono inseriti uno alla volta dando invio dopo ciascuno
66
ciclo:
fine:
str:
67
t0 = t0 XOR t1
69
Funzione sn
sn(x, k) restituisce il numero delle somme di k addendi che danno x (x e k sono quindi interi positivi) ed cos definita:
70
Funzione sn
x\k 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 3 0 0 0 1 1 2 3 4 5 7 8 10 12 14 16 19 21 24 27 30 33 4 0 0 0 0 1 1 2 3 5 6 9 11 15 18 23 27 34 39 47 54 64 5 0 0 0 0 0 1 1 2 3 5 7 10 13 18 23 30 37 47 57 70 84 6 0 0 0 0 0 0 1 1 2 3 5 7 11 14 20 26 35 44 58 71 90 7 0 0 0 0 0 0 0 1 1 2 3 5 7 11 15 21 28 38 49 65 82 8 0 0 0 0 0 0 0 0 1 1 2 3 5 7 11 15 22 29 40 52 70 9 0 0 0 0 0 0 0 0 0 1 1 2 3 5 7 11 15 22 30 41 54 10 0 0 0 0 0 0 0 0 0 0 1 1 2 3 5 7 11 15 22 30 42 11 0 0 0 0 0 0 0 0 0 0 0 1 1 2 3 5 7 11 15 22 30 12 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 3 5 7 11 15 22 13 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 3 5 7 11 15 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 3 5 7 11 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 3 5 7 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 3 5 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 3 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
71
Funzione sn
Implementazione in C int sn(int x, int k) { if (x==k) return 1; else if (x<k || k<=0) return 0; else return sn(x-k,k)+sn(x-1,k-1); }
72
Funzione sn
Implementazione in MIPS: x = $a0, k = $a1 li $v0, 1 beq $a0, $a1, ESCI move $v0, $zero slt $t0, $zero, $a1 beq $t0, $zero, ESCI slt $t0, $a0, $a1 bne $t0, $zero, ESCI # Esci se x<k
73
# Esci se k<=0
Funzione sn
$s0, $s1 e $s2 registri di appoggio per memorizzare i parametri ed un risultato intermedio, evitando luso dello stack tra le jal.
move $s0, $a0 move $s1, $a1 sub $a0, $s0, $s1 jal sn move $s2, $v0 addi $a0, $s0, -1 addi $a1, $s1, -1 jal sn add $v0, $v0, $s2 # sn(x-1,k-1)
74
# sn(x-k,k)
Funzione sn
sn: sub $sp, $sp, 16 sw $ra, 12($sp) sw $s0, 8($sp) sw $s1, 4($sp) sw $s2, 0($sp) (corpo della funzione) ESCI: lw $s0, 8($sp) lw $s1, 4($sp) lw $s2, 0($sp) lw $ra, 12($sp) addi $sp, $sp, 16 jr $ra
75
Funzione sn
sn: li $v0, 1 beq $a0, $a1, ESCI move $v0, $zero slt $t0, $zero, $a1 beq $t0, $zero, ESCI
stata effettuata unottimizzazione in modo da utilizzare lo stack solo quando la funzione effettua le chiamate ricorsive e non quando gi in grado di restituire il risultato.
slt $t0, $a0, $a1 bne $t0, $zero, ESCI sub $sp, $sp, 16 sw $ra, 12($sp) sw $s0, 8($sp) sw $s1, 4($sp) sw $s2, 0($sp) move $s0, $a0 move $s1, $a1 sub $a0, $s0, $s1 jal sn move $s2, $v0 addi $a0, $s0, -1 addi $a1, $s1, -1 jal sn add $v0, $v0, $s2 lw $s0, 8($sp) lw $s1, 4($sp)
PUSH
stata spostata
ESCI:
POP
76
Esercizio
Data limplementazione multi-ciclo discussa nel 5c apitolo del libro di testo, descrivere che cosa avviene nel 19ciclo di clock relativamente allesecuzione delle seguenti istruzioni MIPS, supposto che i registri $t1 e $t0 contengano rispettivamente 40 e 4.
CICLO: sub $t1, $t1, $t0 add $t2, $s0, $t1 lw $t3, 0($t2) add $s1, $s1, $t3 bne $t1, $zero, CICLO
77
Esercizio - soluzione
Evidenziando i cicli di clock richiesti da ogni istruzione, si ricava che durante il 19ciclo in corso il 2ciclo dellistru zione bne; quindi siamo nella fase di decodifica e caricamento dei registri. In questo caso specifico: A = $t1 B = $zero ALUOut = PC + (sign-ext(CICLO) << 2)
CICLO: sub $t1, $t1, $t0 add $t2, $s0, $t1 lw $t3, 0($t2) add $s1, $s1, $t3 bne $t1, $zero, CICLO
4 4 5 4 3
78
Istruzioni logico-aritmetiche
MIPS add r, s, t sub r, s, t mult s, t mul r, s, t div s, t div r, s, t rem r, s, t and r, s, t or r, s, t not r, s xor r, s, t nor r, s, t sll r, s, c sllv r, s, t srl r, s, c srlv r, s, t sra r, s, c srav r, s, t C r = s+ t r = s- t ( Hi Lo ) = s * t r = s* t Lo = s / t ; Hi = s % t r = s/ t r = s%t r r r r r r r r r = = = = = = = = = s&t s|t ~s s^ t ~ ( s|t ) s << s << s >> s >> c t c t Pseudo Immediate Unsigned Note
79
Scrivere un frammento di codice per estrarre dal registro s0 il numero positivo rappresentato dai bit dalla posizione 12 alla 23.
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -
31 0
30 0
29 0
28 0
27 0
26 0
25 0
24 0
23 0
22 0
21 0
20 0
19 0
18 0
17 0
16 0
15 0
14 0
13 0
12 0
11 -
10 -
9 -
8 -
7 -
6 -
5 -
4 -
3 -
2 -
1 -
0 -
Si possono utilizzare due tecniche: 1) 2) Maschera di bit + operazione di scorrimento 2 operazioni di scorrimento
80
and
31 0 30 0 29 0 28 0 27 0 26 0 25 0 24 0 23 1 22 1 21 1 20 1 19 1 18 1 17 1 16 1 15 1 14 1 13 1 12 1 11 0 10 0 9 0 8 0 7 0 6 0 5 0 4 0 3 0 2 0 1 0 0 0 31 0 30 0 29 0 28 0 27 0 26 0 25 0 24 0 23 22 21 20 19 18 17 16 15 14 13 12 11 0 10 0 9 0 8 0 7 0 6 0 5 0 4 0 3 0 2 0 1 0 0 0
shift right 12
31 0 30 0 29 0 28 0 27 0 26 0 25 0 24 0 23 0 22 0 21 0 20 0 19 0 18 0 17 0 16 0 15 0 14 0 13 0 12 0 11 10 9 8 7 6 5 4 3 2 1 0 -
2) 2 operazioni di scorrimento
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -
shift left 8
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 0 6 0 5 0 4 0 3 0 2 0 1 0 0 0
shift right 20
31 0 30 0 29 0 28 0 27 0 26 0 25 0 24 0 23 0 22 0 21 0 20 0 19 0 18 0 17 0 16 0 15 0 14 0 13 0 12 0 11 10 9 8 7 6 5 4 3 2 1 0 -
82
Hexify
.text .globl __start __start: li $v0, 5 syscall move $t0, $v0 li $t1, 7 hexify: and $t2, $t0, 0x0F srl $t0, $t0, 4 lb $t3, hex_table($t2) sb $t3, hex_digits($t1) sub $t1, $t1, 1 bgez $t1, hexify li $v0, 4 la $a0, the_result_is syscall li $v0, 10 syscall .data hex_table: the_result_is: hex_digits: .ascii "0123456789ABCDEF" .ascii "Hexadecimal value: 0x" .asciiz "XXXXXXXX" # exit # save n # 7 (+ 1) hex digits for 32 bits # extract least significant 4 bits # prepare for next digit # convert 4 bit group to hex digit # store hex digit # next digit # more digits? # print string # read integer n
83
Hexify: note
Le istruzioni lb e sb non utilizzano la modalit di indirizzamento c(rx) consentita dallhardware, ma unaltra concessa solo dallassemblatore che deve quindi effettuare la seguente traduzione:
lui $at, 4097 addu $at, $at, $t2 lb $t3, 0($at) lui $at, 4097 addu $at, $at, $t1 sb $t3, 37($at) ; sb $t3, hex_digits($t1) ; lb $t3, hex_table($t2)
84
Riferimenti
Computer Organization and Design
The Hardware/Software Interface 3rd Edition David A. Patterson, John L. Hennessy
Capitolo 2 Appendice A Versione italiana: Struttura e Progetto dei Calcolatori LInterfaccia Hardware-Software 2a edizione Zanichelli
http://en.wikipedia.org/ o http://it.wikipedia.org/
85