Sistemas integrados: instrucciones

El flujo del programa procede de manera secuencial, de una instrucción a la siguiente, a menos que se ejecute una instrucción de transferencia de control. Los diversos tipos de instrucciones de transferencia de control en lenguaje ensamblador incluyen saltos condicionales o incondicionales e instrucciones de llamada.

Instrucciones de bucle y salto

Bucle en el 8051

Repetir una secuencia de instrucciones un cierto número de veces se denomina loop. Una instrucciónDJNZ reg, labelse utiliza para realizar una operación de bucle. En esta instrucción, un registro se reduce en 1; si no es cero, 8051 salta a la dirección de destino a la que hace referencia la etiqueta.

El registro se carga con el contador del número de repeticiones antes del inicio del ciclo. En esta instrucción, tanto el decremento de registros como la decisión de saltar se combinan en una sola instrucción. Los registros pueden ser cualquiera de R0 – R7. El contador también puede ser una ubicación de RAM.

Ejemplo

Multiply 25 by 10 using the technique of repeated addition.

Solution- La multiplicación se puede lograr sumando el multiplicando repetidamente, tantas veces como el multiplicador. Por ejemplo,

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 - Acción de bucle con la instrucción DJNZ Reg labelestá limitado a 256 iteraciones únicamente. Si no se realiza un salto condicional, se ejecuta la instrucción que sigue al salto.

Bucle dentro de un bucle

Cuando usamos un bucle dentro de otro bucle, se llama nested loop. Se usan dos registros para mantener el conteo cuando el conteo máximo está limitado a 256. Por lo tanto, usamos este método para repetir la acción más de 256 veces.

Example

Escribe un programa para -

  • Cargue el acumulador con el valor 55H.
  • Complementa el ACC 700 veces.

Solution- Dado que 700 es mayor que 255 (la capacidad máxima de cualquier registro), se utilizan dos registros para mantener la cuenta. El siguiente código muestra cómo utilizar dos registros, R2 y R3, para el recuento.

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

Otros saltos condicionales

La siguiente tabla enumera los saltos condicionales utilizados en 8051 -

Instrucción Acción
JZ Saltar si A = 0
JNZ Saltar si A ≠ 0
DJNZ Decrementar y saltar si el registro ≠ 0
CJNE A, datos Saltar si A ≠ datos
CJNE reg, #data Saltar si byte ≠ datos
JC Saltar si CY = 1
JNC Saltar si CY ≠ 1
JB Saltar si bit = 1
JNB Saltar si bit = 0
JBC Saltar si bit = 1 y borrar bit
  • JZ (jump if A = 0)- En esta instrucción, se verifica el contenido del acumulador. Si es cero, el 8051 salta a la dirección de destino. La instrucción JZ se puede usar solo para el acumulador, no se aplica a ningún otro registro.

  • JNZ (jump if A is not equal to 0)- En esta instrucción, se comprueba que el contenido del acumulador sea distinto de cero. Si no es cero, el 8051 salta a la dirección de destino.

  • JNC (Jump if no carry, jumps if CY = 0)- El bit de bandera de acarreo en el registro de bandera (o PSW) se utiliza para tomar la decisión de saltar o no la "etiqueta JNC". La CPU mira la bandera de acarreo para ver si está levantada (CY = 1). Si no se genera, la CPU comienza a buscar y ejecutar instrucciones desde la dirección de la etiqueta. Si CY = 1, no saltará pero ejecutará la siguiente instrucción debajo de JNC.

  • JC (Jump if carry, jumps if CY = 1) - Si CY = 1, salta a la dirección de destino.

  • JB (jump if bit is high)

  • JNB (jump if bit is low)

Note - Debe tenerse en cuenta que todos los saltos condicionales son saltos cortos, es decir, la dirección del objetivo debe estar entre –128 y +127 bytes del contenido del contador del programa.

Instrucciones de salto incondicional

Hay dos saltos incondicionales en 8051 -

  • LJMP (long jump)- LJMP es una instrucción de 3 bytes en la que el primer byte representa el código de operación y el segundo y tercer bytes representan la dirección de 16 bits de la ubicación de destino. La dirección de destino de 2 bytes permite un salto a cualquier ubicación de memoria desde 0000 a FFFFH.

  • SJMP (short jump)- Es una instrucción de 2 bytes donde el primer byte es el código de operación y el segundo byte es la dirección relativa de la ubicación de destino. La dirección relativa varía de 00H a FFH, que se divide en saltos hacia adelante y hacia atrás; es decir, entre –128 y +127 bytes de memoria en relación con la dirección de la PC actual (contador de programa). En caso de salto hacia adelante, la dirección de destino puede estar dentro de un espacio de 127 bytes desde la PC actual. En caso de salto hacia atrás, la dirección de destino puede estar dentro de los –128 bytes de la PC actual.

Cálculo de la dirección de salto corto

Todos los saltos condicionales (JNC, JZ y DJNZ) son saltos cortos porque son instrucciones de 2 bytes. En estas instrucciones, el primer byte representa el código de operación y el segundo byte representa la dirección relativa. La dirección de destino siempre es relativa al valor del contador del programa. Para calcular la dirección de destino, el segundo byte se agrega a la PC de la instrucción inmediatamente debajo del salto. Eche un vistazo al programa que se muestra a continuación:

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 de dirección de destino de salto hacia atrás

En caso de un salto hacia adelante, el valor de desplazamiento es un número positivo entre 0 y 127 (00 a 7F en hexadecimal). Sin embargo, para un salto hacia atrás, el desplazamiento es un valor negativo de 0 a –128.

Instrucciones de LLAMADA

CALL se usa para llamar a una subrutina o método. Las subrutinas se utilizan para realizar operaciones o tareas que deben realizarse con frecuencia. Esto hace que un programa sea más estructurado y ahorra espacio en la memoria. Hay dos instrucciones: LCALL y ACALL.

LCALL (llamada larga)

LCALL es una instrucción de 3 bytes donde el primer byte representa el código de operación y el segundo y tercer bytes se utilizan para proporcionar la dirección de la subrutina de destino. LCALL se puede utilizar para llamar subrutinas que están disponibles dentro del espacio de direcciones de 64K bytes del 8051.

Para hacer un regreso exitoso al punto después de la ejecución de la subrutina llamada, la CPU guarda la dirección de la instrucción inmediatamente debajo de LCALL en la pila. Por lo tanto, cuando se llama a una subrutina, el control se transfiere a esa subrutina y el procesador guarda la PC (contador de programa) en la pila y comienza a buscar instrucciones desde la nueva ubicación. La instrucción RET (retorno) transfiere el control de nuevo al llamador después de finalizar la ejecución de la subrutina. Cada subrutina usa RET como última instrucción.

ACALL (Absolute Call)

ACALL es una instrucción de 2 bytes, en contraste con LCALL, que tiene 3 bytes. La dirección de destino de la subrutina debe estar dentro de los 2K bytes porque solo se usan 11 bits de los 2 bytes para la dirección. La diferencia entre ACALL y LCALL es que la dirección de destino para LCALL puede estar en cualquier lugar dentro del espacio de direcciones de 64K bytes del 8051, mientras que la dirección de destino de CALL está dentro de un rango de 2K bytes.