Fluxo Seqüencial de Controle e Desvios (1) Nível da Arquitetura do Conjunto das Instruções (Aula 13) Fluxo de Controle Roberta Lima Gomes - LPRM/DI/UFES Sistemas de Programação I Eng. Elétrica 2007/2 Fluxo de Controle: É a seqüência na qual instruções são dinamicamente executadas Isto é, a ordem na qual instruções são executadas no decorrer da execução de um programa. A execução da maioria das instruções não altera o fluxo de controle. Em um fluxo de controle normal as instruções são buscadas em palavras consecutivas da memória Após a execução de uma instrução, a próxima instrução é buscada na memória, incrementando o PC O registrador PC é acrescido de n n = tamanho da instrução que acabou de ser executada O valor do PC é praticamente uma função linear do tempo 2 Fluxo Seqüencial de Controle e Desvios (2) Tempo Desvios Tempo Quando existem desvios, o valor do PC não é mais uma função monótona do tempo! Fluxo Seqüencial de Controle e Desvios (3) Situações em que há que alteração do fluxo de controle de um programa Uso de instruções de desvios (jumps) Chamadas a procedimentos (ex.: CALL) Interrupções e traps Por exemplo, procedimento corrente pára de ser executado e se inicia a execução de um novo procedimento Quando ocorre um desvio em um programa a próxima instrução a ser buscada não é mais a instrução na posição consecutiva da memória...... E sim a instrução armazenada no endereço de destino do desvio. Variação do PC em função do tempo (a) sem desvios e (b) com desvios 3 4
Procedimentos (1) Procedimento é uma seqüência de instruções que pode ser executada várias vezes a partir de diferentes partes de um programa Procedimento X Desvio O procedimento, quando termina sua tarefa, retorna o controle para o comando ou instrução seguinte à instrução de chamada. Procedimentos (2) CALL: Recebe como parâmetro o endereço da primeira instrução do procedimento. A execução da chamada desvia o fluxo de controle para a primeira instrução do procedimento. 5 6 RET: última instrução do procedimento Sua execução desvia o fluxo para a instrução seguinte à chamada corrente do procedimento correspondente. Procedimentos (3) Para poder retornar, é preciso armazenar o endereço de retorno do procedimento em algum lugar. A pilha é o lugar mais indicado para armazenar o endereço de retorno Permite implementar procedimentos que chamam outros procedimentos. 7 Procedimentos (4) Pilha Variáveis Locais: São variáveis que podem ser acessadas de dentro de procedimentos, mas deixam de ser visíveis (acessíveis) quando houver o retorno do procedimento. Não é viável armazenar variáveis locais em endereços absolutos. Há problemas em chamadas recursivas! Pilha: Uma área na memória reservada para o armazenamento de variáveis locais endereço de retorno parâmetros de um procedimento (pode armazenar outras informações). 8
Procedimentos (5) Pilha Para cada novo procedimento chamado, é criado um Quadro no topo da pilha. Para a manipulação da pilha, em geral, existem dois ponteiros: SP Stack Pointer (Aponta para o topo da pilha) Na arquitetura Intel: ESP (Stack Pointer) FP Frame Pointer (Apontador de Quadro Aponta para a base do Quadro corrente). Na arquitetura Intel: EBP (Base Pointer) Quadro Procedimentos (6) void main (){ printf ( COMEÇO ); func (3,1,3); printf ( FIM ); } void func (int n, int i, int j){ int k = n 1 ; if ( k > 1 ) { func (k, i, j); } else printf ( Ultimo FUNC ); } 9 10 Procedimento Recursivo (1) Procedimento Recursivo Procedimento que pode chamar a si próprio (de maneira direta ou indireta). Destacável, pois ajuda no entendimento da mecânica de implementação de chamadas a procedimentos e ilustra o papel das variáveis locais. Torres de Hanói Problema simples, mas ajuda a ilustrar o conceito de recursão. Procedimento Recursivo (2) Torres de Hanói Em um certo mosteiro na cidade de Hanói, foram encontradas três hastes de ouro. Em torno da primeira haste havia um conjunto de 64 discos de ouro, cada um deles com deles com um buraco no centro, que permitia que eles fossem inseridos em qualquer das hastes. Cada um desses discos tinha um diâmetro ligeiramente menor do que aquele que estava encaixado na posição imediatamente abaixo da ocupada por ele. A segunda e a terceira hastes estavam inicialmente vazias. Os monges do mosteiro gastavam grande parte do seu tempo transferindo todos os discos da primeira para a terceira haste, um disco de cada vez, mas de maneira que nunca um disco maior ficasse em cima de um menor. A segunda haste é usada como um caminho intermediário dos discos que saem da primeira para a terceira haste Os monges afirmavam que, quando terminassem a transferência, o mundo iria acabar! 11 12
Procedimento Recursivo (3) Procedimento Recursivo (4) A solução para 3 discos (da haste 1 p/ a 3) Haste 1 Haste 2 Haste 3 Haste 1 Haste 2 Haste 3 Para n = 5 discos 13 14 Procedimento Recursivo (7) A solução para o problema de mover n discos da haste número 1 para a haste número 3 consiste em primeiro mover n 1 discos da haste 1 para a haste 2, depois, mover 1 disco da haste 1 para a haste 3, então, mover n 1 discos da haste 2 para a haste 3 Procedimento Recursivo (8) 15 16
Procedimento Recursivo (9) Procedimento Recursivo (10) Para resolver o problema, define-se um procedimento para mover n discos da haste i para a haste j : towers(n, i, j) Se o valor de n for 1, a solução é trivial movendo um disco da haste i para a haste j. Se n for diferente de 1, a solução é dividida em três partes, cada uma com uma chamada recursiva. towers (n-1, i, k) towers (1, i, j) towers (n-1, k, j) 17 18 Procedimento Recursivo (11) Torres de Hanói (cont.) towers(3, 1, 3) towers(2, 1, 2) towers(1, 1, 3) towers(2, 2, 3) Procedimento Recursivo (12) towers(2, 1, 2) towers(3, 1, 3) towers(1, 1, 3) towers(2, 2, 3) towers(1, 1, 3) towers(1, 1, 2) towers(1, 3, 2) towers(1, 2, 1) towers(1, 2, 3) towers(1, 1, 3) 19 20
Procedimento Recursivo (13) Torres de Hanói (n inicial sendo 3) Suponha a chamada torres(3, 1, 3). Outras 3 chamadas são geradas: torres(2, 1, 2); torres(1, 1, 3); torres(2, 2, 3) Procedimento Recursivo (14) Torres de Hanói Qual será o impacto das chamadas towers(...) na pilha? Assuma uma palavra de 32 bits e uma célula de 1 byte. Cada chamada a towers(...) implica na criação de um quadro na pilha Cada quadro contém (neste ordem) Os parâmetros passados à chamada O endereço de retorno da chamada O valor do FP antigo As variáveis locais O quadro mais recente é o quadro corrente A pilha cresce para cima (dos endereços de memória baixos para os endereços altos) 21 22 Procedimento Recursivo (15) Torres de Hanói towers (3,1,3) towers(2,1,2) towers(1,1,3) 23 towers(1,1,2) Procedimento Recursivo (16) Torres de Hanói Cada chamada a procedimento adiciona um novo quadro à pilha e cada retorno de procedimento remove um quadro da pilha. A primeira chamada a torres coloca na pilha os valores de n, i e j, e depois executa a instrução CALL, que: coloca o endereço de retorno na pilha armazena o valor antigo de FP na pilha, copia o conteúdo de SP em FP (incrementado de 4) avança o ponteiro de topo de pilha (SP) de maneira a alocar a memória para as variáveis locais SP = SP + [tamanho do quadro] O tamanho do quadro depende da quantidade de parâmetros e de variáveis locais do procedimento 24
Exemplo Detalhado: Torres de Hanói Para casa: página 241 do livro texto. (Fig. 5.36) Traps (1) Uma Trap é uma chamada automática de procedimento Causada pela ocorrência de alguma condição especial (exceção) na execução de um programa Detectada pelo hardware ou pelo microprograma Também pode ser chamada de Exceção (Exception) Durante a execução de um programa, uma trap pode ser gerada, por exemplo, quando ocorre um: Overflow em operações aritméticas inteiras e de ponto flutuante Violação de proteção de memória Estouro de capacidade da pilha Divisão por zero etc. 25 26 TRAP Traps (2) Quando há a ocorrência de uma trap, o fluxo de controle é alterado para uma posição fixa da memória Traps (3) PC MUL FFFF Programa de usuário Nesse endereço fixo, há uma instrução de desvio para um Procedimento de Tratamento do Trap Este procedimento (ou rotina) executa as ações convenientes Ex: a impressão de uma mensagem de erro CALL 00B2 Sistema Operacional OUT R1,25... 00B2 Rotina de tratamento de trap 27 28
Traps (4) Os traps são causados pelo próprio programa Um trap é iniciado por algum evento ou condição excepcional, causado pelo própria execução do programa Diferença essencial entre um trap e uma interrupção Traps são síncronos Os traps acontecem sincronamente porque resultam da execução do próprio programa enquanto Se um programa for processado milhões de vezes, com as mesmas entradas, os traps vão ocorrer nos mesmos pontos da execução Interrupções são assíncronas As interrupções podem ser causadas por agentes externos (Ex.: o apertar de uma tecla do teclado). 29 Interrupções Interrupções são modificações no fluxo de controle de um programa causadas por um evento externo ao processamento do programa Geralmente eventos relacionados a operações de E/S. As interrupções (como as traps) também transferem o controle para uma Rotina de Serviço/Tratamento de Interrupção, que executa ações apropriadas O endereço da primeira instrução da RSI está armazenado numa estrutura denominada Vetor de Interrupção. Vetor de Interrupção... 30 RSI RSI Processamento de Interrupções (1) 1 O controlador de um dispositivo ativa uma linha de interrupção no barramento do sistema para iniciar a seqüência de interrupção. 2 O processador ativa no barramento um sinal de reconhecimento da interrupção. 3 O dispositivo envia então um valor inteiro indicando a entrada do Vetor de Interrupções (i.e. o índice). 4- Os conteúdos do PC e do PSW são salvos na pilha. Os valores dos registradores da CPU são temporariamente armazenados (em uma tabela ou na própria pilha) 5 É feita uma chamada à rotina de tratamento de interrupção 6 O tratamento da interrupção, indicado pelo índice no vetor de interrupções, é realizado. 7 Todos os valores originais dos registradores são restaurados. 8 O processador continua o processamento do programa como se nada tivesse acontecido. Processamento de Interrupções (2) Palavra-Chave: Transparência Quando ocorre uma interrupção, algumas ações são tomadas e há execução de código; porém, quando tudo termina, o processador deve voltar exatamente ao mesmo estado que ele tinha antes da interrupção. 31 32
Processamento de Interrupções (3) Exemplo no slide anterior : computador com três dispositivos de E/S, A, B e C, cada um com prioridade 2, 4 e 5 respectivamente. O programa do usuário, inicialmente em execução, possui prioridade zero. O programa do usuário é interrompido pelo dispositivo A. O estado atual da máquina é empilhado e a RSI de A é executada. RSI de A é interrompida pelo dispositivo C (prioridade maior). O estado atual da máquina é empilhado e a RSI de C é executada. Dispositivo B gera interrupção. Como a prioridade do dispositivo B é menor que a prioridade do dispositivo C, o seu pedido de interrupção fica pendente e a RSI de C continua. Quando a RSI de C termina, o estado da RSI de A é desempilhado e nesse mesmo instante a interrupção de B recebe acknowledge. O estado atual da máquina (correspondente à RSI de A) é empilhado novamente. E a RSI de B é executada. Ao fim da RSI de B, o estado da RSI de A é desempilhado e esta rotina continua até o fim. Ao fim da RSI de A, o estado do programa do usuário é desempilhado e o programa continua a sua execução a partir do ponto interrompido, como se nada tivesse ocorrido. 33 Referências Andrew S. Tanenbaum, Organização Estruturada de Computadores, 5ª edição, Prentice-Hall do Brasil, 2007. 34