240 likes | 371 Views
A Linguagem de Máquina – Funções e recursividade. Prof. André Luis M. Silva andreluis.ms@gmail.com orgearq200101.wordpress.com. Funções e Procedimentos. Procedimento ou função é um recurso empregado em linguagens de alto nível para modularizar código.
E N D
A Linguagem de Máquina – Funções e recursividade Prof. André Luis M. Silva andreluis.ms@gmail.com orgearq200101.wordpress.com
Funções e Procedimentos • Procedimento ou função é um recurso empregado em linguagens de alto nível para modularizar código. • Chamadas de função usam alguns registradores reservados, são eles: • $a0 - $a3: quatro registradores de argumento, para passar parâmetros • $v0-$v1: dois registradores de valor, para valores de retorno • $ra: um registrador de endereço de retorno, para retornar ao ponto de origem.
Funções e Procedimentos • Registradores reservados para chamada de funções: • $a0 - $a3: quatro registradores de argumento, para passar parâmetros • $v0-$v1: dois registradores de valor, para valores de retorno
Funções e Procedimentos • Registradores reservados para chamada de funções: • $ra: um registrador de endereço de retorno, para retornar ao ponto de origem. • $PC (programcounter): Registrador armazena o endereço da instrução atual sendo executada. • Então qual endereço salvo por jal no registrador $ra?
Funções e Procedimentos • Instrução jal (jump and link) • Desvia para um endereço e simultaneamente salva o endereço da instrução seguinte no registrador $ra (endereço de retorno). • Sintaxe • jal laco
Funções e Procedimentos • Qual seria o código assembly do seguinte procedimento C? void exemplo_chamada(){ exemplo_folha(2, 3, 4, 5); } intexemplo_folha (int g, int h, int i, int j){ int f; f = (g + h) – (i + j); return f; } Caller oufunçãochamadora Calleeoufunçãochamada
Funções e Procedimentos exemplo_chamada: addi $a0, $zero, 2 addi $a1, $zero, 3 addi $a2, $zero, 4 addi $a3, $zero, 5 jalexemplo_folha exemplo_folha: add $t0, $a0, $a1 # $t0 = g+h add $t1, $a2, $a3 # $t1 = i + j sub $s0, $t0, $t1 # $s0 = (g+h) – (i + j) add $v0, $s0, $zero #return f jr $ra $sp
Funções e Procedimentos • Para codificarfunçõesdevemosseguiressasregras. • 1. Callercoloca os valores de parâmetro em $a0 - $a3. • 2. Callerutiliza jal X para chamar o procedimento X • 3. Calleerealiza os cálculos, coloca os resultados em $v0-$v1. • 4. Callee retorna o controle para o caller usando jr $ra.
Funções e Procedimentos • Quando a funçãopossui 5 oumaisargumentos, o calee realiza um processo denominado spillingregisters. • Armazenar em memória valores que serão necessários posteriormente para a execução do programa. • Para controle da memória, o MIPS possui um registrador especial denominado stack pointer ($sp). • O stack pointer sempre aponta para o último endreço alocado mais recentemente.
Spilling Registers $sp = 10000 Stack 10000
Spilling Registers $sp = 9996 Stack 10000 Valor do registrador $r1 crescimento 9996
Spilling Registers $sp = 9992 Stack 10000 Valor do registrador $r1 9996 crescimento Valor do registrador $r2 9992
Spilling Registers • Spilling registers também são utilizados para preservar valores de registradoressalvos.
Spilling Registers • Qual seria o código assembly do seguinte procedimento C? void exemplo_chamada(){ int p = 0; p += 5; exemplo_folha(2, 3, 4, 5); } intexemplo_folha (int g, int h, int i, int j){ int f; f = (g + h) – (i + j); return f; } Caller oufunçãochamadora Calleeoufunçãochamada
Spilling Registers exemplo_chamada: addi $s0, $s0, 5 addi $a0, $zero, 2 addi $a1, $zero, 3 addi $a2, $zero, 4 addi $a3, $zero, 5 jalexemplo_folha exemplo_folha: add $t0, $a0, $a1 # $t0 = g+h add $t1, $a2, $a3 # $t1 = i + j sub $s0, $t0, $t1 # $s0 = (g+h) – (i + j) add $v0, $s0, $zero #return f jr $ra Problema: Valor de $s0 perdidoapós a chamada de umafunção. Exemplo_folhadevefazer backup do valor. $sp
Memória Memória $s0 $s0 … … Spilling Registers exemplo_folha: addi $sp, $sp, -4 sw $s0, 0($sp) add $t0, $a0, $a1 # $t0 = g+h add $t1, $a2, $a3 # $t1 = i + j sub $s0, $t0, $t1 # $s0 = (g+h) – (i + j) add $v0, $s0, $zero #return f lw $s0, 0($sp) addi $sp, $sp, 4 jr $ra Mudanças $sp $sp $sp Mudanças
Funções aninhadas e recursivas • Funções que fazem chamadas a outras funções são chamadas aninhadas. • Quando elas chamam a si mesmo, denominamos recursivas. • Tais funções precisam fazer “backup” do registrador $ra. Porque? • Como seria a implementação dessa função? int fact (int n){ if (n < 1) return (1); else return (n * fact(n – 1)); }
Funções aninhadas e recursivas fact: addi $sp, $sp, -8 #aloca 2 itens em memória sw $ra, 4($sp) # armazena endereço de retorno sw $a0, 0($sp) # armazena n slti $t0, $a0, 1 # teste para n < 1 beq $t0, $zero, L1 # se n>=1 vai para L1 addi $v0, $zero, 1 # retorna 1 addi $sp, $sp, 8 # retira 2 itens da memória jr $ra #retorna para depois de jal L1: addi $a0, $a0 -1 #arg1 = n – 1; jalfact #chama fact(n-1); lw $a0, 0($sp) #retorna de jal. Restaura n lw $ra, 4($sp) #restaura endereço de retorno addi $sp, $sp, 8 #ajusta stack pointer mul $v0, $a0, $v0 # retorna n * fact( n - 1) jr $ra # retorna para o procedimento que o chamou
Suporte a procedimentos no hardware do computador • Além dos elementos citados, a memória também pode ser utilizada para armazenar outros elementos. • Alguns exemplos são variáveis locais (tais como arrays ou estruturas) que não cabem em registradores. • Este segmento de memória relativo a um procedimento é conhecido como frame ou registro de ativação. • Em geral os processadores possuem um registradorespecífico para apontar para o início do frame. Este registrador é conhecido como frame pointer ($fp).
Atividade 8 • Codifique utilizando assembly. Façam uso da instrução div $r0, $r1, $r2, onde $r0 = $r1/$r2. int harmonico( int n){ if (n <= 1) return 1; else return (1/n + harmonico(n-1)); }
Atividade 9 • Codifique o seguintecódigoem assembly: intfibonacci (int n){ inti, atual = 1, anterior =0, auxiliar; if (n ==0) return 0; if (n ==1) return 1; for(i = 2; i <= n; i++){ auxiliar = atual; atual = atual + anterior; anterior = auxiliar; } return atual; }
Atividade 10 Codifique o seguinte código em assembly: int ack(n: int, m: int){ if (n == 0) ack = m + 1; else if (n > 0 && m == 0) ack = ack(n-1,m); else ack = ack(n-1,ack(n,m-1)); }
Referências • Henessy e Patterson Capítulo 2.