700 likes | 825 Views
Professor: André Luis Meneses Silva E-mail/msn: andreLuis.ms@gmail.com Página: www.dcomp.ufs.br/index.php/docentes:Andre. Instruções: A Linguagem de Máquina – Aula 02. Introdução. Instruções para tomada de decisões Desvio incondicional Suporte a procedimentos no hardware do computador
E N D
Professor: André Luis Meneses Silva E-mail/msn: andreLuis.ms@gmail.com Página: www.dcomp.ufs.br/index.php/docentes:Andre Instruções: A Linguagem de Máquina – Aula 02
Introdução • Instruções para tomada de decisões • Desvio incondicional • Suporte a procedimentos no hardware do computador • Endereçamento no mips para operandos e endereços de 32 bits. • Endereçamento em desvios condicionais e jumps.
Instruções para a tomada de decisões. • O que distingue um computador de uma calculadora simples? • Capacidade de tomar decisões com base nos dados de entrada e valores calculados. • Em linguagens de alto nível, estruturas típicas de decisão são as construções if, algumas vezes acompanhadas de goto e rótulos (labels). • O assembly do mips possue duas instruções que dão suporte para tomada de decisões (beq e bnq).
Instruções para a tomada de decisões. • beq • Instrução utilizada quando desejamos comparar se dois valores armazenados em registradores, são iguais. • Sintaxe: • beq $r1, $r2, L1, • Onde $r1, $r2 são os registradores cujos valores armazenados vão ser comparados. • Se os valores são iguais, a sequência de execução pula para a instrução que possui o rótulo L1.
Instruções para a tomada de decisões. • bnq • Instrução utilizada quando desejamos comparar se dois valores armazenados em registradores, são diferentes. • Sintaxe: • bnq $r1, $r2, L1, • Onde $r1, $r2 são os registradores cujos valores armazenados vão ser comparados. • Se os valores são diferentes, a seqüência de execução pula para a instrução que possui o rótulo L1. • beq e bnq são instruções conhecidas como desvios condicionais. • Desvios condicionais são instruções que requerem a comparação de dois valores e que leva em conta uma transferência de controle subseqüente para um novo endereço.
Desvio incondicional • O assembly do Mips também dá suporte a instrução de desvio incondicional. • Basicamente, um desvio incondicional é uma instrução que sempre diz que o processador deverá seguir o desvio. • A instrução para isso é a instrução j (jump). • Sintaxe: • j rotulo # pula para a instrução precedida por # rotulo
Instruções para a tomada de decisões. • Vamos ver estas instruções na prática. • Dada a seguinte construção Java, qual o assembly obtido? if ( i == j) f = g + h; else f = g – h;
Instruções para a tomada de decisões. • Vamos ver estas instruções na prática. • Dada a seguinte construção Java, qual o assembly obtido? if ( i == j) f = g + h; else f = g – h; • Calma isso ainda não é o assembly
Instruções para a tomada de decisões. Bne $s3, $s4, Else
Instruções para a tomada de decisões. Bne $s3, $s4, Else add $s0, $s1, $s2
Instruções para a tomada de decisões. Bne $s3, $s4, Else add $s0, $s1, $s2 J Exit;
Instruções para a tomada de decisões. Bne $s3, $s4, Else add $s0, $s1, $s2 J Exit; ELSE:sub $s0, $s1, $s2
Instruções para a tomada de decisões. Bne $s3, $s4, Else add $s0, $s1, $s2 J Exit; ELSE:sub $s0, $s1, $s2 Exit:
Instruções para a tomada de decisões. • Observem que o programador assembly não precisa se preocupar com o cálculo do endereço utilizado nos desvios. • E um laço, como seria? • Nos restringiremos ao laço while. Os demais laços são bastante semelhantes.
Instruções para a tomada de decisões. • Seja o seguinte código Java while (save[i] == k) i += 1; • Qual seria o assembly correspondente, supondo que os valores de i e k estão nos registradores $s3 e $s5, e a base do array save em $s6?
Instruções para a tomada de decisões. • 1. Realizar a leitura de save[i] Loop: sll $t1, $s3, 2 # $t1 = 4 * i add $t1, $t1, $s6 # $t1 = endereço de save[i] lw $t0, 0($t1) # $t0 = save[i] • 2. Teste do loop, terminando se save[i] != k Bne $t0, $s5, Exit #vá para exit se save[i] != k • 3. Senão, adiciona 1 a i e volta para o início. add $s3, $s3, 1 # i = i + 1 j Loop Exit:
Instruções para a tomada de decisões. • Resultado Final Loop: sll $t1, $s3, 2 add $t1, $t1, $s6 lw $t0, 0($t1) Bne $t0, $s5, Exit add $s3, $s3, 1 j Loop Exit: • Código fonte while (save[i] == k) i += 1;
Instruções para a tomada de decisões. • Estas sequências de instruções sem desvios (exceto, possivelmente, no final) e sem destinos de desvio ou rótulos de desvio (exceto, possivelmente, no início) são conhecidas como blocos básicos. • Blocos básicos são muito importante e constituem uma das etapas do projeto de compiladores, basicamente, através deles, podemos realizar algumas otimizações no programa.
Instruções para a tomada de decisões. • As instruções slt e slti • Embora o teste de igualdade e desigualdade seja bastante popular, precisamos também de um outro tipo de comparação. • A instrução slt é usada quando desejamos verificar se o valor armazenado em um registrador é menor que o valor armazenado em um outro registrador. • A instrução slti é usada quando desejamos verificar se o valor armazenado em um registrador é menor que o valor de uma constante literal.
Instruções para a tomada de decisões. • Sintaxe de uso • slt $t1, $r1, $r2 • Basicamente, se o valor em $r1 for menor que o valor em $r2, $t1 recebe o valor 1. Caso contrário, $t1 recebe o valor 0. • slti $t1, $r1, constante • Basicamente, se o valor em $r1 for menor que o valor da constante literal, $t1 recebe o valor 1. Caso contrário, $t1 recebe o valor 0. • E se quisermos fazer algo do tipo se i < j faça, tem como? • Senão tiver como fazer, porque o MIPS é assim?
Instruções para a tomada de decisões. • Realmente não temos como fazer isso, mas há uma razão bastante lógica. • Se o MIPS tivesse uma instrução que já desempenhasse ambos os papéis ele estaria ferindo sua restrição de projeto (no qual, o processador seria dotado de apenas instruções simples). • Logo é preferível quebrar esta instrução mais complexas em duas mais simples e, caso tenhamos necessidade de reproduzirmos um se i < 4 então, utilizamos as instruções apresentadas anteriormente.
Instruções para a tomada de decisões. • O registrador $zero • No MIPS temos um registrador especial que sempre armazena o valor 0. • O registrador $zero em conjunto com slt, slti, beq, bne criam todas as condições relativas: igual, diferente, menor que, maior que, menor ou igual e maior ou igual.
Instruções para a tomada de decisões. • Instruções Case/Switch • O modo mais simples de implementá-las é através de uma cadeia de if-then-else. • Outra forma de implementá-las é através de uma tabela de endereços de desvio. • Para apoiar tais situações, o processador MIPS possui a instrução de desvio incondicional jr (jump register) que pula para o endereço armazenado pelo registrador. • Sintaxe: • jr $r1
Clareando as idéias Processador
Clareando as idéias Processador
Suporte a procedimentos no hardware do computador • Procedimento ou função é um recurso bastante empregado em linguagens de alto nível para modularizar o código. • Podemos ver um procedimento como um espião, pois um espião: • Sai com um plano secreto, adquire recursos, realiza a tarefa, cobre seus rastros e depois retorna ao ponto de origem com o resultado desejado. • De forma similar funcionam os procedimentos, vamos ver como isso funciona.
Suporte a procedimentos no hardware do computador • Na chamada de uma função, alguns registradores do MIPS são reservados para propósito especial, 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.
Suporte a procedimentos no hardware do computador • Além de alocar esses registradores, o assembly do MIPS inclui uma instrução apenas para tratamento de funções/procedimentos. • Esta instrução desvia para um endereço e simultaneamente salva o endereço da instrução seguinte no registrador $ra. • Esta instrução se chama jal (jump-and-link). Sua sintaxe é a seguinte: • jal EndereçoProcedimento
Suporte a procedimentos no hardware do computador • Existe também um outro registrador de próposito específico denominado PC (program counter). • Este registrador armazena o endereço da instrução atual sendo executada. • Então qual endereço salvo por jal no registrador $ra?
Suporte a procedimentos no hardware do computador • Existe também um outro registrador de próposito específico denominado PC (program counter). • Este registrador armazena o endereço da instrução atual sendo executada. • Então qual endereço salvo por jal no registrador $ra? • $PC + 4;
Suporte a procedimentos no hardware do computador • Então, quando ocorre uma chamada de função: • 1. O programa que chama (caller),coloca os valores de parâmetro em $a0 - $a3. • 2. Em seguida, caller, utiliza jal X para desviar o procedimento para o procedimento X (o procedimento chamado é denominado callee). • 3. O callee, então, realiza os cálculos, coloca os resultados em $v0-$v1. • 4. Em seguida o callee retorna o controle para o caller usando jr $ra.
Suporte a procedimentos no hardware do computador • E se precisarmos de mais argumentos além dos 4 registradores para argumentos e os dois para valores de retorno? • O que o callee deve fazer?
Suporte a procedimentos no hardware do computador • O callee executa um processo denominado spilling registers. • A idéia básica é armazenar em memória valores que serão necessários posteriormente para a execução do programa. • A estrutura de dados utilizada para fazer este armazenamento é uma pilha. • Para controle desta pilha, o MIPS possui um registrador especial denominado stack pointer ($sp). • O stack pointer sempre aponta para o último endreço alocado mais recentemente.
Suporte a procedimentos no hardware do computador Stack Pointer Stack 10000
Suporte a procedimentos no hardware do computador Stack Pointer Stack 10000 Valor do registrador $r1 crescimento 9996
Suporte a procedimentos no hardware do computador Stack Pointer Stack 10000 Valor do registrador $r1 9996 crescimento Valor do registrador $r2 9992
Suporte a procedimentos no hardware do computador • Qual seria o código assembly do seguinte procedimento C? int exemplo_folha (int g, int h, int i, int j){ int f; f = (g + h) – (i + j); return f; }
Suporte a procedimentos no hardware do computador • Fazendo o mapeamento dos elementos da função para registradores, teremos: int exemplo_folha (int g, int h, int i, int j){ int f; f = (g + h) – (i + j); return f; } $a0, $a1, $a2, $a3 $s0 $t0 e $t1 $v0
Suporte a procedimentos no hardware do computador • Percebam a existência de registradores conflitantes, ou seja, que já podem estar sendo utilizados ($s0, $t0 e $t1). int exemplo_folha (int g, int h, int i, int j){ int f; f = (g + h) – (i + j); return f; } $s0 $t0 e $t1
$t1 $t0 $s0 Suporte a procedimentos no hardware do computador Alguém chama jal exemplo_folha #Liberando registradores exemplo_folha: addi $sp, $sp, -12 # ajusta a pilha criando #espaço para três itens sw $t1, 8($sp) #salva registradores $t1, $t0 e $s0 sw $t0, 4($sp) # para ser usado depois sw $s0, 0($sp) $sp
Suporte a procedimentos no hardware do computador add $t0, $a0, $a1 # $t0 = g+h add $t1, $a2, $a3 # $t1 = i + j sub $s0, $t0, $t1 # $s0 = (g+h) – (i + j), ou seja, f #Retornando o valor de f add $v0, $s0, $zero int exemplo_folha (int g, int h, int i, int j){ int f; f = (g + h) – (i + j); return f; }
$t1 $t0 $s0 Suporte a procedimentos no hardware do computador #Restaurando os três valores antigos dos registradores lw $s0, 0($sp) lw $t0, 4($sp) lw $t1, 8($sp) addi $sp, $sp, 12 # E finalmente, o procedimento termina jr $ra # Desvia de volta à rotina que chamou $sp $sp
Suporte a procedimentos no hardware do computador • No exemplo anterior, salvamos os valores dos registradores $t0 e $t1. Porém existem casos em que o valor de um registrador pode ser descartado sem problemas. • Por causa disso, o mips separa 18 dos registradores em dois grupos: • $t0-$t9: 10 registradores temporários que não são preservados pelo procedimento chamado (callee) em uma chamada de procedimento. • $s0-$s7: 8 registradores salvos que precisam ser preservados em uma chamada de procedimento (se forem usados, o procedimento chamado os salva e restaura).
Suporte a procedimentos no hardware do computador • O código mostrado anteriormente é perfeitamente aceitável para funções que não fazem chamadas a outras funções. • Funções que não fazem chamadas a outras funções são denominadas folhas. As que chamam outras são denominadas aninhadas. • E para funções aninhadas, como seria? int fact (int n){ if (n < 1) return (1); else return (n * fact(n – 1)); }
Suporte a procedimentos no hardware do computador #Salvando registradores fact: addi $sp, $sp, -8 #ajusta pilha para 2 itens sw $ra, 4($sp) # salva o endereço de retorno sw $a0, 0($sp) # salva o argumento n • int fact (int n){ • if (n < 1) return (1); • else return (n * fact(n – 1)); • }
Suporte a procedimentos no hardware do computador #Condição slti $t0, $a0, 1 # teste para n < 1 Beq $t0, $zero, L1 # se n>=1 vai para L1 • int fact (int n){ • if (n < 1) return (1); • else return (n * fact(n – 1)); • }
Suporte a procedimentos no hardware do computador #Senão for maior que 1, devolve o valor 1. addi $v0, $zero, 1 # retorna 1 addi $sp, $sp, 8 # retira 2 itens da pilha jr $ra #retorna para depois de jal Pessoal, não entendi. Alguém me responda. Porque não restauramos os valores da pilha nesse caso? • int fact (int n){ • if (n < 1) return (1); • else return (n * fact(n – 1)); • }
Suporte a procedimentos no hardware do computador addi $v0, $zero, 1 # retorna 1 addi $sp, $sp, 8 # retira 2 itens da pilha jr $ra #retorna para depois de jal Observem que no caso base, o valor do registrador $ra e $a0 não é alterado, logo não é necessário recuperar os valores dele da memória • int fact (int n){ • if (n < 1) return (1); • else return (n * fact(n – 1)); • }
Suporte a procedimentos no hardware do computador • #Se for maior que 1 L1: addi $a0, $a0 -1 #arg1 = n – 1; jal fact #chama fact(n-1); • int fact (int n){ • if (n < 1) return (1); • else return (n * fact(n – 1)); • }
Suporte a procedimentos no hardware do computador #Restaurando registradores. #A próxima instrução é onde fact retorna. 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 • int fact (int n){ • if (n < 1) return (1); • else return (n * fact(n – 1)); • }