Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Pilhas

653 views

Published on

  • Be the first to comment

  • Be the first to like this

Pilhas

  1. 1. Pilhas <ul><li>Você já deve saber que uma pilha </li></ul><ul><li>é uma estrutura de dados que </li></ul><ul><li>consiste em um amontoado de valo- </li></ul><ul><li>res (empilhados, daí o nome) </li></ul><ul><li>Pilhas serão importantes na execução </li></ul><ul><li>de programas. Veremos a seguir como </li></ul><ul><li>elas são utilizadas </li></ul>
  2. 2. <ul><li>Toda pilha possui duas operações básicas: PUSH, que consiste em adicionar um valor </li></ul><ul><li>na pilha; e POP, que retira da pilha o </li></ul><ul><li>valor presente no topo </li></ul><ul><li>Para a nossa arquitetura, pilhas serão </li></ul><ul><li>blocos contíguos presentes na memó- </li></ul><ul><li>ria principal que conterão dados a serem processados, com um ponteiro SP ( Stack Pointer ) que indicará o endereço onde está o topo da pilha </li></ul><ul><li>À medida que descemos pela memória, os endereços aumentam. Ou seja, sempre que adicionarmos um valor na pilha (PUSH), o ponteiro SP apontará para o endereço atual – 1, um endereço acima </li></ul><ul><li>O contrário acontece para a operação POP </li></ul>
  3. 3. <ul><li>A pilha do exemplo a seguir começa no endereço 1000 da memória, e seu topo está em 996 </li></ul>. . . . . . . . . . . 1000 999 998 997 996 4 9 7 2 5 SP
  4. 4. <ul><li>Fazendo PUSH 3, o valor 3 será acrescentado na pilha, e o topo será o endereço 996 – 1 = 995 </li></ul>. . . . . . . . . . . 1000 999 998 997 996 4 9 7 2 5 SP 995 3
  5. 5. <ul><li>Por outro lado, se tivéssemos feito POP, o valor 9 passaria a ser lixo e o novo topo estaria em 996 + 1 = 997 </li></ul>. . . . . . . . . . . 1000 999 998 997 996 4 9 7 2 5 SP
  6. 6. <ul><li>Algumas linguagens de programação são organizadas em blocos (escopos) </li></ul><ul><li>Em Java, por exemplo, o escopo de uma classe são todos os procedimentos existentes naquela classe, e no escopo de cada procedimento existem todas as operações realizadas por ele, inclusive eventuais chamadas a outros procedimentos </li></ul>
  7. 7. <ul><li>Para essas linguagens, é interessante utilizar pilhas durante a execução de um programa para liberar o espaço ocupado pelas variáveis locais de um procedimento, quando ele é finalizado </li></ul><ul><li>Variáveis locais são variáveis utilizadas e conhecidas exclusivamente nos procedimentos onde foram inicializadas, e no nível de macroprogramação são geralmente carregadas nas pilhas </li></ul><ul><li>Já as variáveis globais são variáveis conhecidas em todo o programa e a princípio estão presentes em endereços da memória que não fazem parte da pilha de um procedimento em particular </li></ul>
  8. 8. <ul><li>Além das operações PUSH e POP, outra operação útil para pilhas é mover arbitrariamente o ponteiro SP, sem inserir dados inicialmente </li></ul><ul><li>Isto é útil para quando a execução entrar em um procedimento que utilizará variáveis locais, de maneira que SP será decrementado (topo subirá) para reservar espaço para essas variáveis </li></ul><ul><li>Em Pascal, isso fica fácil de ser visto, já que as variáveis locais são inicializadas antes da palavra begin , que indica o começo do procedimento </li></ul><ul><li>O exemplo a seguir mostra o começo do método de ordenação BubbleSort , em Pascal </li></ul>
  9. 9. <ul><li>procedure BubbleSort(var A: ArrayType); </li></ul><ul><li>var i, j: integer; </li></ul><ul><li>begin </li></ul><ul><li>. </li></ul><ul><li>. </li></ul><ul><li>. </li></ul><ul><li>Repare que as variáveis i e j são inicializadas. Em seguida, a palavra begin indica o começo das operações do procedimento – é neste ponto onde SP é decrementado em 2 </li></ul><ul><li>A pilha agora ocupa mais 2 espaços: os espaços de i e j , que eventualmente receberão valores durante a execução do procedimento </li></ul><ul><li>E se o topo da pilha atingir endereços que já estão sendo usados pelo programa? </li></ul>
  10. 10. <ul><li>Familiar? </li></ul><ul><li>Agora vamos supor uma função, também em Pascal, que recebe duas entradas e retorna como resultado o produto entre elas </li></ul><ul><li>Perceba como fica sua pilha de execução </li></ul>
  11. 11. <ul><ul><ul><li>function produto(a, b: integer): integer; </li></ul></ul></ul><ul><ul><ul><li>var p, j: integer; </li></ul></ul></ul><ul><ul><ul><li>begin </li></ul></ul></ul><ul><ul><ul><li>if (a = 0) or (b = 0) then </li></ul></ul></ul><ul><ul><ul><li>produto := 0 </li></ul></ul></ul><ul><ul><ul><li>else </li></ul></ul></ul><ul><ul><ul><li>begin </li></ul></ul></ul><ul><ul><ul><li>p := 0; </li></ul></ul></ul><ul><ul><ul><li>for j := 1 to a do </li></ul></ul></ul><ul><ul><ul><li>p := p + b; </li></ul></ul></ul><ul><ul><ul><li>produto := p; </li></ul></ul></ul><ul><ul><ul><li>end </li></ul></ul></ul><ul><ul><ul><li>end; </li></ul></ul></ul>a b <ul><li>Quando a função é chamada no programa, já temos na pilha as variáveis de entrada, e precisamos também do endereço de retorno, para que o processador saiba para onde voltar quando a função terminar </li></ul>end. ret. SP
  12. 12. <ul><ul><ul><li>function produto(a, b: integer): integer; </li></ul></ul></ul><ul><ul><ul><li>var p, j: integer; </li></ul></ul></ul><ul><ul><ul><li>begin </li></ul></ul></ul><ul><ul><ul><li>if (a = 0) or (b = 0) then </li></ul></ul></ul><ul><ul><ul><li>produto := 0 </li></ul></ul></ul><ul><ul><ul><li>else </li></ul></ul></ul><ul><ul><ul><li>begin </li></ul></ul></ul><ul><ul><ul><li>p := 0; </li></ul></ul></ul><ul><ul><ul><li>for j := 1 to a do </li></ul></ul></ul><ul><ul><ul><li>p := p + b; </li></ul></ul></ul><ul><ul><ul><li>produto := p; </li></ul></ul></ul><ul><ul><ul><li>end </li></ul></ul></ul><ul><ul><ul><li>end; </li></ul></ul></ul>a b end. ret. p j <ul><li>Já ao final desta linha, precisamos de mais 2 para as variáveis locais p e j </li></ul>SP
  13. 13. <ul><ul><ul><li>function produto(a, b: integer): integer; </li></ul></ul></ul><ul><ul><ul><li>var p, j: integer; </li></ul></ul></ul><ul><ul><ul><li>begin </li></ul></ul></ul><ul><ul><ul><li>if (a = 0) or (b = 0) then </li></ul></ul></ul><ul><ul><ul><li>produto := 0 </li></ul></ul></ul><ul><ul><ul><li>else </li></ul></ul></ul><ul><ul><ul><li>begin </li></ul></ul></ul><ul><ul><ul><li>p := 0; </li></ul></ul></ul><ul><ul><ul><li>for j := 1 to a do </li></ul></ul></ul><ul><ul><ul><li>p := p + b; </li></ul></ul></ul><ul><ul><ul><li>produto := p; </li></ul></ul></ul><ul><ul><ul><li>end </li></ul></ul></ul><ul><ul><ul><li>end; </li></ul></ul></ul>a b end. ret. <ul><li>Quando a função termina, os espaços das variáveis locais são liberados. Em outras palavras, SP é incrementado em 2, voltando a ser o endereço de retorno. Este endereço dirá onde a execução estava quando chamou a função produto , e ela continuará a partir daquele ponto </li></ul>SP
  14. 14. <ul><li>Com apenas estas descrições, fica a </li></ul><ul><li>impressão de que a função foi inútil, </li></ul><ul><li>já que a pilha guardou apenas seus </li></ul><ul><li>valores de entrada e manipulou as variáveis locais </li></ul><ul><li>Mas é óbvio que isto não é verdade. De que maneira então foram usadas as variáveis </li></ul><ul><li>a e b para chegar até o resultado final, </li></ul><ul><li>e onde ele foi parar? </li></ul><ul><li>Todos os resultados de operações intermediárias foram sendo armazenados no nosso registrador AC (Accumulator). O mesmo vale para o resultado final da função, que pode ser apenas um valor intermediário para o resto do programa </li></ul>
  15. 15. <ul><li>O endereço de retorno está relacionado a outro registrador, o Program Counter </li></ul><ul><li>Quando a função produto termina, o endereço de retorno é desempilhado e salvo em PC </li></ul><ul><li>Caso você não se lembre, AC e PC são dois dos nossos 16 registradores conectados aos barramentos A, B e C em N0 </li></ul><ul><li>Isso nos dá bagagem suficiente para falar sobre o nível de macroprogramação </li></ul>

×