MM – Microprocessadores e Microcontroladores – Roteiro da Experiência 5 EXPERIÊNCIA 5 – INSTRUÇÕES DE TRANSFERÊNCIA DE DADOS Parte I – Fundamentos Teóricos Nas experiências anteriores, foram utilizadas diversas instruções que executam uma transferência de dados, isto é, que copiam um dado “fonte” para um “destino”. A Tabela 1 descreve as instruções que fazem transferências de dados com acessos à RAM interna do 8051; na Tabela 2, são descritas as instruções de transferência de dados capazes de acessar a RAM externa; e as instruções que acessam a memória de programa (código) são descritas na Tabela 3. Nessas tabelas, <dado8>, <fonte8> e <destino8> são valores de 8 bits, que podem ser obtidos através de um dos modos de endereçamento assinalados por “X”; <valor16> é um valor imediato de 16 bits; e Ri representa o registrador R0 ou o registrador R1. instrução operação modos de endereçamento direto indireto registrador imediato X X X X X X X X X X X X ACC <fonte8> <destino8> ACC <destino8> <fonte8> DPTR <valor16> SP SP 1 PUSH <fonte8> X mem.int.[SP] <fonte8> <destino8> mem.int.[SP] X POP <destino8> SP SP 1 X X X XCH A, <dado8> ACC <dado8> XCHD A, @Ri X “nibble” inf.(ACC) “nibble” inf.(mem.int.[Ri]) Tabela 1 – Instruções transferência de dados do 8051, com acesso à RAM interna MOV A, <fonte8> MOV <destino8>, A MOV <destino8>, <fonte8> MOV DPTR, #<valor16> A instrução MOV copia o valor fonte no destino. O valor fonte não se altera. As instruções PUSH e POP fazem acesso à pilha, que é uma área da RAM interna, do tipo “LIFO” (“Last In, First Out”, ou seja, o último dado inserido será o primeiro a ser retirado), cujo apontador é o registrador SP. Note que esse registrador é incrementado antes da inserção de um dado, isto é, ele aponta o último dado já inserido, que é o primeiro a ser removido. A instrução XCH troca os valores do acumulador e de um outro dado, numa única instrução. Já a instrução XCHD troca os “nibbles” inferiores (4 bits menos significativos) do acumulador e da posição da RAM interna apontada pelo registrador R0 ou R1. modos de endereçamento direto indireto registrador imediato MOVX A, @Ri X ACC mem.ext.[Ri] X MOVX @Ri, A mem.ext.[Ri] ACC MOVX A, @DPTR X ACC mem.ext.[DPTR] X MOVX @DPTR, A mem.ext.[DPTR] ACC Tabela 2 – Instruções transferência de dados do 8051, com acesso à RAM externa instrução operação A instrução MOVX copia um valor da, ou para a, RAM externa, utilizando o acumulador para essa operação. O modo de endereçamento é sempre indireto, podendo ser utilizados como apontador os registradores R0, R1 ou DPTR. modo de endereçamento indexado X MOVC A, @A+DPTR ACC mem.prog.[DPTR+A] MOVC A, @A+PC X ACC mem.prog.[PC+A] Tabela 3 – Instruções transferência de dados do 8051, com acesso à memória de programa instrução operação A instrução MOVC copia um valor da memória de código para o acumulador (não é possível a escrita nesse memória!). O modo de endereçamento é sempre indexado, sendo o acumulador o registrador de índice, e o registrador DPTR ou PC o registrador de base. Parte II – Roteiro Experimental Carregue, na memória RAM externa, a partir do endereço 5000h, o programa da Tabela 4, digitando seu código de máquina. pass o 1 2 3 4 5 6 7 8 9 10 11 endereç o 5000 5003 5005 5007 5008 500B 500C 500E 500F 5010 5012 código de máquina 75 74 79 F7 90 F0 C0 C9 D7 D0 02 01 01 01 mnemônico e operandos comentários MOV SP, #2Fh SP 2Fh MOV A, #26h ACC 26h MOV R1, #18h R1 18h MOV @R1, A mem.int.[R1] ACC 38 MOV DPTR, #5038h DPTR 5038h MOVX @DPTR, A mem.ext.[DPTR] ACC PUSH 1 SP SP1; mem.int.[SP] mem.int.[1] (=R1) XCH A, R1 ACC R1 XCHD A, @R1 “nibble” inf.(ACC) “nibble” inf.(mem.int.[R1]) POP 1 mem.int.[1] (=R1) mem.int.[SP]; SP SP1 desvia para o MONITOR C0 LJMP MONITOR Tabela 4 – Programa com instruções de transferência de dados 81 2F 26 18 50 rótulo MM – Microprocessadores e Microcontroladores – Roteiro da Experiência 5 Execute o programa passo a passo, a partir do endereço 5000h (não se esqueça de, antes da execução, carregar o registrador PC com este valor). A cada instrução executada, leia o respectivo item, preenchendo suas lacunas. Preencha, também, os valores solicitados na Tabela 5. 1) O ponteiro da pilha (registrador ____) recebe o valor imediato 2Fh. Isso significa que a base da pilha, isto é, a posição do primeiro dado a ser empilhado, é a posição 2Fh+1=____h, que é a primeira posição da área livre da RAM interna, imediatamente acima da área dos bits endereçáveis. Se esta instrução não fosse executada, o registrador SP manteria seu valor recebido no “reset”, que é ____h, e, assim, a base da pilha seria a posição 08h, o que impediria o uso do banco 1 de registradores. 2) O acumulador recebe o valor imediato ____h. 3) O registrador ____ recebe o valor imediato 18h. 4) O registrador ____ endereça, indiretamente, a posição de endereço 18h da RAM interna, que corresponde ao registrador R0 do banco ___, fazendo com que este registrador receba o valor do acumulador (26h). 5) O registrador DPTR recebe o valor imediato ________h. 6) A posição de endereço 5038h da RAM _______________ (endereçada indiretamente pelo registrador DPTR) recebe o valor do acumulador (26h). 7) A instrução PUSH faz um “empilhamento”, isto é, coloca um dado numa área da RAM interna (a pilha), na posição apontada pelo registrador SP. Antes dessa transferência, porém, o ponteiro da pilha é incrementado, pois ele sempre aponta o “topo” da pilha, isto é, o último dado já inserido nela. O dado a ser empilhado é obtido, obrigatoriamente, por endereçamento direto; no caso, seu endereço é ___, o que significa que se trata do conteúdo da posição de endereço 01h da RAM interna, correspondente ao registrador ____ do banco ___. 8) O acumulador e o registrador ____ têm seus conteúdos trocados entre si. 9) Os “nibbles” menos significativos do ________________ e da posição da RAM interna apontada pelo registrador R1 (endereçamento indireto) são trocados entre si. 10) A instrução POP faz o inverso da instrução PUSH, ou seja, obtém o último dado empilhado, posicionado no “_______” da pilha (na posição apontada pelo registrador ____) e o copia, por endereçamento direto, para a posição de endereço 1 da RAM interna (registrador R1 do banco 0). Depois dessa transferência, o ponteiro da pilha é ____________________, apontando o novo “topo” da pilha (consumando a remoção do dado que, anteriormente, ocupava o “topo”). 11) Desvia para o programa Monitor. passo endereço da instrução 1 2 3 4 5 6 5000h 5003h 5005h 5007h 5008h 500Bh 7 8 9 10 mnemônico e operandos MOV SP, #2Fh MOV A, #26h MOV R1, #18h MOV @R1, A MOV DPTR, #5038h MOVX @DPTR, A PC (após a execução da instrução) valores obtidos (após a execução da instrução) h h h h h h SP = h ACC = h R1 = h mem.int.[18h] = h DPH = h DPL = h DPTR = mem.ext.[5038h] = h SP = h mem.int.[30h] = h 500Ch PUSH 1 h ACC = h R1 = h ACC = h R1 = h 500Eh h XCH A, R1 mem.int.[26h] = h ACC = h R1 = h 500Fh XCHD A, @R1 h mem.int.[26h] = h SP = h mem.int.[30h] = h 5010h h POP 1 ACC = h R1 = h Tabela 5 – Resultados da execução do programa com instruções de transferência de dados h EXPERIÊNCIA 5 – QUESTÕES ADICIONAIS 1) A instrução do passo 4 (MOV @R1, A) copia o valor do acumulador para a posição da RAM interna apontada por R1. Qual é a instrução que copia o valor do acumulador para a posição da memória externa apontada por R1? 2) Além do registrador R1, quais outros registradores podem ser utilizados como apontadores para endereçamento indireto? Quais áreas (RAM interna, RAM externa) podem ser apontadas por cada um desses registradores? (dica: consulte o roteiro da Experiência 2, Parte I, item a)2), e a questão adicional 6 dessa mesma experiência) 3) Suponha que o conteúdo do acumulador seja um valor X qualquer, e que o conteúdo do registrador R1 seja um valor Y. Sendo assim, qual o resultado final da execução da seguinte seqüência de instruções? PUSH 0E0H empilha acumulador PUSH 1 empilha R1 POP 0E0H desempilha acumulador POP 1 desempilha R1 4) Indique como obter o mesmo resultado da seqüência da questão anterior, através de uma única instrução. (dica: é uma das instruções desta experiência!) 5) Suponha que você escreveu uma seqüência de instruções (por exemplo, uma “sub-rotina”) que pode ser executada no meio de um programa qualquer. O problema é que essa seqüência precisa utilizar os registradores R0, R1 e R2, alterando seus valores, e, possivelmente, esses registradores serão utilizados, também, pelo programa que irá utilizar sua seqüência. É conveniente, portanto, preservar os valores de R0, R1 e R2, fazendo com que , ao final da execução de sua seqüência, eles sejam os mesmos que eram quando sua seqüência foi iniciada. Para garantir isso, insira 3 instruções no início da seqüência, e 3 instruções no final. (dica: utilize a pilha para “salvar” os valores originais dos registradores, e, no final, “restaure-os”). 6) desafio: Sabendo que o programa onde a sua seqüência será inserida utiliza, obrigatoriamente, apenas o banco 0 de registradores, proponha outra solução para o problema da questão anterior.