Assembly MIPS, gestione dello stack
Ciao a tutti,
non mi è chiara una cosa riguardo alla gestione dello stack quando scrivo in Assembly.
Ad esempio, so che se ho un registro da salvare e preservare devo inserirlo nello stack.
Mettiamo che debba salvare il registro s0; all'inizio della funzione, libero lo stack in questo modo:
Ma come faccio a capire se un determinato registro deve essere salvato oppure no?
Ad esempio, dato questo codice C:
alla variabile i è associato il registro s0 mentre ad acc è associato il registro s1.
Il professore l'ha tradotto in Assembly così:
ha quindi inserito (e poi eliminato) nello stack due registri, che corrispondono ad i e ad acc.
Ma perchè devo salvarli?
non mi è chiara una cosa riguardo alla gestione dello stack quando scrivo in Assembly.
Ad esempio, so che se ho un registro da salvare e preservare devo inserirlo nello stack.
Mettiamo che debba salvare il registro s0; all'inizio della funzione, libero lo stack in questo modo:
addi $sp, $sp, -4 sw $s0, 0($sp)
Ma come faccio a capire se un determinato registro deve essere salvato oppure no?
Ad esempio, dato questo codice C:
int mul(int ar[], int dim) { int i, acc; acc=1; for (i=0; i<dim; i++) acc = acc*ar[i]; return(acc); }
alla variabile i è associato il registro s0 mentre ad acc è associato il registro s1.
Il professore l'ha tradotto in Assembly così:
addi $sp, $sp, -8 sw $s0, 0($sp) sw $s1, 4($sp) sll $t4, $t0, 2 # $t4 <- i*4 add $t4, $a0, $t4 # $t4 <- &a[i] lw $t5, 0($t4) # $t5 <- a[i] mul $t1, $t5 mflo $t1 # $t1 <- acc*ar[i]; lw $s0, 0($sp) lw $s1, 4($sp) addi $sp, $sp, 8 jr $ra
ha quindi inserito (e poi eliminato) nello stack due registri, che corrispondono ad i e ad acc.
Ma perchè devo salvarli?
Risposte
Di solito si fa uso dello stack per due ragioni:
1. In alcune architetture e sistemi operativi è necessario inserire gli argomenti di una funzione nello stack prima di richiamarla.
2. L'operazione che si vuole implementare potrebbe richiedere di memorizzare più valori del numero dei registri disponibili ed è quindi necessario memorizzare alcuni di loro nello stack. In questo caso non esiste alcuna regola su quali valori tu debba memorizzare nello stack e quali tenere nei registri.. Il codice del tuo professore è insomma solo una delle tante possibili implementazioni alternative.
1. In alcune architetture e sistemi operativi è necessario inserire gli argomenti di una funzione nello stack prima di richiamarla.
2. L'operazione che si vuole implementare potrebbe richiedere di memorizzare più valori del numero dei registri disponibili ed è quindi necessario memorizzare alcuni di loro nello stack. In questo caso non esiste alcuna regola su quali valori tu debba memorizzare nello stack e quali tenere nei registri.. Il codice del tuo professore è insomma solo una delle tante possibili implementazioni alternative.
Quindi è a discrezione del programmatore? Se invece di salvare le variabili i ed acc avessi salvato solo acc il codice avrebbe funzionato ugualmente?
Ad esempio, dato questo codice C:
il professore ha utilizzato lo stack in questo modo:
e non capisco come mai devo salvare tutti questi registri...
int nuovo_valore(int val); void incr(int vet[], int dim) { int i, fret; i = 0; while (i<dim) { fret = nuovo_valore(vet[i]); vet[i] = fret; i++; } }
il professore ha utilizzato lo stack in questo modo:
addi $sp, $sp, -24 sw $s0, 0($sp) sw $s1, 4($sp) sw $s2, 8($sp) sw $s3, 12($sp) sw $s4, 26($sp) sw $ra, 20($sp) # salvataggio $ra .... lw $s0, 0($sp) lw $s1, 4($sp) lw $s2, 8($sp) lw $s3, 12($sp) lw $s4, 16($sp) lw $ra, 20($sp) # ripristino $ra addi $sp, $sp, 24 jr $ra
e non capisco come mai devo salvare tutti questi registri...
Copi i registri nello stack per garantire che il codice chiamante mantenga i registri come prima della chiamata alla funzione.