Post on 12-Dec-2015
description
UNIVERSIDADE ESTADUAL PAULISTA
“JÚLIO DE MESQUITA FILHO” Faculdade de Engenharia de Ilha Solteira
Departamento de Engenharia Elétrica
4º Experimento
Pilhas e Subrotinas
Aluno: Nercival Buschieri Júnior R.A.: 11052091 Grupo 7
Discuplina: Microprocessadores I Turma: P4
Docente: Prof. Dr. Alexandre César Rodrigues da Silva
Relatório referente ao experimento realizado no dia 19/04 e entregue em 02/05.
Ilha Solteira – 2013
2
Sumário 1. Objetivos ......................................................................................................................... 1
2. Introdução Teórica.......................................................................................................... 3
2.1 Pilhas...............................................................................................................................3
2.2 Subrotinas.......................................................................................................................4
3. Procedimento Experimental e Apresentação de Resultados.......................................6
3.1 Contador Hexadecimal Crescente..............................................................................6
3.2 Contador Decimal Crescente......................................................................................8
3.3 Contador Decimal Decrescente................................................................................10
3.4 Visualizador de Programa.........................................................................................13
4. Conclusão e Comentários Finais...............................................................................16
5. Referências..............................................................................................................17
3
1. Objetivos
Entender o conceito de PILHA e apresentar as instruções de Subrotinas do 8085.
2. Introdução Teórica
2.1 Pilha
Como já foi dito anteriormente, a Pilha é uma região da memória RAM,
definida pelo usuário, para guardar valores que serão usados posteriormente.
Assim, o usuário pode guardar o conteúdo de qualquer registrador (dois a dois: A e
Flags, B e C, D e E, H e L) na pilha e o microprocessador guarda automaticamente
os endereços de retorno de subrotinas comuns e de subrotinas de interrupções. A
seguir é ilustrada a região da memória definida como Pilha (Stack).
Observações:
(a) O conteúdo guardado na pilha é sempre de 16 bits. Assim, o microprocessador
normalmente guarda o conteúdo de PC, que já é de 16 bits, mas o usuário
normalmente guarda o conteúdo de registradores de 8 bits, que então são
associados 2 a 2;
(b) Os registradores duplos que podem ser guardados na pilha são PSW (= A +
Flags), B (= B + C), D (=D + E) e H (= H + L);
(c) Para guardar o conteúdo de um desses registradores duplos usa-se a instrução
PUSH rp;
(d) Para recuperar o conteúdo que foi guardado na pilha usa-se a instrução POP rp;
(e) Quando uma informação é enviada para a pilha o byte mais significativo é
guardado primeiro; isso
significa que o byte menos significativo vai ser retirado primeiro porque o último
dado armazenado é o primeiro a ser retirado;
(f) A pilha do 8085 evolui do maior endereço para o menor, ou seja, a cada vez que
uma informação (2 bytes) é enviada para a pilha, o endereço do topo da pilha é
reduzido de 2. Ele é acrescido de 2 quando a informação é retirada da pilha;
(g) O apontador de pilha SP aponta sempre para o topo da pilha, mas ele é
incrementado de 1 antes de cada byte ser armazenado.
Exemplo de armazenamento na pilha:
Supondo que inicialmente SP = 2090 h, A = 01 h, F = 23 h, B = 45 h e C = 67 h, as
figuras a seguir mostram a evolução da pilha após cada instrução dada. A região
em destaque corresponde à posição apontada por SP após a instrução.
4
Figura 2.1.1 – Exemplo de armazenagem na pilha.
Observações:
(I) Apesar da região da pilha continuar com o mesmo conteúdo após as instruções
POP rp, eles não acessíveis porque o Apontador de Pilha SP aponta para a posição
original, de quando a pilha estava vazia;
(II) POP B vem antes de POP PSW porque a ordem de retirada da pilha é inversa à
ordem de armazenagem.
2.2 Subrotinas
As subrotinas são mais um tipo de instrução de desvio, ou seja, alteram o
fluxo normal do programa. Trata-se de um grupo de instruções escrito
separadamente do programa principal, para executar uma função que ocorre
repetidamente no programa principal. Seu principal objetivo é dividir o programa
em tarefas simples e modulares e criar procedimentos que podem ser “chamados”
de diversos pontos do programa, facilitando assim a construção do programa.
As instruções das sub-rotinas no 8085 funcionam basicamente da seguinte
forma:
Temos as instruções incondicionais:
CALL<addr16> : É usado no programa principal para chamar a sub-rotina.
RET: É utilizado no final da sub-rotina para retornar ao programa principal.
Quando uma sub-rotina é chamada, o conteúdo do PC (Program Counter),
que é o endereço da instrução seguinte ao da instrução CALL, é armazenado na
Pilha e a execução do programa é transferida para o endereço da sub-rotina.
Quando a instrução RET é executada no final da sub-rotina, o endereço de
memória armazenado na Pilha é retirado e a sequência de execução é retomada
no programa principal a partir do endereço retirado do SP.
5
Há também as instruções condicionais para a chamada e retorno das
subrotinas:
CALL condicional:
CC => Chama a sub-rotina se o Flag Carry é 1 (CY = 1)
CNC => Chama a sub-rotina se o Carry é 0 (CY = 0)
CZ => Chama a sub-rotina se o Flag Zero = 1 (Z = 1)
CNZ => Chama a sub-rotina se Zero = 0 (Z=0)
CM => Chama a sub-rotina se Sinal = 1 (S=1 – Número negativo)
CP => Chama a sub-rotina se Sinal = 0 (S=0 = Número positivo)
CPE => Chama a sub-rotina se Paridade = 1 (P=1 – paridade par)
CPO => Chama a sub-rotina se Paridade = 0 (P=0 – paridade impar)
RET condicional:
RC => Retorna se o Flag Carry é 1 (CY = 1)
RNC => Retorna se o Carry é 0 (CY = 0)
RZ => Retorna se o Flag Zero = 1 (Z = 1)
RNZ => Retorna se Zero = 0 (Z=0)
RM => Retorna se Sinal = 1 (S=1 – Número negativo)
RP => Retorna se Sinal = 0 (S=0 = Número positivo)
RPE => Retorna se Paridade = 1 (P=1 – paridade par)
RPO => Retorna se Paridade = 0 (P=0 – paridade impar)
6
3. Procedimento Experimental e Apresentação de resultados
3.1 Contador Hexadecimal Crescente
Devia-se fazer um programa para contar de 00H até FFH indefinidamente,
mostrando o valor da contagem de dados no display e usar a subrotina delay para
facilitar a sua visualização.
O Fluxograma a seguir, mostra a ideia geral do programa.
Início
Define a pilha
A<=00H
Joga o valor de
A na pilha
Call UPDAD
Define o tempo do
delay no reg. par DE
Call Delay
A<=A+1
Pega o valor da pilha
e devolve para A
7
A Tabela 3.1.1 mostra o programa elaborado:
Tabela 3.1.1 – Contador de 00H até FFH utilizando pilha.
Endereço MNEMONIC Op. Code Comentário 2000 LXI SP, 20B0H 31 B0 20 Define a posição inicial da pilha em 20B0H. 2003 MVI A, 00H 3E 00 Carrega A com 00H. 2005 PUSH PSW F5 Manda o valor dos regs. A e F pra pilha,
considerando A como byte superior. 2006 CALL 0363H CD 6E 03 Chama a subrotina UPDAD. 2009 LXI D, 0F00H 11 00 0F Carrega o par DE com 0F00H para ser usado
pela subrotina Delay. 200C CALL 05F1H CD F1 05 Chama a subrotina Delay. 200F POP PSW F1 Devolve os valores armazenados na pilha para
os reg. A e F, na mesma ordem em que foram retirados.
2010 INR A 3C Incrementa o reg. A, fazendo sua contagem. 2011 JMP 2005 C3 05 20 Pula para a instrução 2005.
A Figura 3.1.1 mostra a simulação do programa no Abacus.
Figura 4.1.1 – Simulação do contador hexadecimal no Abacus.
8
3.2 Contador Decimal Crescente
Modificamos o programa anterior de para que ele apresente contagem em
decimal.
A ideia do programa é a mesma, apenas fizemos o ajuste decimal, utilizando o
comando DAA.
Início
Define a pilha
A<=00H
Joga o valor de
A na pilha
Call UPDAD
Define o tempo do
delay no reg. par DE
Call Delay
A<=A+1
Pega o valor da pilha
e devolve para A
Ajuste decimal
9
A Tabela 3.2.1 mostra o algoritmo do programa com comentários.
Tabela 3.2.1 – Contador decimal crescente.
Endereço MNEMONIC Op. Code Comentário 2000 LXI SP, 20B0H 31 B0 20 Define a posição inicial da pilha em 20B0H. 2003 MVI A, 00H 3E 00 Carrega A com 00H. 2005 ORA A B7 2006 DAA 27 2007 PUSH PSW F5 Manda o valor dos regs. A e F pra pilha,
considerando A como byte superior. 2008 CALL 0363H CD 6E 03 Chama a subrotina UPDAD. 200B LXI D, 0F00H 11 00 0F Carrega o par DE com 0F00H para ser usado
pela subrotina Delay. 200E CALL 05F1H CD F1 05 Chama a subrotina Delay. 2011 POP PSW F1 Devolve os valores armazenados na pilha para
os reg. A e F, na mesma ordem em que foram retirados.
2012 INR A 3C Incrementa o reg. A, fazendo sua contagem. 2013 JMP 2005 C3 05 20 Pula para a instrução 2005.
A Figura 3.2.1 mostra a simulação do programa no Abacus.
Figura 3.2.1 – Simulação do contador decimal crescente.
10
3.3 Contador Decimal Decrescente
Agora, devia-se fazer um programa que faça a contagem hexadecimal em
ordem decrescente e usar a subrotina DELAY de modo que se obtivesse intervalo
de 1 segundo entre as contagens.
Início
A<=99H
Deifniu-se a pilha:
SP<=20B0H
Coloca o valor
de A na pilha
(PUSH PSW)
Call UPDDT
Call DELAY
1segundo
A=A-1
Pega nibble menos
significativo
(mascara nibble
mais significativo)
A-0FH=00 ?
Devolve o valor da
pilha para o reg. A
(POP PSW)
B<=A
A<=B
A<=A-06H
B<=A
YES
A<=B
A-F9H=00 ?
ANI 9FH
Jump
NO
YES
NO
11
A ideia principal ainda consistia na mesma dos programas anteriores,
entretanto agora, nós mesmos tivemos que fazer o ajuste decimal. Para isso,
partimos de 99 e fomos decrementando esse numero. Ao chegar 90, como a
máquina conta em hexadecimal, o próximo número seria 8FH. Para fazer o ajuste
decimal, subtraímos 06H do nibble menos significativo, de forma a obter 89 e
continuar a contagem, usando o mesmo procedimento.
Ao chegarmos em 00, o próximo número que a maquina iria seria FFH. O
ajuste do nibble menos significativo foi mesmo procedimento utilizado para os
outros números. O nibble mais significativo, fizemos uma opereção de AND FH
com 9H, o que resulta em 9 e, portanto, ajusta a contagem do programa voltando
para 99.
Para obtermos um intervalo de 1 segundo, chamamos a subrotina DELAY
duas vezes, uma com temporização FFFFH e outra 7D7EH. Usando o módulo MC-1,
de fato tivemos cerca de 1s de intervalo, entretanto no simulador Abacus, o
intervalo foi bem maior, talvez porque os tempos de processamento de dados
sejam diferentes. A Tabela 3.3.1 mostra o algoritmo do programa com
comentários.
Tabela 3.3.1 – Contador decimal decrescente.
Endereço MNEMONIC Op. Code Comentário 2000 LXI SP, 20B0 31 B0 20 Define a posição inicial da pilha em 20B0H. 2003 MVI A, 99H 3E 99 Carrega A com 99H. 2005 PUSH PSW F5 Coloca o valor de A na pilha. 2006 CALL 036E CD 6E 03 Chama a subrotina UPDDT para exibir o dado no Dislpay. 2009 LXI D, 7D7EH 11 7E 7D Carrega DE com 7E7EH, que será um tempo para o delay. 200C CALL 05F1H CD F1 05 Chama a subrotina DELAY. 200F LXI D, FFFFH 11 FF FF Carrega DE com 7E7EH, que outro tempo para o delay. 2012 CALL 05F1H CD F1 05 Chama a subrotina DELAY. 2015 POP PSW F1 Transfere o valor da pilha para o reg. A. 2016 SUI 01H D6 01 Decrementa A. 2018 MOV B,A 47 Move o valor de A para o reg. B. 2019 ANI 0FH E6 0F Mascara o nibble mais significativo. 201B CPI 0FH FE 0F Compara com 0FH para ajustar a decrementação decimal. 201D CZ 202AH CC 2A 20 Se Z=1, chama a subrotina em 202A. 2020 MOV A, B 78 Move o conteúdo do reg. B para o reg. A. 2021 ORA A B7 Faz CY=0. 2022 CPI F9H FE F9 Compara com F9H. para fazer o ajuste para decimal. 2024 CZ 202FH CC 2F 20 Se Z=1, então vai para a subrotina em 202F. 2027 JMP 2005H C3 05 20 Pula para a instrução presente no endereço 2005H. 202A MOV A, B 78 Move o valor contido em B para o reg. A. 202B SUI 06H D6 06 Subtrai 06H, para obtermos 9, fazendo assim o ajuste decimal 202D MOV B, A 47 Move o conteúdo de A para o reg. B. 202E RET C9 Volta para o endereço 2020D e continua a execução do programa. 202F ANI 9FH E6 9F Faz com que FH ajuste-se para 9. 2031 RET C9 Volta para o endereço 2027H.
12
A Figura 3.3.1 mostra a simulação do programa no Abacus.
Figura 3.3.1 – Simulação do contador decimal decrescente no Abacus.
13
3.4 Visualizador de Programa
Finamente, fizemos um programa que mostra nos displays o endereço de
memória e seu conteúdo, de faixa de endereços 2000H à 201FH indefinidamente.
Define a Pilha
SP<=20B0H
Início
Define-se endereço
DE<=2000
Carrega A com o valor
especificado pelo
endereço de DE
Coloca DE na pilha
(PUSH DE)
Coloca A na pilha
(PUSH PSW)
Call UPDAD
(Display 16 bits)
Call UPDAD
(Display 16 bits)
Resgata a valor
de A da pilha
(POP PSW)
Call UPDDT
(Display 8 bits)
Call DELAY
Define tempo
DE<=0F00H
Resgata a valor
de A da pilha
(POP DE)
DE<= DE+1
A<= E
A-22H=0?A-22H=0?
Jump
14
Nesse programa, definimos o registrador par DE para fazer o controle
do endereço, e utilizamos a pilha para não perdermos os valores que deviam ser
amostrados nos displays. A partir daí, projetamos o programa com o cuidado de
observar a onde ele terminaria e aumentar esse valor em uma unidade, para que
assim, pudéssemos mostrar todo o programa. A Tabela 3.4.1 mostra o algoritmo
do programa com comentários.
Tabela 3.4.1 – Visualizador de programa.
Endereço MNEMONIC Op. Code Comentário 2000 LXI SP, 20B0H 31 B0 20 Define a posição inicial da pilha em 20B0H. 2003 LXI D, 2000H 11 00 20 Carrega o par DE com 2000H. 2006 LDAX D 1A Carrega o reg. A com o valor contido no endereço especificado
pelo para DE. 2007 PUSH D D5 Salva o valor do reg. par DE na pilha para não perde-lo, pois a
subrotina pode alterar valores de registradores. 2008 PUSH PSW F5 Salva o valor do reg. par AF na pilha para não perde-lo. 2009 CALL 0363H CD 63 03 Chama subrotina UPDAD (Display 16 bits). 200C POP PSW F1 Recupera o valor armazenado na pilha para A. 200D CALL 036EH CD 6E 03 Chama subrotina UPDDT (Display 8 bits). 2010 LXI D, 0F00H 11 00 0F Carrega o reg. par DE com 0F00 (será o tempo de delay). 2013 CALL 05F1H CD F1 05 Chama subrotina DELAY. 2016 POP D D1 Recupera o valor armazenado na pilha para DE. 2017 INX D 13 Incrementa o par DE. 2018 MOV A, E 7B Move o valor do reg. E para o Acumulador. 2019 ORA A B7 Faz CY=0. 201A CPI 22H FE 22 Compara o valor do Acumulador com 22H, que é o valor a partir
de quando não há mais programa.. 201C JZ 2003H CA 03 20 Se Z=1, pula para instrução presente no endereço 2003H. 201F JMP 2006H C3 06 20 Pula para instrução presente no endereço 2006H.
15
Figura 3.4.1 – Simulação do programa elaborado.
16
4. Conclusão e Comentários Finais
Nesse experimento pudemos ver o quanto as pilhas e subrotinas são
ferramentas essenciais na construção de um programa mais elaborado através do
Microprocessador 8085.
Pudemos notar que as subrotinas nos proporcionam códigos mais compactos,
já que se é necessário executar várias vezes uma mesma tarefa, podemos utilizar
apenas uma subrotina para isso. Além disso, as subrotinas nos proporcionam um
código mais ordenado e estruturado minimizando erros e facilitando o encontro de
erros, já que elas podem ser testadas uma a uma.
Quanto à pilha, vimos que esta é compartilhada tanto pelo programador
quanto pelo microprocessador. Ela é utilizada para armazenamento temporário na
execução de subrotinas e o programador pode também utilizá-la para armazenar e
retirar informação, através das funções PUSH E POP, mostrando assim ferramenta
indispensável na construção de qualquer programa mais complexo.
17
5. Referências
http://www2.ufersa.edu.br/portal/view/uploads/setores/147/arquivos/MM/7047
549-Cpu-Process-Adores.pdf
CÉSAR R. DA SILVA, Alexandre. ELE 1078 Microprocessadores I: notas de aula. Ilha
Solteira, Abril 2013. < http://www.lpssd.feis.unesp.br/course/view.php?id=13>