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 $raha 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 $rae 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.