Introdução à Arquitetura de Computadores/Suporte à Funções: diferenças entre revisões
[edição não verificada] | [edição não verificada] |
Sem resumo de edição |
|||
Linha 49: | Linha 49: | ||
sub $v0, $t0, $t1 # Subtrai os dois valores e coloca o resultado no registrador de retorno |
sub $v0, $t0, $t1 # Subtrai os dois valores e coloca o resultado no registrador de retorno |
||
jr $ra # Retorna o controle para a função principal |
jr $ra # Retorna o controle para a função principal |
||
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'''. |
Revisão das 01h55min de 14 de agosto de 2008
Funções são ferramentas muito importantes, pois tornam código escrito muito mais usável e torna a tarefa de programar mais produtiva. Elas permitem que um programador se concentre em apeenas uma tarefa de cada vez. Portanto, é essencial que um processador possua suporte á elas. Veremos como isso ocorre no MIPS.
As Etapas Necessárias para Invocar Funções
Quando queremos chamar uma função, as seguintes etapas devem ser cumpridas:
- O programa principal deve colocar os parâmetros da função em um local que ela possa acessar.
- O programa principal deve ceeder o controle para a função.
- A função deve coletar todos oos parâmetros deixados pelo programa principal.
- A função deve executar a tarefa desejada.
- A função deve aramazenar seus resultados em um lugar em que o programa principal possa acessar.
- A função deve retornar o fluxo do código para o ponto imediatamente após ser chamada.
Para que estes requisitos sejam cumpridos, as seguintes convenções fora criadas:
- Os registradores $r4, $r5, $r6 e $r7 seriam usados para armazenar parâmetros de funções. Por causa desta funcionalidade, tais registradores podem ser chamados pelos seus "apelidos": $a0, $a1, $a2 e $a3.
- Os registradores $r2 e $r3 seriam usados para as funções armazenarem seus valores de retorno para o programa principal. Por isso, eles costumam ser chamados de $v0 e $v1.
Tais regras são apenas convenções. Nada impede que um programador as desrespeite e use outros registradores para estabelecer comunicação entre funções e programas principais. Entretanto, para que um programa funcione bem em conjunto com todos os demais, é importante quee tais convenções sejam seguidas.
Além dos registradores convencionados acima, o registrador $r31 também tem um papel importante. Ele sempre armazena o endereço de retorno para o qual a última função chamada deve retornar. Por ter uma função tão importante, este registrador é mais conhecido pelo apelido $ra.
Instruções de Uso de Funções: jal e jr
A instrução que usamos para invocar uma função chama-se jal, ou Jump and Link. Ela é usada da seguinte forma:
jal ENDEREÇO_DA_FUNÇÃO
Entretanto, só devemos chamar esta função depois de já termos salvo os argumentos nos registradores apropriados.
Depois da função executar todas as operações e salvar os resultados apropriados em $v0 e $v1, podemos usar a instrução jr, ou Jump Register. Normalmente usamos a instrução passando para ela o valor do registrador $ra, que contém o endereço certo para voltarmos:
jr $ra
Como exemplo de como isso pode ser feito, vamos converter para Assembly o seguinte código em C:
int example(int a, int b, int c, int d){ int f; f = (a + b) - (c + d) return f; }
O código no Assembly do MIPS ficaria assim:
example: # Label 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 jr $ra # Retorna o controle para a função principal
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.