Conjunto de Instruções do Intel 8051

Instruções do Intel 8051 Mapa de Memória no Intel 8051 8051 Arquitetura Intel 8051

Este artigo é continuação da série Intel 8051 e tem como principal objetivo apresentar o conjunto de instruções do Intel 8051. De acordo com Patterson e Hennessy, a linguagem que um computador entende é chamada de instruções e seu vocabulário é denominado conjunto de instruções. Basicamente, as instruções indicam as operações que são executadas e os operandos utilizados. Além disso, as instruções são codificadas como números binários e são armazenadas na memória principal. Assim, o formato armazenado na memória é chamado de linguagem de máquina, já sua representação simbólica é chamada de linguagem de montagem ou Assembly.

Antes de Escrever o Programa

Um programa é essencialmente uma série de instruções gravadas em memória. O desenvolvimento dos programas em Assembly consiste na declaração dessas instruções e da utilização de um montador para convertê-las para linguagem de máquina. Além disso, o programa em Assembly contém diretivas que especificam parâmetros ao montador (Assembler), isto é, são comandos passados para o montador e que não são convertidos em linguagem de máquina.

Geralmente, uma linha de um programa em Assembly possui:

  • Label: Pode ser utilizado para nomear a linha do código de contém a instrução indicada.
  • Mnemônico: É o nome da instrução.
  • Operandos: São informações utilizadas na execução de uma instrução. Cabe ressaltar que algumas instruções não possuem operandos.
  • Comentários: São opcionais. Devem ser iniciados com ‘;’ e descrever a operação realizada na respectiva linha.

Nesse exemplo, a diretiva ORG <número> determina a posição da memória em que a próxima instrução será colocada na memória de programa. Já a diretiva END indica o fim do programa.

Modos de Endereçamento

  • Direto:
    • O endereço do operando é determinado pela própria instrução (endereço de 8 bits).
    • Neste caso, apenas a RAM interna e os registradores especiais podem ser acessados.
  • Indireto:
    • O endereço do operando é determinado por um registrador.
    • Um endereço de 8 bits pode ser determinado pelos registradores R0~R1 do banco de registradores atual, ou pelo Stack Pointer.
    • Endereços de 16 bits só podem ser especificados pelo registrador DPTR.
  • Imediato:
    • O operando é a constante.
  • Registrador:
    • Os registradores R0~R7 do banco atual são acessados pela instrução.
  • Registrador Específico:
    • A operação da instrução é realizada em um registrador específico.
    • Neste caso, não é necessário indicar um endereço.
  • Indexado:
    • Somente a memória de programa pode ser acessada.
    • Apenas operações de leitura são possíveis.
    • Utilizado em instruções de salto e look-up table.

No último modo, os registradores PC e DPTR podem ser usados para armazenar um endereço base. Já o acumulador é utilizado para determinar o offset.

Conjunto de Instruções

  • Símbolos utilizados:
    • C: Flag de carry;
    • A: Acumulador;
    • PC: Contador de Programa;
    • DPTR: Ponteiro;
    • N: Endereço de 8 bits;
    • NN: Endereço de 16 bits;
    • #N: Constante de 8 bits;
    • Rn: Registrador Rn (R0~R7) do banco atual de registradores;
    • @Ri: Endereço é determinado pelo registrador Ri (R0 ou R1);
    • H: indica que o valor está na base hexadecimal;
    • B: indica que o valor está na base binária;
  • Instruções de Movimentação de Dados
Instruções de Movimentação de Dados
Instruções de Movimentação de Dados
Instruções de Movimentação de Dados

De modo geral, quando o destino é o acumulador:

MOV

A,Rn

Move o registro Rn para o Acumulador

MOV

A,N

Move o conteúdo da memória N para o Acumulador

MOV

A,@Ri

Move o conteúdo da RAM endereçada por Ri para o Acumulador

MOV

A,#N

Move a constante N para o Acumulador

MOVC

A,@A+DPTR

Soma A + DPTR obtendo um endereço de 16 bits na memória de programa. Carrega o acumulador com o
conteúdo desta memória

MOVC

A,@A+PC

Idem ao anterior, mas soma A + PC

MOVX

A,@Ri

Move o conteúdo da RAM endereçada por Ri para o Acumulador

MOVX

A,@DPTR

Move RAM externa endereçada por DPTR (endereço 16 bits) para o Acumulador

XCH

A,Rn

Troca entre si o conteúdo do Acumulador e do Registro Rn

XCH

A,N

Troca entre si o conteúdo da memória N com Acumulador

XCH

A,@Ri

 Troca entre si a RAM endereçada por Ri com Acumulador

XCHD

A,@Ri

Troca entre si o nibble menos significativo do Acumulador e da RAM endereçada por Ri

Quando o destino é um registrador:

MOV

Rn,A

Move o Acumulador para o registro Rn

MOV

Rn,N

Move o conteúdo da memória N para o registro Rn

MOV

Rn,#N

Move a constante N para o registro Rn

MOV

DPTR,#NN

Move constante NN para o DPTR

Quando o destino é um endereço direto:

MOV

N,A

Move o Acumulador para a memória N

MOV

N,Rn

Move o registro Rn para a memória N

MOV

N1,N2

Move o conteúdo da memória N2 para a memória N1

MOV

N,@Ri

Move RAM endereçada por Ri para a memória N

MOV

N,#N

Move a constante N para o conteúdo da memória N

PUSH

N

Incrementa o SP e então coloca a memória no Stack

POP

N

Retira dado do Stack e coloca na memória, depois decrementa SP

Quando o destino é um endereço indireto:

MOV

@Ri,A

Move o Acumulador para a RAM endereçada por Ri

MOV

@Ri,N

Move o conteúdo da memória N para a RAM endereçada
por Ri

MOV

@Ri,#N

Move a constante N para a RAM endereçada por Ri

MOVX

@DPTR,A

Move Acumulador para a RAM externa endereçada por
DPTR (endereço 16 bits)
  • Instruções Aritméticas
is_arit

Quando o destino é o acumulador:

ADD

A,Rn

Soma Rn ao Acumulador

ADD

A,N

Soma o conteúdo da posição de memória N ao Acumulador

ADD

A,@Ri

Soma o conteúdo da RAM endereçada por Ri ao Acumulador

ADD

A,#N

Soma a constante N ao Acumulador

ADDC

A,Rn

Soma Rn e o flag Carrry ao Acumulador

ADDC

A,N

Soma o conteúdo da posição de memória N e o flag Carry ao Acumulador

ADDC

A,@Ri

Soma o conteúdo da RAM endereçada por Ri e o flag Carry ao Acumulador

ADDC

A,#N

Soma a constante N e flag Carry ao Acumulador

SUBB

A,Rn

Subtrai Rn e o flag Carry do Acumulador

SUBB

A,N

Subtrai o conteúdo da posição de memória N e o flag Carry do Acumulador

SUBB

A,@Ri

Subtrai o conteúdo da RAM endereçada por Ri e o flag Carry do Acumulador

SUBB

A,#N

Subtrai a constante N e o flag Carry do Acumulador

INC

A

Soma 1 ao Acumulador

DEC

A

Subtrai 1 do Acumulador

DA

A

Ajuste decimal do Acumulador

DIV

AB

Divide A e B, resultado: A inteiro e B resto

MUL

AB

Multiplica A e B, resultado: BA

Cabe ressaltar que nas operações de adição, subtração e incremento o flag de carry e de overflow são alterados. As operações de multiplicação e divisão zeram o flag de carry, e no caso da multiplicação, a flag de overflow é modificada. Além disso, a instrução de ajuste decimal também modifica a flag de carry.

Quando o destino é um registrador:

INC

Rn

Soma 1 ao Rn

DEC

Rn

Subtrai 1 de Rn

  • Instruções Lógicas
Instruções Lógicas

Quando o destino é o acumulador:

ANLA, RnOperação “E” entre Rn e Acumulador
ANLA,NOperação “E” entre o conteúdo da memória N e o Acumulador
ANLA,@RiOperação “E” entre RAM endereçada por Ri e Acumulador
ANLA,#NOperação “E” entre a constante N e Acumulador
ORLA,RnOperação “OU” entre Rn e Acumulador
ORLA,NOperação “OU” entre memória N e Acumulador
ORLA,@RiOperação “OU” entre RAM endereçada por Ri e Acumulador
ORLA,#NOperação “OU” entre constante N e Acumulador
XRLA,RnOperação “OU EXCLUSIVO” entre Rn e Acumulador
XRLA,NOperação “OU EXCLUSIVO” entre o conteúdo da memória N e Acumulador
XRLA,@RiOperação “OU EXCLUSIVO” entre RAM endereçada por Ri e Acumulador
XRLA,#NOperação “OU EXCLUSIVO” entre constante N e Acumulador

Quando o destino é um endereço direto:

ANLN,AOperação “E” entre Acumulador e memória N
ANLN,#NOperação “E” entre constante N e memória N
ORLN,AOperação “OU” entre Acumulador e conteúdo da memória N
ORLN,#NOperação “OU” entre constante N e conteúdo da memória N
XRLN,AOperação “OU EXCLUSIVO” entre Acumulador e conteúdo da memória N
XRLN,#NOperação “OU EXCLUSIVO” entre a constante N e o conteúdo da memória N

Operação sobre o acumulador:

RLAFaz A = 0
CPLAInverte o estado dos bits do Acumulador
SWAPATroca os nibbles do Acumulador
RLARotação do Acumulador para esquerda
RLCARotação do Acumulador para esquerda através do flag Carry
RRARotação do Acumulador para direita
RRCARotação do Acumulador para direita através do flag Carry
  • Instruções Booleanas e de Desvio
Instruções Booleanas e de Desvio

Operações utilizando o endereçamento de bits:

LRbitZera o bit endereçado
SETBbitSeta o bit endereçado
CPLbitInverte o estado do bit endereçado
MOVbit,CMove o flag Carry para o bit endereçado
JBbit,NDesvia se o bit endereçado estiver setado
JNBbit,NDesvia se o bit endereçado estiver zerado
JBCbit,NDesvia se o bit endereçado estiver setado e depois zera o bit

Operações sobre o flag de Carry:

CLRCZera o flag Carry
SETBCSeta o flag Carry
CPLCInverte o estado do flag Carry

MOV

C,bit

Move o bit endereçado para o flag Carry

ANL

C,bit

Operação “E” entre o bit endereçado e o flag Carry

ANL

C,/bit

Operação “E” entre o complemento do bit endereçado e o flag Carry

ORL

C,bit

Operação “OU” entre o bit endereçado e o flag Carry

ORL

C,/bit

Operação “OU” entre o complemento do bit endereçado e o flag Carry

JC

N

Desvia se o flag Carry estiver setado

JNC

N

Desvia se o flag Carry estiver zerado

  • Instruções de Salto

Instruções de salto incondicional são bastante simples. Basicamente, um endereço alvo é utilizado para alterar o fluxo de execução, isto é, o contador de programa. Na figura são mostradas as instruções capazes de alterar o fluxo de execução do programa, com exceção da instrução NOP, que não realiza nenhuma operação.

Instruções de Salto

As instruções JMP e CALL possuem as seguintes variações:

ACALLNChama sub-rotina numa faixa de 2 Kbytes da atual posição
LCALLNNChama sub-rotina em qualquer posição da memória de programa
AJMPNDesvia para outro endereço numa faixa de 2 Kbytes da atual posição.
LJMPNNDesvia para qualquer posição da memória
SJMPNDesvio curto relativo

Outras duas instruções que alteram o valor do contador de programa são as de retorno de sub-rotina e retorno de interrupção.

RET Retorna da sub-rotina
RETI Retorna da interrupção

O desvio também pode ser tomado com base no resultado de uma comparação. Nesse caso, o desvio é dito condicional.

is_jmp2
CJNEA,N,NCompara e desvia se o Acumulador for diferente do conteúdo da memória N
CJNEA,#N,NCompara e desvia se o Acumulador for diferente da constante N
CJNERn,#N,NCompara e desvia se o Rn for diferente da constante N
CJNE@Ri,#N,NCompara e desvia se a RAM endereçada por Ri for diferente da constante N
DJNZN,NDecrementa o conteúdo da memória N e desvia se for diferente de “zero”
DJNZRn, NDecrementa Rn e desvia se for diferente de “zero”
JZNDesvia se o Acumulador for “zero”
JNZNDesvia se o Acumulador “não for zero”

Cabe ressaltar que as instruções CJNE modificam a flag de carry.

  • Exemplo de acesso a memória externa: Zera os elementos de um vetor que são iguais a FFH.
  • Exemplo de acesso a memória externa: Copia os dados de um vetor para outro.

Referências

  • [1] MCS® 51 Microcontroller Family User’s Manual.
  • [2] HARRIS. D. M; HARRIS. S. L. Digital Design and Computer Architecture. Elsevier. 2012.
  • [3] PATTERSON. D. A.; HENNESSY. J. L. Computer Organization and Design: The Hardware/Software Interface 5th Edition. Morgan Kaufmann-Elsevier. 2013.
  • Imagem Destacada.

Outros artigos da série

<< Mapa de Memória no Intel 8051Interrupções e Subrotinas no Intel 8051 >>
Veja + conteúdo

Fascinado por computação, especialmente na interface entre hardware e software, me engajei na área de sistemas embarcados. Atuo com desenvolvimento de sistemas embarcados e sou docente da Faculdade de Engenharia de Sorocaba.

Para mais informações: https://about.me/fdelunogarcia

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Comentários:
Notificações
Notificar
guest
5 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Souza
Souza
05/11/2016 14:14

Só uma dúvida nessa parte Fernando Deluno Garcia:

“SUB A,#N Subtrai a constante N e o flag Carry do Acumulador”

Esse SUB não deveria ser SUBB? Já que os demais acima seguiram essa lógica.
E, por curiosidade, por que não tem SUB para as mesmas que tem SUBB?

Ainda estou apanhando um pouco, mas está bem prazeroso.

Fernando Deluno Garcia
Fernando Deluno Garcia
Reply to  Souza
05/11/2016 15:48

Olá, Souza.

Obrigado pela correção. Faltava um B!

Na verdade, SUBB significa subtract with borrow. Nesse caso, borrow é a flag de Carry.

Souza
Souza
Reply to  Fernando Deluno Garcia
05/11/2016 17:12

Obrigado pelo pronto atendimento. Quero ficar bom nesse negócio. É um mundo repleto de possibilidades. E o meu cérebro é muito inquieto. Na hora do descanso não posso simplesmente “desligar” o cérebro. Tenho que mantê-lo em atividade o tempo todo (ao menos enquanto estou acordado e, alem de tudo, durmo muito pouco). Pode parecer prejudicial (talvez seja um pouco), mas já tenho mais de 50 anos se sempre foi assim e me sinto muito bem sendo assim. Quando tentei “aquietar” a mente foi pior. Aquela coisa de família propensa a depressão é complicado. Mas, do jeito que faço tem dado… Leia mais »

Haroldo Amaral
Haroldo Amaral
28/10/2016 15:44

Parabéns pela série Fernando. Muito legal rever algo que aprendi lá no técnico (e me lembrava vagamente).

Vou aproveitar os artigos, pegar o protoboard e brincar com assembly de 8051 novamente.

Fernando Deluno Garcia
Fernando Deluno Garcia
Reply to  Haroldo Amaral
31/10/2016 06:52

Muito obrigado, Haroldo!

É sempre bom voltar às origens ahah.

Talvez você goste:

Séries



Outros da Série

Menu