Traducciones de esta página:

Herramientas de usuario

Herramientas del sitio


es:capítulo_2_-_ejecución_condicional_i

CAPÍTULO 2

EJECUCIÓN CONDICIONAL (I)

Cuando se habla de microprocesadores, la ejecución condicional se refiere a la posibilidad de ejecutar uno u otro programa (o una u otra parte de un programa) en función de que se cumpla o no una cierta condición. Dado que los microprocesadores se basan en la lógica binaria (SI/NO 0/1), esto nos facilita representar las condiciones mediante un único bit para cada una, y el criterio general es usar el 0 si la condición no se cumple (es falsa) y usar el 1 si sí se cumple (es cierta). Esta forma de representación es lo que se conoce como “lógica positiva”, y contra puesta a ella está la llamada “logica negativa”, en la que el 0 representa que la condición es cierta y el 1 representa que la condición es falsa.

En el capítulo cero, al tratar la estructura de registros del microprocesador 8080 de Intel, ya vimos cómo se las arregla el microprocesador para representar las condiciones. Si volvéis la vista atrás hacia el citado capítulo, veréis que existe un registro de flags (banderas en inglés) o también llamado registro de estado, precisamente porque sus bits denotan el estado de una condición. Las condiciones que se pueden verificar son cinco:

  • 1.ª Que un número es negativo o no (flag de signo).
  • 2.ª Que un número es cero o no (flag de cero).
  • 3.ª Que al convertir un número a formato BCD el resultado es un número BCD correcto o no (flag de acarreo auxiliar).
  • 4.ª Que el número de bits 1 en un número es par o impar (flag de paridad).
  • 5.ª Que al realizar una suma o resta con números se ha producido un acarreo (flag de acarreo).

De todos estos flags o indicadores de estado, uno de ellos, el de acarreo, podemos manipularlo directamente mediante instrucciones preparadas para ellos (STC=Set Carry Flag; Activa flag de acarrero, y CMC=Complement Carry Flag: complementa o invierte el flag de acarreo). El estado de los otros cuatro flag depende del resultado de ciertas operaciones aritméticas y lógicas.

Sin embargo, el tema de este capítulo no es las instrucciones que alteran al estado de los flags (que iremos viendo poco a poco más adelante, pues son muchas y cada una actúa de distinta manera), sino las que se sirven del estado de dichos flags para poder ejecutar una acción de entre dos.

Básicamente podemos agrupar estas instrucciones en tres grupos: de salto, de llamada y de retorno. En el capítulo 1 vimos un caso concreto de dos de ellas (CALL, de las de llamada, y RET, de las de retorno), que poseen la peculiaridad de ser incondicionales, es decir, la llamada o el retorno se ejecutan siempre, y no dependen del estado de ningún flag. Análogamente, en el grupo de las instrucciones de salto existe una instrucción (JMP) cuya ejecución es también incondicional.

Las incondicionales

JMP dirección —dirección es un número de 16 bits (entre 0 y 65535), o si está usando un ensamblador, una etiqueta de dirección. Su función es bien sencilla: pasa el control del programa a la dirección indicada, en lugar de continuar con la instrucción siguiente a JMP. Más o menos equivale al GOTO del BASIC.

CALL dirección -ésta la vimos en el capítulo 1, y es similar a JMP, pero con la particularidad de que, una vez que se efectúa el salto, cuando se encuentre una instrucción RET, se vuelve a la instrucción siguiente a CALL. Más o menos equivale al GOSUB del BASIC.

RET —ver CALL y ver el capítulo 1. Más o menos equivale al RETURN del BASIC.

Estas son las instrucciones básicas de las cuales se derivan las instrucciones de ejecución condicional. La única diferencia es que en éstas, si se cumple la condición, se efectúa la acción (salto, llamada subrutina o retorno), y si no se cumple la condición se ignora la acción y se pasa a la siguiente instrucción. Sin embargo, hay otra instrucción de salto incondicional especial, que no tiene equivalente en el grupo de llamadas ni en el de retornos, que es la instrucción PCHL. Su nombre significa que se pasa al registro PC el contenido del registro HL, y el resultado de ejecutarla es, evidentemente, un salto a la dirección que se encuentre en el registro. De este modo, este listado:

JMP destino

y este otro:

LXI H,destino
PCHL

ejecutan la misma acción, que es saltar a la dirección indicada por la etiqueta “destino”.

De momento puede parecer absurda esta instrucción, ya que el ejemplo que os he puesto no es el más adecuado. Sin embargo, es una instrucción muy útil, ya que en muchos programas es necesario que el propio programa calcule la dirección a la que tiene que saltar, es decir, el programador no la sabe de antemano, por lo que no puede usar la instrucción JMP. En estos casos el programa calcula la dirección a la que quiere saltar, la introduce en el registro HL y ejecuta la instrucción PCHL para saltar. Al final del capítulo veremos un ejemplo.

Saltos condicionales

JNZ dirección -JNZ es abreviatura de Jump if Not Zero (salta si no es cero)—, y como su nombre indica el salto a la “dirección” se ejecuta si el flag de cero es 0 (indicando que en la última operación el resultado no fue cero).

JZ dirección -JZ es abreviatura de Jump if Zero (salta si es cero)-, y es la contraria a la anterior, es decir, el salto a la “dirección” se ejecuta si el flag de cero es 1 (indicando que en la última operación el resultado fue cero).

JNC dirección —JNC es abreviatura de Jump if Not Carry (salta sí no hubo acarreo)—, y el salto a “dirección” se ejecuta si el flag de acarreo está a cero.

JC dirección —JC es abreviatura de Jump if Carry (salta si hubo acarreo)—, y el salto a “dirección” se ejecuta si el flag de acarreo está a uno.

JPO dirección —JPO es abreviatura de Jump if Parity Odd (salta si la paridad es impar, esto es, el número de bits contenidos en el byte resultado de la última operación era impar)-. El salto a “dirección” se ejecuta si el flag de paridad está a cero.

JPE dirección —JPE es abreviatura de Jump if Parity Even (salta si la paridad es par, esto es, el número de bits contenidos en el byte resultado de la última operación era par)—. El salto a “dirección” se ejecuta si el flag de paridad está a uno.

Nota: Al hablar de la última operación no nos referimos a la situada antes de la instrucción de salto, sino a la última instrucción ejecutada que además modifique dicho flag.

JP dirección —JP es la abreviatura de Jump if Plus (salta sí es positivo)-, y el salto a “dirección” se ejecuta si el resultado de la última operación fue un número positivo, en cuyo caso el flag de signo estará a cero.

JM dirección -JM es la abreviatura de Jump if Minus (salta si es negativo)—, y el salto a “dirección” se ejecuta si el resultado de la ultima operación fue un número negativo, en cuyo caso el flag de signo estará a uno.

                                   - INSTRUCCIONES DE SALTO DEL 8080 -

   INSTRUCCIONES DE SALTO INCONDICIONALES                                          JMP dirección
   --------------------------------------                                          PCHL

==================================================================================================================
                                                                          
   INSTRUCCIONES DE SALTO CONDICIONALES              JNZ dirección                 JPO dirección
   ------------------------------------              JZ dirección                  JPE dirección
                                                     
                                                     JNC dirección                 JP dirección
                                                     JC dirección                  JM dirección
 

Un pequeño ejemplo

El listado 1 ilustra el uso de la instrucción PCHL junto con una tabla. Básicamente lo que se hace es, primero, pedir al usuario que elija una opción de entre tres. A continuación se toma, de una tabla de direcciones, la dirección correspondiente al subprograma encargado de ejecutar la opción elegida y salta a ella mediante PCHL. Como esto es sólo un ejemplo, lo único que hacen los subprogramas es imprimir un texto indicando qué opción hemos elegido.

        ORG     0100H

CR      EQU     13              ;CODIGO DEL RETORNO DE CARRO
LF      EQU     10              ;CODIGO DEL AVANCE DE LINEA
BDOS    EQU     0005H           ;PUNTO DE ENTRADA AL BDOS
PRINT   EQU     9               ;FUNCION 9: IMPRIME CADENA DE TEXTO
LEECAR  EQU     1               ;FUNCION 1: LEE UN CARACTER DEL TECLADO
PRCAR   EQU     2               ;FUNCION 2: IMPRIME UN CARACTER

COMIEN: LXI     D,PROMPT        ;DIRECCION DEL TEXTO PIDIENDO UNA OPCION
        MVI     C,PRINT
        CALL    BDOS
        MVI     C,LEECAR
        CALL    BDOS            ;A=CODIGO ASCII DEL CARACTER PULSADO
        PUSH    PSW             ;SALVA EL CARACTER EN EL STACK
        SUI     31H             ;LE RESTA EL VALOR DEL CODIGO ASCII DEL '1'
                                ;PARA CONVERTIRLO EN UN NUMERO DEL 0 AL 2
        ADD     A               ;LO MULTIPLICA POR 2, <A+A=2*A) ASI:
                                ;SI PULSAMOS 1, A VALDRA 0
                                ;SI PULSAMOS 2, A VALDRA 2
                                ;SI PULSAMOS 3, A VALDRA 4
        MOV     C,A             ;PASAMOS A AL PAR BC
        MVI     B,0
        LXI     H,TABLA         ;HL APUNTA AL COMIENZO DE LA TABLA DE
                                ;DIRECCIONES
        DAD     B               ;AL SUMARLE BC, APUNTA A LA DIRECCION DEL
                                ;SUBPROGRAMA
                                ;CORRESPONDIENTE A LA OPCION ELEGIDA
        MOV     E,M             ;AHORA PASAMOS LA DIRECCION AL PAR DE
        INX     H
        MOV     D,M
        XCHG                    ;Y LA PASAMOS AL PAR HL
        PCHL                    ;Y SALTAMOS A ELLA

; SUBPROGRAMA PARA LA OPCION 1

OP1:    LXI     D,TEXTO1        ;DIRECCION DEL TEXTO A IMPRIMIR
        JMP     COMUN           ;SALTAMOS A LA PARTE COMUN A LOS TRES
                                ;SUBFROGRAMAS
    
; SUBPROGRAMA PARA LA OPCION 2

OP2:    LXI     D,TEXTO2        ;DIRECCION DEL TEXTO A IMPRIMIR
        JMP     COMUN           ;SALTAMOS A LA PARTE COMUN A LOS TRES
                                ;SUBPROGRAKAS

; SUBPROGRAMA PARA LA OPCION 3

OP3:    LXI     D,TEXTO3        ;DIRECCION DEL TEXTO A IMPRIMIR

; PARTE COMUN A LOS TRES SUBPROGRAMAS

COMUN:  MVI     C,PRINT
        CALL    BDOS            ;IMPRIME EL TEXTO
        POP     PSW             ;RECUPERA DEL STACK EL CODIGO DEL CARÁCTER QUE
                                ;HABIAMOS PULSADO
        MVI     C,PRCAR
        MOV     E,A             ;LO PASA AL REGISTRO E
        CALL    BDOS            ;Y LO IMPRIME
        LXI     D,FINAL         ;TEXTO QUE TERMINA LA IMPRESION
        MVI     C,PRINT
        CALL    BDOS            ;LO IMPRIME
        RET                     ;Y VUELVE AL SISTEMA OPERATIVO

TABLA:  DW      OP1             :DIRECCION DE LA RUTINA PARA LA OPCION  1
        DW      OP2             ;DIRECCION DE LA RUTINA PARA LA OPCION  2
        DW      OP3             ;DIRECCION DE LA RUTINA PARA LA OPCION  3
        
PROMPT: DB      CR,LF
        DB      'POR FAVOR,  ELIGE UNA OPCION PULSANDO'
        DB      ' UNA TECLA DEL 1 AL 3: $'

TEXTO1: DB      CR,LF
        DB      'ESTUPENDO, FUISTE DIRECTO A LA OPCION $'

TEXTO2: DB      CR,LF
        DB      ';VAYA!,  HAS SALTADO A LA OPCION $'

TEXTO3: DB      CR,LF
        DB      'YA SE SABE: LOS ULTIMOS SERAN LOS PRIMEROS;
        DB      ' POR ESO ELEGISTE LA OPCION $'

FINAL:  DB       CR,LF,'$'

        END      COMIEN

Y de momento dejamos aquí el tema de la ejecución condicional. En el próximo capítulo podremos ver las llamadas y retornos condicionales y ejemplos de su uso.

es/capítulo_2_-_ejecución_condicional_i.txt · Última modificación: 2016/07/10 22:25 por jevicac