Sistemas Embarcados - Instruções

O fluxo do programa prossegue de maneira sequencial, de uma instrução para a próxima, a menos que uma instrução de transferência de controle seja executada. Os vários tipos de instrução de transferência de controle em linguagem assembly incluem saltos condicionais ou incondicionais e instruções de chamada.

Instruções de loop e salto

Looping no 8051

A repetição de uma sequência de instruções um certo número de vezes é chamada de loop. Uma instruçãoDJNZ reg, labelé usado para realizar uma operação de loop. Nesta instrução, um registro é decrementado em 1; se não for zero, o 8051 salta para o endereço de destino referido pela etiqueta.

O registro é carregado com o contador do número de repetições antes do início do loop. Nesta instrução, tanto o decréscimo dos registradores quanto a decisão de pular são combinados em uma única instrução. Os registros podem ser qualquer um de R0 – R7. O contador também pode ser um local de RAM.

Exemplo

Multiply 25 by 10 using the technique of repeated addition.

Solution- A multiplicação pode ser obtida adicionando o multiplicando repetidamente, tantas vezes quanto o multiplicador. Por exemplo,

25 * 10 = 250 (FAH)

25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 = 250

MOV A,#0             ;A = 0,clean ACC 
   MOV R2,#10           ; the multiplier is replaced in R2 
   Add A,#25            ;add the multiplicand to the ACC 
	
AGAIN:DJNZ R2, 
AGAIN:repeat  until R2 = 0 (10 times) 

   MOV R5 , A           ;save A in R5 ;R5 (FAH)

Drawback in 8051 - Ação de loop com a instrução DJNZ Reg labelestá limitado a apenas 256 iterações. Se um salto condicional não for executado, a instrução após o salto será executada.

Loop dentro de um Loop

Quando usamos um loop dentro de outro loop, ele é chamado de nested loop. Dois registros são usados ​​para manter a contagem quando a contagem máxima é limitada a 256. Portanto, usamos este método para repetir a ação mais de 256.

Example

Escreva um programa para -

  • Carregue o acumulador com o valor 55H.
  • Complemente o ACC 700 vezes.

Solution- Como 700 é maior que 255 (a capacidade máxima de qualquer registro), dois registros são usados ​​para manter a contagem. O código a seguir mostra como usar dois registradores, R2 e R3, para a contagem.

MOV A,#55H            ;A = 55H 
	
NEXT: MOV R3,#10         ;R3 the outer loop counter 
AGAIN:MOV R2,#70         ;R2 the inner loop counter 

   CPL A                 ;complement

Outros saltos condicionais

A tabela a seguir lista os saltos condicionais usados ​​em 8051 -

Instrução Açao
JZ Pule se A = 0
JNZ Pula se A ≠ 0
DJNZ Decrementar e saltar se registrar ≠ 0
CJNE A, dados Pule se dados A ≠
CJNE reg, #data Saltar se byte ≠ dados
JC Pule se CY = 1
JNC Pula se CY ≠ 1
JB Pula se bit = 1
JNB Pula se bit = 0
JBC Saltar se bit = 1 e limpar o bit
  • JZ (jump if A = 0)- Nesta instrução, o conteúdo do acumulador é verificado. Se for zero, o 8051 salta para o endereço de destino. A instrução JZ pode ser usada apenas para o acumulador, não se aplica a nenhum outro registrador.

  • JNZ (jump if A is not equal to 0)- Nesta instrução, o conteúdo do acumulador é verificado para ser diferente de zero. Se não for zero, o 8051 salta para o endereço de destino.

  • JNC (Jump if no carry, jumps if CY = 0)- O bit de flag Carry no registrador de flag (ou PSW) é usado para tomar a decisão de pular ou não "etiqueta JNC". A CPU olha para a bandeira de transporte para ver se ela está levantada (CY = 1). Se não for elevado, a CPU começa a buscar e executar instruções do endereço do rótulo. Se CY = 1, ele não saltará, mas executará a próxima instrução abaixo de JNC.

  • JC (Jump if carry, jumps if CY = 1) - Se CY = 1, ele salta para o endereço de destino.

  • JB (jump if bit is high)

  • JNB (jump if bit is low)

Note - Deve-se notar que todos os saltos condicionais são saltos curtos, ou seja, o endereço do destino deve estar entre –128 a +127 bytes do conteúdo do contador do programa.

Instruções de salto incondicional

Existem dois saltos incondicionais em 8051 -

  • LJMP (long jump)- LJMP é uma instrução de 3 bytes em que o primeiro byte representa o opcode, e o segundo e o terceiro bytes representam o endereço de 16 bits do local de destino. O endereço de destino de 2 bytes permite um salto para qualquer local da memória de 0000 a FFFFH.

  • SJMP (short jump)- É uma instrução de 2 bytes em que o primeiro byte é o opcode e o segundo byte é o endereço relativo do local de destino. O endereço relativo varia de 00H a FFH, que é dividido em saltos para frente e para trás; isto é, dentro de –128 a +127 bytes de memória em relação ao endereço do PC atual (contador do programa). No caso de salto para a frente, o endereço de destino pode estar dentro de um espaço de 127 bytes do PC atual. Em caso de salto para trás, o endereço de destino pode estar dentro de –128 bytes do PC atual.

Calculando o endereço de salto curto

Todos os saltos condicionais (JNC, JZ e DJNZ) são saltos curtos porque são instruções de 2 bytes. Nessas instruções, o primeiro byte representa opcode e o segundo byte representa o endereço relativo. O endereço de destino é sempre relativo ao valor do contador do programa. Para calcular o endereço de destino, o segundo byte é adicionado ao PC da instrução imediatamente abaixo do salto. Dê uma olhada no programa abaixo -

Line   PC    Op-code   Mnemonic   Operand 
1      0000               ORG       0000 
2      0000  7800         MOV       R0,#003  
3      0002  7455         MOV       A,#55H0 
4      0004  6003         JZ        NEXT 
5      0006  08           INC       R0 
6      0007  04   AGAIN:  INC       A 
7      0008  04           INC       A 
8      0009  2477 NEXT:   ADD       A, #77h 
9      000B  5005         JNC       OVER 
10     000D  E4           CLR       A
11     000E  F8           MOV       R0, A 
12     000F  F9           MOV       R1, A 
13     0010  FA          MOV       R2, A 
14     0011  FB           MOV       R3, A 
15     0012  2B   OVER:   ADD       A, R3 
16     0013  50F2         JNC       AGAIN 
17     0015  80FE HERE:   SJMP      HERE 
18     0017             END

Cálculo do endereço de destino de salto para trás

No caso de um salto para a frente, o valor de deslocamento é um número positivo entre 0 a 127 (00 a 7F em hexadecimal). No entanto, para um salto para trás, o deslocamento é um valor negativo de 0 a –128.

Instruções CALL

CALL é usado para chamar uma sub-rotina ou método. As sub-rotinas são usadas para realizar operações ou tarefas que precisam ser realizadas com frequência. Isso torna o programa mais estruturado e economiza espaço na memória. Existem duas instruções - LCALL e ACALL.

LCALL (chamada longa)

LCALL é uma instrução de 3 bytes em que o primeiro byte representa o opcode e o segundo e o terceiro bytes são usados ​​para fornecer o endereço da sub-rotina de destino. LCALL pode ser usado para chamar sub-rotinas que estão disponíveis no espaço de endereço de 64 K bytes do 8051.

Para fazer um retorno bem-sucedido ao ponto após a execução da sub-rotina chamada, a CPU salva o endereço da instrução imediatamente abaixo do LCALL na pilha. Assim, quando uma sub-rotina é chamada, o controle é transferido para essa sub-rotina e o processador salva o PC (contador de programa) na pilha e começa a buscar instruções do novo local. A instrução RET (retorno) transfere o controle de volta para o chamador após o término da execução da sub-rotina. Cada sub-rotina usa RET como a última instrução.

ACALL (Chamada Absoluta)

ACALL é uma instrução de 2 bytes, em contraste com LCALL que tem 3 bytes. O endereço de destino da sub-rotina deve estar dentro de 2K bytes porque apenas 11 bits dos 2 bytes são usados ​​para o endereço. A diferença entre ACALL e LCALL é que o endereço de destino para LCALL pode estar em qualquer lugar dentro do espaço de endereço de 64K bytes do 8051, enquanto o endereço de destino de CALL está dentro de um intervalo de 2K bytes.