“LabArch 2003”
Transcript
“LabArch 2003”
[Docente H. Muccini] http://www.di.univaq.it/~muccini/ArchLab03 “LabArch 2003” Laboratorio di Architetture degli Elaboratori Terzo Quadimestre, anno 2003 Lecture 6 e 7: - Procedure - Stack per le procedure - Procedure annidate - Procedure ricorsive 2003 Henry Muccini LabArch2003 (parte della) Architettura del MIPS SEA Group MAR Memoria MBR R1R2 … R32 32 bit MEMORIA ALU Bus CPU 2003 Henry Muccini 2/28 1 LabArch2003 Procedure Int { SEA Group SommaTernaria (int a, int b, int c) int d; d = a + b + c; return d; } 2003 Henry Muccini 3/28 LabArch2003 SEA Group Steps per una procedura 1. 2. 3. 4. 5. 6. Assegnare uno spazio ai parametri Salto alla procedura Ottenimento dei Registri necessari alla procedura Computazione Mettere il risultato in un registro accessibile dal programma chiamato Salto al programma chiamante 2003 Henry Muccini 4/28 2 LabArch2003 SEA Group Idea Main Istruzione 1; Istruzione 2; Registri $a0 - $a3: $v0 - $v1: $ra: Procedura (par1, par2); Istruzione 3; … Procedura (par1, par2) Istruzione P1 Istruzione P2 Istruzione P3 Registri per il passaggio dei parametri Registri per il ritorno dei risultati Registro per memorizzare l’indirizzo dell’istruzione di ritorno end 2003 Henry Muccini 5/28 LabArch2003 SEA Group Riassunto sui Registri $s0 - $s7: 8 registri dati $t0 - $t7: 8 registri per dati temporanei $a0 - $a3: 4 registri per i parametri $v0 - $v1: 2 registri per i risultati $ra: 1 registro per il ritorno da procedura Mancano ancora 9 registri 2003 Henry Muccini 6/28 3 LabArch2003 SEA Group Istruzioni per Procedure jal IndirizzoProcedura Per saltare ad una procedura Main Istruzione 1 Istruzione 2 jal ProceduraSomma # diverso da “j”, poiche’... Istruzione 3 ProceduraSomma Istruzione P1 jr $ra “jal” memorizza il PC+4 nel registro di ritorno $ra 2003 Henry Muccini 7/28 LabArch2003 SEA Group Problema ? Cosa accade se necessitiamo, dentro una procedura, di altri registri, rispetto ai 4 registri per i parametri e piu’ di 2 per i risultati??? $a0 - $a3 : 4 registri per i parametri $v0 - $v1 : 2 registri per i risultati Necessito anche di $t0, $t1, $s0, per fare calcoli!!! Il problema e’ nel fatto che $t0, $t1, $s0 potrebbero essere gia’ in uso dal chiamante!!! 2003 Henry Muccini 8/28 4 LabArch2003 Grafichiamo il problema Main: $t0 SEA Group $t1 $s0 Istr1 Tali istruzioni usano $t0, $t1, $s0 Istr2 Jal Proc ???Dov’e’ il problema??? Istr3 Proc: IstrP1 Jr $ra Tale istruzione usa $t0, $s0 2003 Henry Muccini 9/28 LabArch2003 SEA Group Stack per le Procedure Cos’e’ una pila (o stack) e come funziona Numerazione di uno stack nel MIPS 100 99 … 80 … 1 Stack, in MIPS, e’ un registro $sp dove vengono memorizzati temporaneamente le informazioni sui Registri in uso dal Main Idea: Quando Main chiama Proc: creo spazio per tutte le variabili usate in Proc ($t0, $s0) nello stack memorizzo tali variabili nello stack Quando Proc rida’ il controllo a Main: rimetto nei registri utilizzati da Proc ($t0, $s0) i valori iniziali pulisco lo stack 1. 2. 3. 4. 2003 Henry Muccini 10/28 5 LabArch2003 Esempio SEA Group Int EsempioProc (int a, int b, int c){ int x; x = (a+b) - c return x} Analisi: ho bisogno di due registri non dedicati x $s0 (registro che potrebbe essere gia’ in uso) a+b $t0 (registro temporaneo che potrebbe essere gia’ in uso) a $a0, b $a1, c $a2 (registri dei parametri) $v0 per il risultato (registro per risultati) 2003 Henry Muccini 11/28 LabArch2003 Esempio (cont.) SEA Group EsempioProc: sub $sp, $sp, 8 # alloco due spazi nello stack sw $s0, 4($sp) sw $t0, 0($sp) # memorizzo I reg. nello stack add $t0, $a0, $a1 # (a+b) sub $s0, $t0, $a2 # x = (a+b) – c add $v0, $s0, $zero # setto il risultato lw $t0, 0($sp) lw $s0, 4($sp) # ripristino I vecchi valori di $t0 e $s0 add $sp, $sp, 8 jr $ra 2003 Henry Muccini 12/28 6 LabArch2003 SEA Group Alcune note Nota l’ordine con cui le operazioni “sw” e “lw” vengono eseguite sullo stack (lifo) E’ proprio uno stack! 4 100 99 … 80 … 0 1 Nota: i registri temporanei solitamente non vengono salvati e ripristinati Semplificazione sull’esempio precedente 2003 Henry Muccini 13/28 LabArch2003 SEA Group Da fare in classe Int SommaTernaria (int a, int b, int c) { } int d; d = a + b + c; return d; 2003 Henry Muccini 14/28 7 LabArch2003 d $s0 (registro che potrebbe essere gia’ in uso) a+b $t0 (registro temporaneo) a $a0, b $a1, c $a2 (registri dei parametri) $v0 per il risultato (registro per risultati) SEA Group SommaTernaria: sub $sp, $sp, 4 # alloco uno spazio nello stack sw $s0, 0($sp) # memorizzo il reg. $s0 nello stack add $t0, $a0, $a1 # (a+b) add $s0, $t0, $a2 # d = (a+b) + c add $v0, $s0, $zero # setto il risultato lw $s0, 0($sp) # ripristino il vecchio valore di $s0 add $sp, $sp, 4 jr $ra 2003 Henry Muccini 15/28 LabArch2003 Procedure Annidate SEA Group Int SommaTernaria (int a, int b, int c) { int d; int e; d = Somma (a, b); e = Somma (c, d); return e;} Int Somma (int a, int b) { int c; c = a + b; return c;} 2003 Henry Muccini 16/28 8 LabArch2003 Ricordiamo come i registri vengono usati nelle procedure Main: I parametri sono in $ai Istr1 Istr2 Jal Proc Istr3 Proc: Salvo i risultati in $vi IstrP1 Jr $ra SEA Group Salva PC+4 in $ra Salvo i registri $si nello stack pointer $sp Ripristino i registri $si dallo stack pointer $sp 2003 Henry Muccini Procedure Annidate in MIPS 17/28 LabArch2003 SEA Group Abbiamo bisogno di memorizzare piu’ registri Main: istr.1 istr.2 jal Procedure #passo parametri istr.3 Procedure: istr. p1 “Procedure” usa jal Procedure2 #passo parametri $ai per i parametri istr. p2 $vi per i risultati jr $ra Procedure2 !!! Entrambi usano gli stessi registri !!! istr. Q “Procedure2” usa jr $ra $ai per i parametri $vi per i risultati 2003 Henry Muccini 18/28 9 LabArch2003 SEA Group Inoltre… Main: istr.1 istr.2 jal Procedure #passo parametri istr. p1 jal Procedure2 #passo parametri istr. P2 jr $ra Procedure2 istr. Q jr $ra $ra l’indirizzo di ritorno istr.3 Procedure: “jal” del Main salva in “jal” di Procedure salva in $ra l’indirizzo di ritorno !!! Entrambi usano lo stesso registro !!! Se Procedure sovrascrivesse $ra, non sarebbe piu’ possibile tornare a Istr. 3 del Main 2003 Henry Muccini 19/28 LabArch2003 SEA Group Quindi Se si lavora con procedure annidate, bisogna salvare: I registri $si che potrebbero essere in uso dal chiamante I registri $ai per i parametri Il registro $ra per mantenere l’indirizzo del chiamante Lo stack pointer $sp va’ aggiornato per tener conto del numero di registri memorizzati nello stack 2003 Henry Muccini 20/28 10 LabArch2003 SEA Group Uso dei registri in procedure annidate I parametri sono in $ai Main: … Jal Proc1 Istr3 Proc1: Come programma chiamante IstrP1 Jal Proc2 Jr $ra Salvo i registri Salva PC+4 in $ra Come programma chiamato Salvo i registri $si nello stack pointer $sp Come programma chiamato Salvo i risultati in $vi $ai ed $ra nello stack pointer $sp Proc2: Come programma chiamante IstrP2 Ripristino i registri $ai ed $ra Jr $ra Come programma chiamato Ripristino i registri $si dallo stack pointer $sp dallo stack pointer $sp 2003 Henry Muccini 21/28 LabArch2003 SEA Group Registri nelle procedure annidate Programma chiamato: Salva $si, cioe’ tutto cio’ che lui puo’ usare e che serve ancora al suo chiamante Ripristina $si Programma chiamante: Salva $ai, $ra (vecchio) cioe’ i registri che potrebbero essere usati dal proprio chiamato e che serviranno a lui in seguito Programma chiamato e chiamante: Salva (e poi ripristina) $si, $ra, $ai 2003 Henry Muccini 22/28 11 LabArch2003 Esempio: Procedure Annidate in MIPS Main: … SommaIF … Int SommaIF (int a, int b) { if (a != b) Somma (a, b) else return(0); } Int Somma (int a, int b) { int c; c = a + b;} $s0 $ra USATO dopo SommaIF PER TORNARE INDIETRO a = $a0 b = $a1 $v0 $s0 $ra SEA Group PARAMETRO PARAMETRO RISULTATO da salvare in $sp (usato da main) PER TORNARE INDIETRO a = $a0 PARAMETRO b = $a1 PARAMETRO c = $t0 REGISTRO INTERNO Non usa nessun $si usato dal chiamante 2003 Henry Muccini 23/28 LabArch2003 SommaIf: #(procedura chiamata - chiamante) SEA Group sub $sp, $sp, 16 # spazio nello stack per 4 registri sw $s0, 12($sp) # salvo $s0 del chiamante Come chiamato sw $ra, 8($sp) # salvo $ra del chiamante Come chiamante sw $a0, 4($sp) # salvo $a0 sw $a1, 0($sp) # salvo $a1 beq $a0, $a1, Else jal Somma lw $a1, 0($sp) # ripristino $ai modificati da Somma lw $a0, 4($sp) lw $ra, 8($sp) # ripristino $ra per poter tornare al Main sub $sp, $sp, 12 # ripristino spazio in $sp add $v0, $v0, $zero # setto il risultato di SommaIf jr $ra 2003 Henry Muccini 24/28 12 LabArch2003 SEA Group Else: add $v0, $zero, $zero lw $s0, 12($sp) Tali operazioni non sono necessarie lw $ra, 8($sp) add $sp, $sp, 8 # libero lo stack jr $ra Somma: #(procedura foglia) # non devo salvare nessun registro, visto che non uso nessun $si e sono foglia add $t0, $a0, $a1 # a+b add $v0, $t0, $zero # setto il risultato # non devo ripristinare nessun registro, visto che non uso nessun $si # non devo liberare spazio nell $sp jr $ra 2003 Henry Muccini 25/28 LabArch2003 SommaIf: #(procedura chiamata - chiamante) SEA Group sub $sp, $sp, 16 # spazio nello stack per 4 registri sw $s0, 12($sp) # salvo $s0 del chiamante sw $ra, 8($sp) # salvo $ra del chiamante sw $a0, 4($sp) # salvo $a0 sw $a1, 0($sp) # salvo $a1 beq $a0, $a1, Else jal Somma; lw $a1, 0($sp) # ripristino $ai che potrebbero essere stati modificati da Somma lw $a0, 4($sp) lw $ra, 8($sp) # ripristino $ra per poter tornare al Main sub $sp, $sp, 12 # ripristino spazio in $sp add $v0, $v0, $zero # setto il risultato di SommaIf jr $ra Else: add $v0, $zero, $zero lw $s0, 12($sp) lw $ra, 8($sp) add $sp, $sp, 8 # libero lo stack jr $ra Somma: #(procedura foglia) # non devo salvare nessun registro, visto che non uso nessun $si e sono foglia add $t0, $a0, $a1 # a+b 2003 Henry Muccini add $v0, $t0, $zero # setto il risultato d h $ 26/28 13 LabArch2003 SEA Group Esercizio: Procedura ricorsiva in MIPS Int fatt (int n){ if (n<1) return (1); } else return (n * fatt (n-1)); Dove: n = $a0 Assumiamo che fatt non usi registri $si in uso dal Main 2003 Henry Muccini 27/28 LabArch2003 SEA Group fatt: sub $sp, $sp, 8 # alloco uno spazio nello stack sw $ra, 4($sp) Come chiamante sw $a0, 0($sp) slt $t0, $a0, 1 # se a0<1, $t0 diventa 1 beq $t0, $zero, Else # Controllo n < 1 add $v0, $zero, 1 add $sp, $sp, 8 # aggiorno stack jr $ra Return 1 Ramo Then Else: sub $a0, $a0, 1 # calcolo n-1 jal fatt # chiamo il fattoriale lw $a0, 0($sp) # ripristino $a0 lw $ra, 4($sp) # ripristino $ra sub $sp, $sp, 8 # aggiorno stack Dopo aver eseguito il fattoriale, ripristono I registri che potrebbero esser stati modificati mul $v0, $a0, $v0 # setto il risultato n * fatt(n-1) jr $ra 2003 Henry Muccini 28/28 14