1 / 28

Procedure in assembler

Procedure in assembler. Procedure. Una procedura, o subrutine, è uno strumento che i programmatori usano per strutturare i programmi, sia per renderli più facili da capire che per permettere il riutilizzo del codice.

rhea
Download Presentation

Procedure in assembler

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Procedure in assembler

  2. Procedure Una procedura, o subrutine, è uno strumento che i programmatori usano per strutturare i programmi, sia per renderli più facili da capire che per permettere il riutilizzo del codice. Le procedure consentono di concentrarsi su una parte del problema, i parametri permettono di scambiare dati.

  3. I registri giocano un ruolo importante per tenere traccia delle procedure e memorizzare i valori di ritorno. Convenzioni: Indirizzo di ritorno $ra Passaggio dei parametri $a0, $a1, $a2, $a3 Valori di ritorno $v0, $v1 Variabili locali $s0, $s1, … , $s7 Procedure

  4. Procedure main() {int i,j,k,m; i = mult(j,k); ... m = mult(i,i); ... } /* really dumb mult function */ int mult (int mcand, int mlier){int product; product = 0;while (mlier > 0) { product = product + mcand; mlier = mlier -1; }return product;}

  5. Istruzioni per procedure (1/4) H L L ... sum(a,b);... /* a,b:$s0,$s1 */}int sum(int x, int y) { return x+y;} address1000 add $a0,$s0,$zero # x = a1004 add $a1,$s1,$zero # y = b1008 addi $ra,$zero,1016 #$ra=10161012j sum#jump to sum1016 ... 2000 sum: add $v0,$a0,$a12004jr $ra# new instruction MIPS

  6. Istruzioni per procedure (2/4) • Esiste una istruzione singola che salta ad un indirizzo e contemporaneamente salva l’indirizzo dell’istruzione successiva nel registro $ra : jump and link (jal) • Prima:1008 addi $ra,$zero,1016 #$ra=10161012 j sum #go to sum • Dopo:1012 jal sum # $ra=1016,go to sum

  7. Istruzioni per procedure (3/4) • La sintassi per jal (jump and link) è la stessa di j (jump): jal label • jal dovrebbe essere chiamato laj : “link and jump”: • Step 1 (link): Salva l’indirizzo dell’isruzione che segue in $ra • Step 2 (jump): Salta all’etichetta indicata

  8. Istruzioni per procedure (4/4) • La sintassi per jr (jump register): jr register • Invece di prevedere un etichetta alla quale saltare, l’istruzione jr prevede un registro che contiene un indirizzo. • jal memorizza l’indirizzo di ritorno nel registro ($ra) • jr ritorna a quell’indirizzo

  9. Nested Procedures (1/2) int sumSquare(int x, int y) { return mult(x,x)+ y;} • Qualcuno ha chiamato sumSquare, ora sumSquare sta chiamando mult. • Così c’è un valore in $ra al quale sumSquare vuole ritornare, ma sarà sovrascritto dalla chiamata a mult. • Bisogna salvare l’indirizzo di ritorno sumSquare prima di chiamare mult.

  10. Nested Procedures (2/2) • In generale può esserci il bisogno di salvare qualche altra informazione oltre che quelle in $ra. • Quando un programma gira, sono allocate tre importanti aree della memoria: • Static: variabili dichiarate nel programma una volta per tutte, finiscono di esistere solo quando il programma termina. E.g., globali • Heap: variabili dichiarate dinamicamente • Stack (pila): Spazio utilizzato dalle procedure durante l’esecuzione: dove è possibile salvare I valori dei registri

  11. Spazio per le procedure $sp puntatore stack Spazio creato esplicitamente, e.g., puntatori Variabili globali Heap Code Static Stack Programma HLL memory Allocation Indirizzi ¥ 0

  12. Usare la Stack (1/2) • La stack è una coda del tipo last-in first-out (l’ultimo ad entrare è il primo ad uscire) • Abbiamo un registro $sp che punta sempre all’ultimo spazio usato nella stack dove la procedura può memorizzare I registri da riversare e dove può recuperare I vecchi valori dei registri. • Il puntatore dello stack viene aggiornato ogni volta che viene inserito o estratto il valore di un registro. • Lo stack “cresce” a partire da indirizzi di memoria alti verso indirizzi di memoria bassi.

  13. Usare la Stack (2/2) • int sumSquare(int x, int y) { return mult(x,x)+ y; } sumSquare: addi $sp,$sp,-8 # space on stack sw $ra, 4($sp) # save ret addr sw $a1, 0($sp) # save y “push” Memorizzare un dato add$a1,$a0,$zero # mult(x,x) jal mult # call mult lw $a1, 0($sp) # restore y add $v0,$v0,$a1 # mult()+y lw $ra, 4($sp) # get ret addraddi $sp,$sp,8 # restore stack jr $ramult: ... “pop” Estrarre un dato

  14. Passi per una chiamata di procedura 1) Salvare I valori necessari nella stack. 2) Assegnare gli argomenti, se ce ne sono. 3) jal 4) Riprendere i valori dalla stack.

  15. Regole per le procedure • Vengono chiamate con un istruzione jal, ritornano al punto chiamante con jr $ra • Accettano fino a 4 argomenti $a0, $a1, $a2 e $a3 • Il valore di ritorno è sempre in $v0 (e se necessario in $v1) • Devono seguire le convenzioni per I registri

  16. Registri MIPS The constant 0 $0 $zeroReserved for Assembler $1 $atReturn Values $2-$3 $v0-$v1Arguments $4-$7 $a0-$a3Temporary $8-$15 $t0-$t7Saved $16-$23 $s0-$s7More Temporary $24-$25 $t8-$t9Used by Kernel $26-27 $k0-$k1Global Pointer $28 $gpStack Pointer $29 $spFrame Pointer $30 $fpReturn Address $31 $ra Usare nomi per I registri – il codice è più chiaro!

  17. Convenzioni per i registri (1/5) • Caller: La procedura chiamante • Callee: La procedura chiamata • Quando callee ritorna dall’esecuzione, caller deve sapere quali registri può aver cambiato e quali sono sicuramente rimasti invariati. • Register Conventions: Un insieme di regole generalmente accettate a proposito di quali registri una chiamata ad una procedura può (e non può cambiare).

  18. Convenzioni per i registri (2/5) • $0: No Change. Sempre 0. • $s0-$s7: No Change. Se callee cambia questi valori ci deve rimettere I valori originali prima di ritornare. • $sp: No Change. Il puntatore alla stack deve essere lo stesso prima e dopo la chiamata jal.

  19. Convenzioni per i registri (3/5) • $ra: Change. jal stesso cambierà questo registro. Caller ha bisogno di salvarlo nella stack se c’è un’altra chiamata. • $v0-$v1: Change. Aspettano I nuovi valori. • $a0-$a3: Change. Sono gli argomenti. Caller deve salvarli se ha ancora bisogno di loro dopo la chiamata. • $t0-$t9: Change. Sono chiamati temporanei: ogni procedura può cambiarli in ogni momento. Caller deve salvarli se ha ancora bisogno di loro dopo la chiamata.

  20. Convenzioni per i registri (4/5) • Cosa significa? • Se la procedura R chiama la procedura E, allora R deve salvare ogni registro temporaneo che può usare nella stack prima di un jal . • La procedura E deve salvare ogni S registro che intende usare prima di recuperare I suoi valori. • Ricordate: Caller/callee hanno bisogno di salvare solo I registri di cui hanno bisogno.

  21. Convenzioni per i registri (5/5) • Notate che se callee è arrivato ad usare qualche registro s deve: • Salvare s nella stack • Usare I registri • Riprendere s dalla stack • jr $ra

  22. “In conclusione…” (1/2) • Le procedure sono chiamate con jal, e ritornano con jr $ra. • Usate la stack per salvare tutto quello di cui avete bisogno. • Register Conventions: Usatele!.

  23. “In conclusione…” (2/2) • Istruzioni che conosciamo Arithmetic: add, addi, sub, addu, addiu, subu Memory: lw, sw Decision: beq, bne, slt, slti, sltu, sltiu Unconditional Branches (Jumps): j, jal, jr

  24. Esempio (1/5) main() {int i,j,k,m; /* i-m:$s0-$s3 */ i = mult(j,k); ... m = mult(i,i); ... } int mult (int mcand, int mlier){int product; product = 0;while (mlier > 0) { product += mcand; mlier -= 1; }return product;}

  25. Esempio (2/5) __start: add $a0,$s1,$0 # arg0 = jadd $a1,$s2,$0 # arg1 = k jal mult # call multadd $s0,$v0,$0 # i = mult()... add $a0,$s0,$0 # arg0 = iadd $a1,$s0,$0 # arg1 = i jal mult # call multadd $s3,$v0,$0 # m = mult()... done

  26. Esempio (3/5) • Note: • La funzione main finisce con done e non con jr $ra: non c’è bisogno di salvare $ra nella stack

  27. Esempio (4/5) mult: add $t0,$0,$0 # prod=0 Loop: slt $t1,$0,$a1 # mlr > 0?beq $t1,$0,Fin # no=>Fin add $t0,$t0,$a0 # prod+=mcaddi $a1,$a1,-1 # mlr-=1 j Loop # goto Loop Fin: add $v0,$t0,$0 # $v0=prod jr $ra # return

  28. Esempio (5/5) • Note: • Non vengono fatti jal da mult e non usiamo registri salvati: non abbiamo bisogno di mettere qualcosa da ricordare nella stack. • $a1 è direttamente modificato • Il risultato è messo in $v0

More Related