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.