Diferenças entre edições de "Introdução à Arquitetura de Computadores/Suporte à Funções"

sem resumo de edição
addi $sp, $sp, 8 # Voltamos o Stack Pointer para a posição original apagando de vez as variáveis locais
jr $ra # Retorna o controle para a função principal
 
== Funções Recursivas e Sub-Funções ==
 
Da mesma forma que o programa principal invocou uma função, uma função também pode invocar outras funções. Se la for recursiva, ela pode até mesmo invocar clones de si mesma para realizzar uma tarefa. Como implementar isso sendo que temos apenas um registrador '''$ra'''? Se chamarmos outra função, oo '''$ra''' original é sobrescrito e podemos perder a capacidade de voltar ao programa principal. Além disso, valores temporários que representam variáveis locais podem ser perdidas.
 
A única forma de evitar isso é enviar para a pilha tudo aquilo que precisa ser salvo - da mesma forma que fizemos com alguns valores no exemplo acima. Para mostrar isso na prática vamos implementar em Assembly a seguinte função em C:
 
/* Calcula Fatorial */
int fat(int n){
if(n < 1)
return 1;
else
return (n * fat(n - 1));
}
 
O resultado final é algo como:
 
fat: # Início da função
addi $sp, $sp, -8 # Aloca espaço na pilha para 2 valores
sw $ra, 4($sp) # Guarda valor de retorno na pilha
sw $a0, 0($sp) # Guarda primeiro argumento na pilha
slti $t0, $a0, 1 # $t0 = ( $a0 < 1)
beq $t0, $zero, L1 # Se $a0 >= 1, vá para L1
addi $v0, $zero, 1 # Senão, coloque 1 como valor de retorno
addi $sp, $sp, 8 # Apague as duas variáveis locais salvas na pilha
jr $ra # Encerra a função
L1: addi $a0, $a0, -1 # Se $a >= 1, decremente $a0
jal fat # Chame um clone recursivo de fat que retorna fat($a0-1)
lw $a0, 0($sp) # Recupere os valores iniciais do parâmetro da função
lw $ra, 4($sp) # Recupere o endereço de retorno antigo
addi $sp, $sp, 8 # Apague as duas variáveis locais salvas na pilha
mul $v0, $a0, $v0 # Coloque $a0 * fat($a0 - 1) como valor de retorno
jr $ra # Encerra a funçãoo
 
[[Categoria: Ciência da Computação]]
381

edições