Procedimentos
Chamada de Procedimentos Utilização de procedimentos: Facilitar entendimento do programa Reutilização de código Passos necessários para execução de um procedimento: Os parâmetros a serem acessados pelo procedimento são disponibilizados Controle é transferido para o procedimento Recursos de memória são garantidos ao procedimento A tarefa desejada é realizada pelo procedimento Resultado do procedimento é disponibilizado Controle é retornado para o ponto de origem
Chamada de Procedimentos Registradores utilizados na implementação de procedimentos em MIPS: $a0-$a3: quatro registradores para argumentos para o procedimento $v0-$v1: dois registradores para retorno dos valores do procedimento $ra: endereço de retorno ao final do procedimento Instrução para desviar para início de procedimento: jal endereço-do-procedimento
Chamada de Procedimentos Um registrador denominado PC (Program Counter) armazena o endereço da instrução corrente Registrador $ra armazena valor do PC somado ao número de bytes da instrução de desvio para o procedimento Endereço Instrução 100 call X(a,b,c,d) 104 instr Y X instr K instr L PC = 100 $ra = 104
Chamada de Procedimentos Programa que chama o procedimento: Coloca os parâmetros em $a0-$a3 Executa a instrução jal X Procedimento chamado: Efetua o processamento necessário Armazena os resultados em $v0-$v1 Retorna o controle através da execução da instrução jr $ra
Chamada de Procedimentos Procedimento pode precisar de mais registradores Registradores utilizados pelos procedimentos necessitam ser restaurados na volta Utilização de uma pilha em memória que contém os dados que não podem ser armazenados no registradores disponíveis Operação de push para colocar dado e pop para remover Registrador para armazenar o topo da pilha $sp (stack pointer)
Chamada de Procedimentos Segmento do programa em C int ex1 (int g, int h, int j, int i) { int f: f= (g + h) (i + j); return f; } Segmento do Programa em MIPS ex1: subi $sp,$sp,12 sw $t1,8($sp) sw $t0, 4($sp) sw $s0,0($sp) add $t0,$a0,$a1 add $t1,$a2,$a3 sub $s0,$t0,$t1 add $v0,$s0,$zero lw $s0, 0($sp) lw $t0,4($sp) lw $t1,8($sp) addi $sp,$sp,12 jr $ra
Chamada de Procedimentos Memória alta $ sp $sp Conteúdo de $t1 Conteúdo de $t0 $sp Conteúdo de $s0 Memória baixa a. b. c.
Procedimentos aninhados Procedimentos que chamam outros procedimentos Exemplo: Programa principal: addi $a0, $zero, 3 # coloca 3 em $a0 jal A Procedimento A: addi $a0, $zero, 7 # coloca 7 em $a0, mas não uso valor em $a0 jal B # perdeu endereço de retorno ($ra) ao programa principal Solução: Salvar registradores na pilha
Procedimentos aninhados Procedimento fatorial em C int fact (int n) { { if (n<1) return (1); else return (n*fact(n-1)); Procedimento fatorial em MIPS fact: sub $sp, $sp, 8 sw $ra, 4($sp) sw $a0, 0($sp) slt $t0, $ao, 1 beq $t0, $zero, L1 add $v0, $zero, 1 add $sp, $sp, 8 jr $ra L1: sub $a0, $a0, 1 jal fact lw $a0, 0($sp) lw $ra, 4($sp) add $sp, $sp, 8 mul $v0, $a0, $v0 jr $ra
Chamada de Procedimentos Variáveis locais são armazenadas na pilha: registro de ativação Memória alta $fp $sp $fp Reg. de arg.salvos End. de retorno Reg. de arg.salvos $sp Arrays e estruturas locais Memória baixa $sp a. b. c.
Processo de Compilação e Execução Programa em C Programa em linguagem de montagem Módulo em linguagem de máquina Executável Memória Compilador Montador Ligador Carregador Bibliotecas
Interpretador Realiza tradução, ligação e execução comando a comando do programa fonte Não gera nenhum produto intermediário (código objeto, código executável)
Interpretação versus Compilação Programas interpretados necessitam de mais memória que programas executáveis Programas interpretados são mais lentos Interpretação facilita identificação de erros no programa fonte, tanto na etapa de conversão como na execução (inconsistência de tipos, etc) Ideal: desenvolver em interpretadores e depois disponibilizar um executável
Montador Um montador traduz um arquivo contendo comandos da linguagem de montagem em um outro arquivo contendo instruções e dados em formato binário Montador Montador Ligador Arquivofonte Arquivofonte Arquivoobjeto Arquivoobjeto Arquivoexecutável
Montador Montador em dois passos (lê o arquivo fonte duas vezes) : Primeiro passo: descobre endereço dos labels Segundo passo: traduz cada comando da linguagem de montagem para uma instrução de máquina, associando seqüências numéricas a códigos de operação, a indicadores de registradores e a labels Montador armazena o nome do label e seu endereço na tabela de símbolos
Montador Montador em um passo (lê o arquivo fonte uma vez): Em uma única leitura, uma representação binária é construída Quando aparece um label não definido, gravam-se o label e a instrução em um tabela Quando label é definido, tabela é consultada para saber as instruções que se referenciam a ele Montador volta para trás para completar instruções Toda representação binária tem que estar em memória
Montador Montadores produzem arquivos-objeto: cabeçalho: descreve o tamanho e posição das outras partes do arquivo segmento de texto: contém o código em linguagem de máquina segmento de dados: contém representação binária dos dados do arquivo-fonte informações sobre relocação: identificam as instruções que dependem de endereços absolutos e que devem ser relocados tabela de símbolos: associa endereços a labels externos e referências não resolvidas informações para análise de erros: informações para depuradores
Ligadores e Carregadores Código objeto não é suficiente para ser executado Tarefas a serem executadas Resolução de referências simbólicas (ligação) Ajuste de endereços (relocação) Alocação de espaço em memória (alocação) Colocação das instruções e dados fisicamente na memória (carga) Código Objeto Absoluto: os endereços constantes do código são endereços reais de memória Relocável: os endereços são relativos ao início do programa, transformando-se em endereços reais apenas na execução mais flexível e mais utilizado!
Ligador Rotinas comuns são agrupadas em bibliotecas Ligador resolve as referências externas Agrega o código objeto das bibliotecas a serem utilizadas, criando um único módulo de carga Substitui chamadas a procedimentos por seus endereços Relocação União dos espaços de endereçamento de cada módulo objeto Gera código executável (ou módulo de carga) DLL (Dynamic Link Library) Os procedimentos só são ligados em tempo de execução Ligador Dinâmico
Alocação de memória no MIPS Memória alta $sp 7fff fffc Stack $gp 1000 8000 1000 0000 Dados dinâmicos Dados estáticos Texto Memória baixa pc 0040 0000 0 Reservado
Código objeto Cabeçalho Nome Procedimento A Tamanho do texto 100 hexa Tamanho dos dados 20 hexa Código Endereço Instrução 0 lw $a0, 0($gp) 4 jal 0 Dados 0 (X) Relocação Endereço Tipo de Instr. Dependência Tabela de símbolos 0 lw X 4 jal B Label Endereço X --- B ---
Código objeto cabeçalho Nome Tamanho do texto Tamanho dos dados Procedimento B 200 hex 30 hex Código Endereço Instrução 0 sw $a1, 0($gp) 4 jal 0 --- --- Dados 0 (Y) --- --- Relocação Endereço 0 sw 4 jal 0 Tabela de símbolos Label Endereço Y --- A ---
Código executável cabeçalho Tamanho do texto Tamanho dos dados 300 hex 50 hex Código Endereço Instrução 0040 0000 hex lw $a0, 8000 hex ($gp) 0040 0004 hex jal 40 0100 hex --- --- 0040 0100 hex sw $a1, 8020 hex ($gp) Dados 0040 0104 hex jal 40 0000 hex --- --- Endereço 1000 0000 hex (X) --- --- 1000 0020 hex (Y) --- ---
Carregador O carregador carrega o módulo executável na memória e executa as seguintes funções: Lê cabeçalho do arquivo executável para determinar tamanho dos segmentos de código e dados Cria espaço para armazenar código e dados Copia instruções e dados para a memória Copia os parâmetros para a pilha do programa principal Inicializa registradores e apontador da pilha para primeiro endereço livre Desvia para rotina de inicialização que copia os parâmetros nos registradores de argumento e chama rotina principal. Quando a rotina principal retorna, chama rotina do sistema