Introdução à Arquitetura de Computadores/Suporte à Funções: diferenças entre revisões

[edição não verificada][edição não verificada]
Conteúdo apagado Conteúdo adicionado
Sem resumo de edição
Linha 51:
 
Entretanto, observe que para realizarmos os cálculos necessários, precisamos usar registradores. Ao fazer isso, existe o grande risco de apagarmos dados importantes do programa principal. Para evitar isso, existe uma convenção que diz que os registradores $r8 até $r15, $r24 e $r25 são registradores temporários. Por isso, eles costumam ser chamados de '''$t0''' até '''$t9'''. Após chamar uma função, o programa principal não deve esperar que os valores destes registradores sejam os mesmos. Somente dados que estejam nos registradores $r16 até $r23 são sempre preservados entre funções. Por esta razão, tais registradores permanentes (salvos) são chamados de '''$s0''' até '''$r7'''.
 
== Funções com Muitas Variáveis ==
 
Existem funções que podem precisar receber mais do que 4 parâmetros. Entretanto, só temos registradores suficientes para armazenar 4 parâmetros. Nós também podemos querer retornar mais do que os 2 valores permitidos pelos registradores. Ou então, noossa função pode precisar armazenar mais do que 10 valores temporários. O que fazer para resolver isso?
 
Como o espaço dentro de registradores é bastante limitado, só nos resta apelar para a pilha da memória. Por convenção, o registrador $r29, ou '''$sp''' (Stack Pointer) armazena o endereço na pilha de onde novos valores podem ser colocados. Acessando seu endereço e alterando-o podemos guardar valores na memória. O acesso à pilha da memória é muito mais lento que o acesso à registradores, mas este é o único modo de podermos armazenar uma quantidade muito maior de informação.
 
Por motivos históricos, a pilha "cresce" sempre dos valores de endereços altos para valores menores. Ou seja, para alocar espaço para mais valores, precisamos sempre decrementar o seu valor. Incrementando-o, estamos na verdade removendo os últimos dados da pilha.
 
Vamos reescrever agora o código Assembly visto acima, desta vez preeservando os valores dos registradores $t0 e $t1 para vermos como ficaria o resultado:
 
example: # Label
 
addi $sp, $sp, -8 # Alocamos espaço para dois valores de 4 bits.
sw $t1, 4($sp) # Preservamos o valor de $t1 à partir do 4o bit após o Stack Pointer
sw $t0, 0($sp) # Preservamos o valor de $t0 sobre o Stack Pointer
add $t0, $a0, $a1 # Soma a + b
add $t1, $a2, $a3 # Soma c + d
sub $v0, $t0, $t1 # Subtrai os dois valores e coloca o resultado no registrador de retorno
lw $t0, 0($sp) # Retiramos o valor antigo salvo de $t0
lw $t1, 4($sp) # Retiramos da pilha o valor antigo de $t1
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