# Conjunto de Instruções e Modos de Endereçamento

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.

```
    ORG 00h         ; endereço inicial do programa

    MOV A, #1       ; move valor 1 para Acumulador
LOOP:
    MOV P1, A       ; move conteúdo do Acumulador para P1
    SETB P1.4       ; faz P1.4 = 1 (pull-up interno) - pino de entrada
    JNB P1.4, CH_PR ; testa se P1.4 é igual a zero. Se sim, vai para CH_PR
    RR A            ; se não, rotaciona os bits do Acumulador para direita
    SJMP LOOP       ; pula para LOOP
CH_PR:
    RL A            ; rotaciona os bits do Acumulador para esquerda
    SJMP LOOP       ; pula para LOOP

    END
```

### 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.

### 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](https://www.embarcados.com.br/wp-content/uploads/2016/10/IS_MOV.png)

| ![Instruções de Movimentação de Dados](https://www.embarcados.com.br/wp-content/uploads/2016/10/IS_MOVX.png) | ![Instruções de Movimentação de Dados](https://www.embarcados.com.br/wp-content/uploads/2016/10/IS_MOVC.png) |
| ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |

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 | <p>Soma A + DPTR obtendo um endereço de 16 bits na memória de programa. Carrega o acumulador com o<br>conteúdo desta memória</p> |
| 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   | <p>Move o conteúdo da memória N para a RAM endereçada<br>por Ri</p>                 |
| MOV  | @Ri,#N  | Move a constante N para a RAM endereçada por Ri                                     |
| MOVX | @DPTR,A | <p>Move Acumulador para a RAM externa endereçada por<br>DPTR (endereço 16 bits)</p> |

### Instruções Aritméticas

![Instruções aritméticas \[1\].](https://www.embarcados.com.br/wp-content/uploads/2016/10/IS_ARIT.png)

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 \[1\].](https://www.embarcados.com.br/wp-content/uploads/2016/10/IS_LOGIC.png)

Quando o destino é o acumulador:

| ANL | A, Rn | Operação “E” entre Rn e Acumulador                                 |
| --- | ----- | ------------------------------------------------------------------ |
| ANL | A,N   | Operação “E” entre o conteúdo da memória N e o Acumulador          |
| ANL | A,@Ri | Operação “E” entre RAM endereçada por Ri e Acumulador              |
| ANL | A,#N  | Operação “E” entre a constante N e Acumulador                      |
| ORL | A,Rn  | Operação “OU” entre Rn e Acumulador                                |
| ORL | A,N   | Operação “OU” entre memória N e Acumulador                         |
| ORL | A,@Ri | Operação “OU” entre RAM endereçada por Ri e Acumulador             |
| ORL | A,#N  | Operação “OU” entre constante N e Acumulador                       |
| XRL | A,Rn  | Operação “OU EXCLUSIVO” entre Rn e Acumulador                      |
| XRL | A,N   | Operação “OU EXCLUSIVO” entre o conteúdo da memória N e Acumulador |
| XRL | A,@Ri | Operação “OU EXCLUSIVO” entre RAM endereçada por Ri e Acumulador   |
| XRL | A,#N  | Operação “OU EXCLUSIVO” entre constante N e Acumulador             |

Quando o destino é um endereço direto:

| ANL | N,A  | Operação “E” entre Acumulador e memória N                             |
| --- | ---- | --------------------------------------------------------------------- |
| ANL | N,#N | Operação “E” entre constante N e memória N                            |
| ORL | N,A  | Operação “OU” entre Acumulador e conteúdo da memória N                |
| ORL | N,#N | Operação “OU” entre constante N e conteúdo da memória N               |
| XRL | N,A  | Operação “OU EXCLUSIVO” entre Acumulador e conteúdo da memória N      |
| XRL | N,#N | Operação “OU EXCLUSIVO” entre a constante N e o conteúdo da memória N |

Operação sobre o acumulador:

| RL   | A | Faz A = 0                                                 |
| ---- | - | --------------------------------------------------------- |
| CPL  | A | Inverte o estado dos bits do Acumulador                   |
| SWAP | A | Troca os nibbles do Acumulador                            |
| RL   | A | Rotação do Acumulador para esquerda                       |
| RLC  | A | Rotação do Acumulador para esquerda através do flag Carry |
| RR   | A | Rotação do Acumulador para direita                        |
| RRC  | A | Rotação do Acumulador para direita através do flag Carry  |

### Instruções Booleanas e de Desvio

![Instruções Booleanas e de Desvio](https://www.embarcados.com.br/wp-content/uploads/2016/10/IS_BOOL.png)

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

| LR   | bit   | Zera o bit endereçado                                         |
| ---- | ----- | ------------------------------------------------------------- |
| SETB | bit   | Seta o bit endereçado                                         |
| CPL  | bit   | Inverte o estado do bit endereçado                            |
| MOV  | bit,C | Move o flag Carry para o bit endereçado                       |
| JB   | bit,N | Desvia se o bit endereçado estiver setado                     |
| JNB  | bit,N | Desvia se o bit endereçado estiver zerado                     |
| JBC  | bit,N | Desvia se o bit endereçado estiver setado e depois zera o bit |

Operações sobre o flag de Carry:

| CLR  | C      | Zera o flag Carry                                                  |
| ---- | ------ | ------------------------------------------------------------------ |
| SETB | C      | Seta o flag Carry                                                  |
| CPL  | C      | Inverte 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 \[1\].](https://www.embarcados.com.br/wp-content/uploads/2016/10/IS_JMP1.png)

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

| ACALL | N  | Chama sub-rotina numa faixa de 2 Kbytes da atual posição            |
| ----- | -- | ------------------------------------------------------------------- |
| LCALL | NN | Chama sub-rotina em qualquer posição da memória de programa         |
| AJMP  | N  | Desvia para outro endereço numa faixa de 2 Kbytes da atual posição. |
| LJMP  | NN | Desvia para qualquer posição da memória                             |
| SJMP  | N  | Desvio 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.

![Desvio condicional \[1\].](https://www.embarcados.com.br/wp-content/uploads/2016/10/IS_JMP2.png)

| CJNE | A,N,N    | Compara e desvia se o Acumulador for diferente do conteúdo da memória N  |
| ---- | -------- | ------------------------------------------------------------------------ |
| CJNE | A,#N,N   | Compara e desvia se o Acumulador for diferente da constante N            |
| CJNE | Rn,#N,N  | Compara e desvia se o Rn for diferente da constante N                    |
| CJNE | @Ri,#N,N | Compara e desvia se a RAM endereçada por Ri for diferente da constante N |
| DJNZ | N,N      | Decrementa o conteúdo da memória N e desvia se for diferente de “zero”   |
| DJNZ | Rn, N    | Decrementa Rn e desvia se for diferente de “zero”                        |
| JZ   | N        | Desvia se o Acumulador for “zero”                                        |
| JNZ  | N        | Desvia 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.

```
       ORG 00h ; endereço inicial do programa
       
       MOV DPTR, #500h ; move valor 500h para DPTR
       MOV R0, #50 ; move valor 50 para R0
LOOP: 
       MOVX A, @DPTR ; move conteúdo apontado por DPTR para Acumulador
       CJNE A, #0FFH, DIFER ; compara conteúdo do Acumulador com 0FFH. Se for diferente, vai para DIFER
       MOV A, #0 ; caso contrário, move valor 0 para Acumulador
       MOVX @DPTR, A ; move conteúdo do Acumulador para endereço apontado por DPTR
DIFER: 
       INC DPTR ; incrementa DPTR
       DJNZ R0, LOOP ; decrementa R0 e compara com 0. Se for diferente, vai para LOOP
       SJMP $ ; espera (LOOP)
 
       END
```

* Exemplo de acesso a memória externa: Copia os dados de um vetor para outro.

```
       ORG 00h ; endereço inicial do programa
       
       MOV R0, #0 ; move valor 0 para R0 (endereço de origem)
       MOV R1, #50 ; move valor 50 para R1 (número de elementos)
       MOV DPTR, #50h ; move valor 50H para DPTR (endereço de destino)
LOOP:
       MOVX A, @R0 ; move para Acumulador o conteúdo do endereço apontado por R0
       MOVX @DPTR, A ; move conteúdo do Acumulador para endereço apontado por DPTR
       INC R0 ; incrementa R0 (endereço de origem)
       INC DPTR ; incrementa DPTR (endereço de destino)
       DJNZ R1, LOOP ; decrementa R1. Se for diferente de zero, vai para LOOP
       SJMP $ ; espera
END
```

##


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bit-by-bit.gitbook.io/embedded-systems/intel-msc-51/conjunto-de-instrucoes-e-modos-de-enderecamento.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
