vuoi
o PayPal
tutte le volte che vuoi
Da C ad Assembly
Programma in C da convertire:
#include <iostream>
int FIB (int n) {
if (n == 0)
return 0;
else if (n < 2)
return 1;
else
return (FIB(n-1) + FIB(n-2)); //chiamo più volte FIB e ogni volta ho bisogno di salvare l'indirizzo di ritorno
}
/*int main () {
int n=5;
bool condotion = true;
while (condition) {
FIB (n);
n-=1;
condition = (n>=0) ? false : true;
}
return 0;
}*/
$ra
contiene sempre l'indirizzo di ritorno (unico per questo scopo)
Con la chiamata più volte di FIB, sovrascrivo ogni volta il valore di $ra
, perdendo quello precedente.
Ciò riguarda qualunque altro registro che riutilizzo, andando a sovrascrivere il nuovo al vecchio.
Come faccio a non perdere il contenuto? → USO LA MEMORIA
Devo preoccuparmi di non perdere il valore di un registro prima di sovrascriverlo.
Per fare ciò, devo salvarlo/copiarlo da qualche parte (ovvero in memoria, in particolare in una cella riservata a salvare
queldato).CONVENZIONE PER FUNZIONI RICORSIVE: si usa non la memoria in generale ma lo stack, zona di memoria "a pila"FIB: addi $sp, $sp, -12 # alloco lo stack
sw $ra, 8($sp) # salvo return address
sw $a0, 4($sp) # salvo n
sw $s1, 0($sp) # salvo risultato parziale
# FIB definita nel suo funzionamento
All'inizio, decremento lo stack pointer di 12 in quanto sto utilizzando tre valori da 4 Byte l'uno, ovvero 12 Byte.
Devo, dunque, spostare l'indirizzo iniziale dello stack di 12 posizioni (in basso perché lo stack è una pila verso il basso).
Con gli sw, salvo nelle varie zone dello stack i valori dei registri che voglio preservare.
Questo è da fare all'inizio della funzione ricorsiva, per preservare i valori ogni volta.IF: bgtz $a0, ELSEIF # brench-> salto a ELSEIF se n>0
add $v0, $zero, $zero # metto dentro a $v0 il valore 0 se n==0 (ovvero, se n==0 ritorna 0)
j END # mi aspettavo jr $ra -> salto all'indirizzo corrispondente al valore
contenuto in $ra# questo, invece, è sempre un salto incondizionato ma a un'etichetta specifica (END). Infatti, devo ripristinare $ra
ELSEIF: slti $t0, $a0, 2 # set $t0 <-- 1 se $a0<2
beq $t0, $zero, ELSE # se $t0==0 salta a ELSE condizionatamente (ovvero se n>=2)
addi $v0, $zero, 1 # se n==1 ritorna 1
j END
Da C ad Assembly 1