Chiamate a Procedure Per l’esecuzione di una procedura, un programma deve eseguire i seguenti sei passi: mettere i parametri in un posto dove la procedura possa recuperarli trasferire il controllo alla procedura allocare le risorse (di memorizzazione dei dati) necessarie alla procedura effettuare la computazione della procedura mettere i risultati in un posto accessibile al chiamante restituire il controllo al chiamante Chiamata semplice (jal) La procedura A chiama la procedura B. La procedura B non chiama nessun altra procedura $ra=0x00400032 A: 0x00400032 B: .... jal B … .... jr $ra • $ra -> registro di ritorno per tornare al punto di origine Chiamata con passaggio parametri La procedura A chiama la procedura B passandogli 3 parametri La procedura B esegue la somma dei tre parametri, restituisce il risultato ad A e non chiama nessun altra procedura $ra -> contiene l’indirizzo di ritorno $a0 - $a3 -> quattro registri argomento per il passaggio dei parametri $v0 - $v1 -> due registri valore per la restituzione dei valori Esempio .text __start: Li $s0, 2 Li $s1, 3 Li $s2, 4 move $a0, $s0 move $a1, $s1 move $a2, $s2 jal somma Move $s3, $v0 Somma: add $t0, $a0, $a1 Add $t0, $t0, $a2 Move $v0, $t0 Jr $ra Convenzione utilizzo dei registri Vedere appendice A -> $t0 (temporanei) -> $s0 il cui contenuto può essere modificato durante la chiamata ad altre procedure il cui contenuto non deve essere modificato durante la chiamata ad altre procedure -> $ra Utilizzo dello stack lo stack cresce verso gli indirizzi di memoria inferiori Il registro stack pointer $sp ($29) punta all'indirizzo dell'ultima parola in stack gli elementi in stack sono raggiunti mediante indirizzi composti dallo stack pointer e da un offset positivo Es. lw $t0 4($sp) Tutto lo spazio in stack di cui ha bisogno una subroutine deve essere esplicitamente allocato in una sola volta deve essere multiplo di due parole Lo spazio nello stack viene allocato sottraendo allo stack pointer la dimensione dello stack Al ritorno da una subroutine il record di attivazione viene deallocato incrementando lo stack pointer della stessa quantità di cui lo si era decrementato Gli elementi sono "pushed" nello stack mediante la loro memorizzaziore ad un offset positivo rispetto allo stack pointer Es. sub $sp,24 -> sono disponibili le seguenti 6 locazioni. 0($sp) 20($sp) 16($sp) 4($sp) 12($sp) 8($sp) 8($sp) 12($sp) 4($sp) 16($sp) 0($sp) 20($sp) Es. sw $ra,20($sp) e vengono "popped" dallo stack leggendo dalla stessa locazione Es. lw $ra,20($sp) Subroutine non Foglia Quando deve chiamare un’altra procedura, devono allocare almeno 24 bytes di spazio in stack 4 parole per i registri $a0-$a3 1 parola per l'indirizzo di ritorno una parola per mantenere l'allineamento alla doppia parola Il record di attivazione di una subroutine contiene quindi spazio per $a0-$a3 (per le subroutines chiamate) argomenti passati alle funzioni chiamate registri general purpose da salvarsi spazio per variabili locali allocate dalla subroutine Esempio di uso dello stack La procedura A: riceve 5 parametri di ingresso scalari (4 nei registri ed 1 in stack) chiama a sua volta altre subroutines (B, C, D, E), con differente numero di parametri scalari; la chiamata con massimo numero di parametri è per una subroutine che riceve in ingresso 7 parametri scalari ha bisogno di salvare, per il suo funzionamento interno, 4 registri floating point ha bisogno di salvare, per il suo funzionamento interno, 5 registri general purpose utilizza 16 parole di spazio in stack per memorizzarvi le sue (di A) variabili locali