Upload
dangliem
View
213
Download
0
Embed Size (px)
Citation preview
ORGANIZAÇÃO E ARQUITETURA DE COMPUTADORES I
AULA 05: LINGUAGEM DE MONTAGEM:
SUPORTE A PROCEDIMENTOS
Prof. Max Santana Rolemberg Farias [email protected]
Colegiado de Engenharia de Computação
O QUE SÃO PROCEDIMENTOS?
• Procedimentos são um conjunto de instruções com função definida. – Realizam uma série de operações com base em valores passados
por parâmetros.
– Podem retornar valores (função).
• A chamada de um procedimento, faz com que o programa execute as instruções contidas no procedimento. – Ao término da execução de um procedimento, o programa deve
executar a instrução seguinte à chamada do procedimento.
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
PARA QUE UTILIZAMOS PROCEDIMENTOS E FUNÇÕES?
• São utilizados para estruturar um programa.
– Facilita entendimento
– Aumenta reuso de código (reutilização do código)
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
COMO UM PROCEDIMENTO É EXECUTADO?
Existem 6 passos para a execução de um procedimento:
1. O programa coloca os parâmetros em um lugar onde o procedimento chamado possa acessá-los.
2. O programa transfere o controle para o procedimento. 3. O procedimento acessa os valores necessários para executar a sua
tarefa. 4. O procedimento executa sua tarefa, gerando valores. 5. O procedimento (chamado) coloca os valores gerados em um local onde
o programa (chamador) possa acessá-lo. 6. O procedimento transfere o controle de volta para o ponto do programa
que o chamou.
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
• Uma CPU simples oferecem alguns registradores específicos para dá suporte a procedimentos.
– Registradores para argumentos ($a0 - $a3): Quatro registradores usados como argumentos para passagem de parâmetros.
– Registradores de retorno ($v0 - $v1): Dois registradores usados para retornar valores.
– Registradores de endereço de retorno ($ra): Registrador que guarda o endereço de retorno (return address) para o ponto do programa que chamou o procedimento.
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
• Uma CPU simple oferecem duas instruções para dá suporte a procedimentos. – Instrução Jump And Link (jal): Pula para o endereço inicial do
procedimento e salva o endereço de retorno (endereço da próxima instrução após chamada).
$ra <- PC + 4
– Instrução Jump Refister (jr): Pula para o endereço armazenado no registrador. No caso de retorno de procedimentos, o registrador deve ser o $ra.
jr $ra
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Formato das Instruções jal
• Salta para o endereço especificado, salvando o endereço da próxima instrução em $ra.
jal addr
$ra <- PC + 4
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Assembly Opcode IMM Linguagem de Máquina
jal 0x200C 0x2 0x200C 0000 1000 0000 0000 0010 0000 0000 1100 (0x0800200C)
Formato das Instruções jr
• Desvio incondicional para endereço guardado em registradores. Para suporte a procedimento o registrador é o $ra.
jr $ra
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Assembly Opcode RS RT RD Shamt Funct Linguagem de Máquina
Jr $ra 0x0 31 0 0 0x0 0x8 0000 0011 1110 0000 0000 0000 0000 1000 (0x03E00008)
COMO PRESERVAR O CONTEXTO DO PROGRAMA?
• Restaurar os valores dos registradores usados pelo procedimento para o valor que tinha antes da chamada.
– Para isso o conteúdo dos registradores deve ser salvo na memória. E depois da execução do procedimento, estes registradores devem ter seus valores restaurados.
• Se as chamadas forem recursivas, é conveniente o uso de uma pilha.
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Implementação com Pilha
• A implementação com pilha é uma solução comum, visto que muitos procedimentos precisam de mais registradores que os especificados para o procedimento. – Pode se utilizar parte da memória como pilha.
• Utilizando o apontador de pilha (Stack Pointer), que é um registrador especifico ($sp) usado para guardar o endereço do topo da pilha da chamada de procedimentos (o registrador guarda o endereço do topo).
• A pilha cresce do endereço mais alto para o mais baixo.
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Organização da memória
• Segmento de texto (text) – Código.
• Dados estáticos (static data)
– Variáveis globais. – Variáveis estáticas. – Em uma CPU simples o registrador $gp guarda o início do segmento.
• Dados dinâmicos (heap) – O malloc da linguagem C
• Pilha (stack) – Variáveis locais – Registradores
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Implementação com Pilha
• Inserir dado na pilha (Push)
$sp <- $sp – 4
• remover dado na pilha (Pop)
$sp <- $sp + 4
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Procedimento simples
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Linguagem de Alto Nível Linguagem de Montagem
int main(){
simples();
...
}
void simples(){
return;
}
0x00400200 jal 0x00401020 #simples()
0x00400204 ...
0x00401020 jr $ra #return
Procedimento com argumentos
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Linguagem de Alto Nível Linguagem de Montagem
int main(){
int y;
...
y = diff_sums(2,3,4,5);
...
}
int diff_sums(int f, int g, int h, int i){
int result;
result = (f + g) – (h + i);
return result;
}
0x00400200 ...
0x00401020 addi $a0 $zero 2 #arg0=2
0x00401024 addi $a1 $zero 3 #arg1=3
0x00401028 addi $a2 $zero 4 #arg2=4
0x0040102C addi $a3 $zero 5 #arg3=5
0x00401030 jal 0x00401048 #diff_sums
0x00401034 add $s0 $v0 $zero #return
0x00401038 ...
0x00401048 add $t0 $a0 $a1 #t0=f+g
0x0040104C add $t1 $a2 $a3 #t1=h+i
0x00401050 sub $s0 $t0 $t1 #s0=t0-t1
0x00401054 add $v0 $s0 $zero #return
0x00401058 jr $ra
A variável y é armazenada nos registrador $s0
Procedimento usando a pilha
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Linguagem de Alto Nível Linguagem de Montagem
int main(){
int y;
...
y = media(2,3,5,6);
...
}
int media(int x, int y, int z, int
w){
int result;
result = (x + y + z + w)/4;
return result;
}
0x00400200 ...
0x00401020 addi $a0 $zero 2 #arg0=2
0x00401024 addi $a1 $zero 3 #arg1=3
0x00401028 addi $a2 $zero 5 #arg2=5
0x0040102C addi $a3 $zero 6 #arg3=6
0x00401030 jal 0x00401048 #media
0x00401034 add $s0 $v0 $zero #return
0x00401038 ...
0x00401048 addi $sp $sp -12 #reservando
0x0040104C sw $t1, 8($sp) #salva $t1
0x00401050 sw $t0, 4($sp) #salva $t0
0x00401054 sw $s0, 0($sp) #salva $s0
A variável y é armazenada no registrador $s0. Os valores de $s0, $t0, $t1 são: 0x3, 0x4 e 0x5.
$s0 (0x3)
$t0 (0x4)
$t1 (0x5)
Procedimento usando a pilha (Continuação)
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Linguagem de Alto Nível Linguagem de Montagem
int main(){
int y;
...
y = media(2,3,5,6);
...
}
int media(int x, int y, int z, int w){
int result;
result = (x + y + z + w)/4;
return result;
}
0x00401038 ...
0x00401048 addi $sp $sp -12 #reservando
0x0040104C sw $t1, 8($sp) #salva $t1
0x00401050 sw $t0, 4($sp) #salva $t0
0x00401054 sw $s0, 0($sp) #salva $s0
0x00401058 add $t0 $a0 $a1 #t0=x+y
0x0040105C add $t1 $a2 $a3 #t1=z+w
0x00401060 add $s0 $t0 $t1 #s0=x+y+z+w
0x00401064 srl $s0 $s0 2 #(x+y+z+w)/4
0x00401068 add $v0 $s0 $zero #return
$s0 (0x3)
$t0 (0x4)
$t1 (0x5)
Procedimento usando a pilha (Continuação)
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Linguagem de Alto Nível Linguagem de Montagem
int main(){
int y;
...
y = media(2,3,5,6);
...
}
int media(int x, int y, int z, int w){
int result;
result = (x + y + z + w)/4;
return result;
}
0x00401038 ...
0x00401058 add $t0 $a0 $a1 #t0=x+y
0x0040105C add $t1 $a2 $a3 #t1=z+w
0x00401060 add $s0 $t0 $t1 #s0=x+y+z+w
0x00401064 srl $s0 $s0 2 #(x+y+z+w)/4
0x00401068 add $v0 $s0 $zero #return
0x0040106C lw $s0 0($sp) #recupera $s0
0x00401070 lw $t0 4($sp) #recupera $t0
0x00401074 lw $t1 8($sp) #recupera $t1
0x00401078 addi $sp $sp, 12 #ajusta top
0x0040107C jr $ra #retorna para main
$s0 (0x3)
$t0 (0x4)
$t1 (0x5)
É POSSÍVEL PROCEDIMENTOS RECURSIVOS?
Procedimento recursivo
LINGUAGEM DE MONTAGEM: SUPORTE A PROCEDIMENTOS
Linguagem de Alto Nível Linguagem de Montagem
int main(){
y = fatorial(3);
...
}
int fatorial(int n){
if (n <= 1)
return 1;
else
return (n * fatorial(n – 1);
}
0x00400200 jal 0x00401020 #fatorial(3)
0x00400204 add $s0 $v0 $zero #y=return
0x0040101C addi $a0 $zero 3 #arg0=3
0x00401020 addi $sp $sp -8 #ajusta a pilha
0x00401024 sw $a0 4($sp) #salva $a0
0x00401028 sw $ra 0($sp) #salva $ra
0x0040102C addi $t0 $zero 2 #t0=2
0x00401030 slt $t0 $a0 $t0 #a0<t0?1:0
0x00401034 beq $t0 $zero 0x00401048
0x00401038 addi $v0 $zero 1 #return 1
0x0040103C addi $sp $sp 8 #restaura pilha
0x00401040 jr $ra #return
0x00401044 addi $a0 $ao -1 #n=n-1
0x00401048 jal 0x00401020 #chamada recursiva
0x0040104C lw $ra 0($sp) #recupera $ra
0x00401050 lw $a0 4($sp) #recupera $a0
0x00401054 addi $sp $sp 8 restaura $sp
0x00401058 mul $v0 $a0 $v0 #n*fatorial(n-1)
0x0040105C jr $ra