Slide 1 - Arquitetura de Computadores UFS 2008/1

Propaganda
Instruções: A Linguagem de
Máquina – Aula 02
Professor: André Luis Meneses Silva
E-mail/msn: [email protected]
Página: www.dcomp.ufs.br/index.php/docentes:Andre
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
decisões.


a
tomada
de
O que distingue um computador de uma
calculadora simples?


para
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
decisões.

para
a
tomada
de
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
decisões.

a
tomada
de
bnq


Instrução utilizada quando desejamos comparar se dois
valores armazenados em registradores, são diferentes.
Sintaxe:

bnq $r1, $r2, L1,



para
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
decisões.

para
a
tomada
de
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
decisões.

para
a
tomada
de
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
decisões.
para
Bne $s3, $s4, Else
a
tomada
de
Instruções
decisões.
para
Bne $s3, $s4, Else
add $s0, $s1, $s2
a
tomada
de
Instruções
decisões.
para
Bne $s3, $s4, Else
add $s0, $s1, $s2
J Exit;
a
tomada
de
Instruções
decisões.
para
Bne $s3, $s4, Else
add $s0, $s1, $s2
J Exit;
ELSE:sub $s0, $s1, $s2
a
tomada
de
Instruções
decisões.
para
Bne $s3, $s4, Else
add $s0, $s1, $s2
J Exit;
ELSE:sub $s0, $s1, $s2
Exit:
a
tomada
de
Instruções
decisões.



para
a
tomada
de
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
decisões.

para
a
tomada
de
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
decisões.
para
a
tomada
de
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
decisões.

para
Código fonte
while (save[i] == k)
i += 1;
a
tomada
de
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:

Instruções
decisões.


para
a
tomada
de
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
decisões.

para
a
tomada
de
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
decisões.



a
tomada
de
Sintaxe de uso


para
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
decisões.



para
a
tomada
de
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
decisões.

para
a
tomada
de
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
decisões.

para
a
tomada
de
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
Memória de
Dados
0
1
2
3
...
9
00000000
00000100
00001000
00001100
...
00100100
Memória de
Instruções
0
1
2
3
...
9
00000000
00000100
00001000
00001100
...
00100100
Clareando as idéias
Processador
Memória de
Dados
0
1
2
3
...
9
00000000
00000100
00001000
00001100
...
00100100
Memória de
Instruções
0
1
2
3
...
9
00000000
00000100
00001000
00001100
...
00100100
Suporte
a
procedimentos
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:


no
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
hardware do computador

no
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
hardware do computador



no
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
hardware do computador



no
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
hardware do computador



no
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
hardware do computador

no
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
hardware do computador


no
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
hardware do computador

no
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
hardware do computador
Stack Pointer
Stack
10000
no
Suporte
a
procedimentos
hardware do computador
Stack
10000
9996
Valor do registrador $r1
crescimento
Stack Pointer
no
Suporte
a
procedimentos
hardware do computador
Stack Pointer
no
Stack
Valor do registrador $r1
9996
Valor do registrador $r2
9992
crescimento
10000
Suporte
a
procedimentos
hardware do computador
no
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
hardware do computador

no
Fazendo o mapeamento dos elementos da
função para registradores, teremos:
$a0, $a1, $a2, $a3
int exemplo_folha (int g, int h, int i, int j){
int f;
$s0
f = (g + h) – (i + j);
return f;
}
$t0 e $t1
$v0
Suporte
a
procedimentos
hardware do computador

no
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;
$s0
f = (g + h) – (i + j);
return f;
}
$t0 e $t1
Suporte
a
procedimentos
hardware do computador
no
Alguém chama jal exemplo_folha
#Liberando registradores
exemplo_folha:
addi $sp, $sp, -12 # ajusta a pilha criando
#espaço para três itens$sp
$t1
$t0
$s0
sw $t1, 8($sp) #salva registradores $t1, $t0 e $s0
sw $t0, 4($sp) # para ser usado depois
sw $s0, 0($sp)
Suporte
a
procedimentos
hardware do computador
add $t0, $a0, $a1
add $t1, $a2, $a3
sub $s0, $t0, $t1
no
# $t0 = g+h
# $t1 = i + j
# $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;
}
Suporte
a
procedimentos
hardware do computador
no
#Restaurando os três valores antigos dos
registradores
lw $s0, 0($sp)
lw $t0, 4($sp)
lw $t1, 8($sp)
addi $sp, $sp, 12
$t1
$t0
$sp
$s0
$sp
# E finalmente, o procedimento termina
jr $ra # Desvia de volta à rotina que chamou
Suporte
a
procedimentos
hardware do computador


no
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.
s
$s0-$s7: 8 registradores
alvos que precisam ser
preservados em uma chamada de procedimento (se
forem usados, o procedimento chamado os salva e
restaura).
Suporte
a
procedimentos
hardware do computador



no
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
hardware do computador
no
#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
hardware do computador
#Condição
slti $t0, $a0, 1
Beq $t0, $zero, L1
# teste para n < 1
# se n>=1 vai para L1
int fact (int n){
if (n < 1) return (1);
else return (n * fact(n – 1));
}
no
Suporte
a
procedimentos
hardware do computador
no
#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
hardware do computador
no
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
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));
}
no
Suporte
a
procedimentos
hardware do computador
no
#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));
}
Suporte
a
procedimentos
hardware do computador
no
#Devolvendo o novo $v0
mul $v0, $a0, $v0 # retorna n * fact( n - 1)
jr $ra # retorna para o procedimento que o chamou
int fact (int n){
if (n < 1) return (1);
else return (n * fact(n – 1));
}
Suporte
a
procedimentos
hardware do computador


Para resumo de história, quem salva o que na
pilha?
Caller



no
Salva os registradores de argumentos.
Salva os registradores temporários ($t0-$t9) que serão
necessários após a chamada da função.
Callee


Salva os registradores salvos ($s0-$s8)
Salva o registrador que armazena o endereço de
retorno ($ra)
Suporte
a
procedimentos
hardware do computador

Além dos elementos já citados, a pilha também
pode ser utilizada para armazenar outros
elementos.



no
Alguns exemplos são variáveis locais (tais como arrays
ou estruturas) que não cabem em registradores.
Este segmento da pilha relativo a um
procedimento é conhecido como frame ou
registro de ativação.
Em geral os processadores possuem um
processador específico para apontar para o
início do frame. Este registrador é conhecido
como frame pointer ($fp).
Suporte
a
procedimentos
hardware do computador
no
Suporte
a
procedimentos
hardware do computador


no
O frame pointer, assim como o stack pointer, é
utilizado nas instruções que alocam e
recuperam dados do frame.
Mas se ambos registradores possuem a mesma
funcionalidade, então para que termos o
frame pointer?
Suporte
a
procedimentos
hardware do computador


no
O frame pointer, assim como o stack pointer, é
podem ser utilizados nas instruções que alocam
e recuperam dados do frame.
Mas se ambos registradores possuem a mesma
funcionalidade, então para que termos o
frame pointer?

O frame pointer, ao contrário do stack pointer, não
tem seu valor alterado durante o procedimento.
Logo se torna mais fácil recuperar dados utilizando o
valor do stack pointer.
Suporte
a
procedimentos
hardware do computador


O assunto que vimos até o momento, é aplicado
apenas para variáveis automáticas (ou seja) locais aos
procedimentos.
No entanto ainda faltam tratar dois casos:





no
Variáveis globais (ou estáticas).
Estruturas de dados dinâmicas.
Estes elementos, quando em memória, não são
alocados no stack.
Os dados estáticos podem ser acessados através do
registrador $gp.
Os dados dinâmicos é armazenado em uma região de
memória denominada heap.
Suporte
a
procedimentos
hardware do computador
no
Endereçamento no MIPS para
operandos e endereços de 32 bits



Até o momento, consideramos que endereços
de memória já estariam em registradores.
Lembrem-se que cada endereço de memória
é representado por 32 bits.
Lembrando que as instruções com constantes
(imediatas) do mips só trabalham com 16 bits.
Como fazemos para armazenar endereços de
memória em registradores?
Endereçamento no MIPS para
operandos e endereços de 32 bits

Precisamos usar duas instruções; nova instrução
“load upper immediate”:
Endereçamento no MIPS para
operandos e endereços de 32 bits

Depois, precisamos acertar os bits de ordem
inferior, por exemplo:
Endereçamento
em
condicionais e jumps


desvios
Já a instrução de desvio condicional jump
utiliza um terceiro formato de instrução (tipo j).
Nessas instruções temos 26 bits para especificar
o local para onde desejamos desviar.
Endereçamento em desvios
condicionais e jumps




No entanto, para desvios condicionais temos
um problema:
Nosso campo de desvio só possui 16 bits.
Fazendo os cálculos, 216 = 65536;
E agora pessoal, será que no MIPS só podemos
fazer programas de no máximo 64 kbytes?
Endereçamento em desvios
condicionais e jumps


Para evitar este problema, os processadores
trabalham com uma técnica denominada de
endereçamento relativo.
Basicamente a idéia é associar o endereço
expresso em uma instrução condicional a um
outro elemento (registrador).

Qual seria este registrador?
Endereçamento em desvios
condicionais e jumps


Para evitar este problema, os processadores
trabalham com uma técnica denominada de
endereçamento relativo.
Basicamente a idéia é associar o endereço
expresso em uma instrução condicional a um
outro elemento (registrador).

Qual seria este registrador?
 O registrador utilizado é o PC. Lembrem-se o PC a
todo momento se atualiza, armazenando o endereço
da instrução atual, sendo executada.
Endereçamento em desvios
condicionais e jumps

Porque isso resolve?
Endereçamento em desvios
condicionais e jumps

Porque isso resolve?


Isso resolve porque, em geral, os endereços de desvio
não ficam muito longe dos locais onde é solicitado o
desvio.
Mas e para chamada de funções? Tem algum
sentido ela ficar próxima do local do desvio?
Como isso é resolvido?
Endereçamento em desvios
condicionais e jumps

Porque isso resolve?


Isso resolve porque, em geral, os endereços de desvio não
ficam muito longe dos locais onde é solicitado o desvio.
Mas e para chamada de funções? Tem algum sentido
ela ficar próxima do local do desvio? Como isso é
resolvido?


Lembrem-se que para funções utilizamos j ou jr que
possuem um espaçamento de bits ainda maior (26 bits).
Adicionalmente, o MIPS otimiza isso tudo. Seu
endereçamento é feito por palavras (endereçamento
alinhado), logo o espaço de endereçamento aumenta em
mais 4 vezes.
Formas de endereçamento.

Endereçamento em Registrador


Endereçamento imediato


Onde o operando está no local de memória cujo endereço é a soma de um
registrador e uma constante.
 lw, sw
Endereçamento relativo ao PC


Onde o operando é uma constante dentro da própria instrução
 addi e subi, por exemplo.
Endereçamento de base


Onde o operando é um registrador
 add e sub, por exemplo.
Onde o endereçamento é a soma do PC e uma constante na instrução
 bne, beq, por exemplo.
Endereçamento pseudodireto.

Onde o endereço de jum são os 26 bits da instrução concatenados com os
bits mais altos do PC.
 j e jr.
Bibliografia


Patterson & Hennessy. Organização e Projeto
de Computadores.
Seção 2.6 a 2.7 e 2.9
Download