Tarifas
Contacto

Cursos y Tutoriales

CURSOS   DE   PROGRAMACION

LENGUAJE   ENSAMBLADOR

Parte Tercera

Parte 1 Parte 2 Parte 3 Parte 4

Instrucciones de Salto.

Vimos que en el funcionamiento de un microprocesador se reduce básicamente a los siguientes pasos:

 Recogida de la siguiente instrucción de la dirección CS:IP

 Incremento de IP en el número de bytes que componen la instrucción.

 Ejecución de la instrucción.

Una introducción de salto se reduce a cambiar el contenido de IP y, eventualmente el de CS.

Principalmente, existen dos tipos de instrucciones de salto: aquellas que especifican la dirección de salto inmediato después del cód. de operación, es decir, especifican la etiqueta a la que hay que saltar (denominados saltos directos), y aquellas que espe­cifican una dirección de memoria  de la que hay que recoger la dirección a la que saltar (denominadas saltos indirectos).

Los bytes que componen una instrucción de salto directo incluyen en el cód. la operación algunos bytes que especifican la dirección a la que se debe producir el salto.

Pero existen varios formatos posibles para la instrucciones de salto directo. El primero se denomina short jump (salto corto), y el único dato que incluye la instrucción después del cód. de ope­ración es un byte, que representa en complemento a 2 el valor a añadir a IP para seguir la ejecución. Este byte se suma a IP, para lo que primero es necesario extenderlo en signo (que el signo del primer byte ocupe el segundo byte) a 16 bits. Así, el byte repre­senta un desplazamiento entre -128 y +127 bytes (256 bytes), que es el rango que se puede especificar con un bytes en complemento a 2.

Si observamos el orden en el que el microprocesador lleva a cabo la ejecución de una instrucción, veremos que el desplazamiento se suma a IP después de haber incrementado éste. Por tanto, el des­plazamiento se toma desde la dirección de comienzo de la siguiente instrucción al salto, y no desde la propia instrucción de salto.

El siguiente formato de salto directo es el near jump o salto cercano. Este formato, la instrucción incluye dos bytes que forman la palabra a sumar a IP, también en complemento a 2. Así, el rango de salto está entre -32768 y +32768 bytes (65535 bytes), que efec­tivamente permiten un salto a cualquier punto del segmento donde reside la instrucción de salto (en este formato CS tampoco es al­terado por el salto). El ensamblador comprueba si el salto está en el rango (-128, +127) para realizar un salto corto y si no lo está genera un salto cercano.

El último tipo de salto se denomina far jump o salto lejano. Esta denominación se debe a que éste formato de salto, cambia tan­to CS como IP, pudiendo saltar a cualquier punto del megabyte di­reccionable (2 elevado a 20). En éste formato de salto, la ins­trucción lleva dos palabras con el desplazamiento y el segmento de la dirección a la que hay que saltar (se utiliza para realizar un salto a otro segmento). Este tipo de salto copia directamente en IP y CS los valores dados por la instrucción, sin tener en cuenta el contenido previo de ambos.

Existen dos formatos de instrucciones de indirecto: el primero, denominado near jump o salto cercano, lee una palabra de la direc­ción de memoria especificada y carga el registro IP con ésta. Así, se puede saltar a cualquier punto del segmento donde resida la instrucción de salto. El otro tipo se denomina far jump o salto lejano, y toma de la dirección especificada dos palabras, la pri­mera de la cuales se introduce en IP, y la segunda en CS (Ya que el ordenamiento INTEL siempre se almacenan primero los elementos de menor peso). De ésta forma se puede saltar a cualquier punto de la memoria direccionable con un salto indirecto.

* JMP:   El formato de la instrucción es JMP dirección. Provoca un salto incondicional, por lo que se utiliza para seguir la ejecución del programa en otro punto, que puede ser espe­cificando una etiqueta (salto directo) o especificando una dirección (salto indirecto). Cuando incluimos instruccio­nes de salto en el programa, indicamos la dirección del destino, y en caso de que el salto necesite especificar un valor a sumar a IP, el ensamblador se encarga de calcular el desplazamiento desde el punto donde se ejecuta el sal­to. En una instrucción JMP; el propio ensamblador decide si debe generar un salto corto o lejano: en el caso de que el destino esté en el rango de un byte con signo, se gene­ra un salto corto, en caso contrario, se genera un salto cercano.

Ejemplo:

ETIQUETA1:

  JMP continuar

ETIQUETA2:

 JMP continuar

 CONTINUAR:

Nota:   Para los siguiente saltos, vamos a tener en cuenta signi­ficados de palabras inglesas que nos van a ayudar a defi­nir el tipo de salto a realizar:

(Equal=igual, Not=no, Greater=mayor, Less=menor, Abo­ve=superior, Be­low=inferior, Carry=acarreo, ­Zero=cero, Over­flow=desbordamiento, Sign=signo, Parity=paridad)

* JA:   (Salto si superior). Es equivalente a JNBE (Salto si no in­ferior ni igual). El formato es: JA etiqueta si tanto el flag de acarreo CF como el flag de cero ZF está a cero (CF=­0, ZF=0). Si CF=1 o ZF=1 no se transfiere el control. No se considera el signo.

Ejemplo:

CMP ax, bx ; Comparar AX con BX.

JA etiqueta ; Saltar (Bifurcar) a ETIQUETA si AX>BX

   .     ; (sin considerar signo).

   .

ETIQUETA:

* JAE: (Salto si superior o igual). Es equivalente a JNB (Salto si no inferior). El formato es: JAE etiqueta. Salta a la etiqueta si el flag de acarreo es cero (CF=0). No se con­sidera el signo.

Ejemplo:

CMP ax, bx         ; Comparamos AX con BX.

JAE etiqueta       ; Bifurca a ETIQUETA si AX> o =BX

   .                      ; (sin considerar el signo).

   .

ETIQUETA:

* JB:   (Salto si inferior). Es equivalente a JNAE (Salto si no su­perior ni igual) y a JC (Salto sin acarreo). El formato es: JB etiqueta. Salta a la etiqueta si el flag de acarreo es uno (CF=1). No se considera el signo.

Ejemplo:

CMP ax, bx                   

JB etiqueta         ; Bifurca a ETIQUETA si AX < BX

   .                      ; (sin considerar el signo).

   .

ETIQUETA:

* JBE:   (Salto si inferior o igual). Es equivalente a JNA (Salto si no superior). El formato es: JBE etiqueta. Salta a la etiqueta si el flag de acarreo es igual a 1 o el flag de cero es igual a uno (CF=1 y ZF=1). Si CF=0 y ZF=0 no hay salto. No se considera el signo.

Ejemplo:

CMP ax, bx                   

JBE etiqueta       ; Bifurca a ETIQUETA si AX es = o < que BX

   .                      ; (sin considerar el signo).

   .

ETIQUETA:

* JE:   (Salto si igual). Es equivalente a JZ (Salto si cero). El formato es: JE etiqueta. Salta a la etiqueta si el flag de cero es igual a uno (ZF=1). Se considera número con signo y sin signo.

Ejemplo:

CMP ax, bx         ; Comparo AX con BX.

JE etiqueta1        ; Bifurca a ETIQUETA1 si AX = BX.

CMP ax, bx         ; AX=AX-BX

JZ etiqueta2        ; Bifurca a ETIQUETA2 si AX es cero.

* JG:   (Salto si mayor). Es equivalente a JNLE (Salto si no menor ni igual). El formato es: JG etiqueta. Salta a la etiqueta si el flag de cero es igual a cero y el flag de desborda­miento contiene el mismo valor que el flag se signo (ZF=0 y SF=OF). Si ZF=1 o SF<>OF, no hay salto. Se considera el sig­no.

Ejemplo:

CMP ax, bx                   

JG etiqueta         ; Bifurca a ETIQUETA si AX > BX

   .                      ; (considerando el signo).

ETIQUETA:

* JGE:   (Salto si mayor o igual). Es equivalente a JNL (Salto si no menor). El formato es: JGE etiqueta. Salta a la etique­ta si el flag de desbordamiento contiene el mismo valor que el flag  de signo (SF=OF). Se considera el signo.

Ejemplo:

CMP ax, bx                   

JGE etiqueta       ; Bifurca a ETIQUETA si AX es > o = BX

   .                      ; (considerando el signo).

ETIQUETA:

* JLE: (Salto si menor o igual). Es equivalente a JNG (Salto si no mayor). El formato es: JLE etiqueta. Salta a la etique­ta si el flag de cero está a uno o el flag de desborda­miento y el de signo contiene valores distintos (ZF=1 o SF distinto de OF). Si ZF=0 y SF=OF no se produce el salto. Se considera el signo.

Ejemplo:

CMP ax, bx                   

JLE etiqueta        ; Bifurca a ETIQUETA si AX es < o = BX

   .                      ; (considerando el signo).

.

ETIQUETA:

* JNA, JNAE, JNB, JNBE, JNE, JNG, JNGE, JNL, JNLE:

Estas instrucciones comprueban exactamente las condiciones opuestas a sus análogas sin la letra N. En realidad no sería necesaria, porque son sinónimas de JBE, JB, JAE, JNZ, JLE, JL, JGE Y JE, respectivamente. Pero el lenguaje ensamblador estándar las incluye para facilitar el trabajo del programa­dor.

* JO:   (Salto si desbordamiento). Formato es: JO etiqueta. Salta a la etiqueta si el flag de desbordamiento está a uno (OF=1­).

Ejemplo:

ADD ax, bx         ; AX=AX+BX

JO etiqueta         ; Bifurca a ETIQUETA si hay desbordamiento

   .                      ; (Overflow).

ETIQUETA:

* JNO:   (Salto si no desbordamiento). El formato es: JNO etiqueta. Salta a la etiqueta si el flag de desbordamiento está a cero (OF=0).

Ejemplo:

ADD al, bl           ; AL=AL+BL

JNO etiqueta       ; Bifurca a ETIQUETA si no hay desbordamiento

.          ; (No overflow).

.

ETIQUETA:

* JS:   (Salto si signo). El formato es: JS etiqueta. Salta a la etiqueta si el flag de signo está a uno (SF=1).

Ejemplo:

SUB ax, bx         ; AX=AX-BX

JS etiqueta         ; Bifurca a ETIQUETA si signo, es decir, AX < 0

.                      ; (en este caso, si AX es menor que BX).

.

ETIQUETA:

* JNS:   (Salto si no signo / si el signo en positivo). El formato es: JNS etiqueta. Salta a la etiqueta si el flag de signo está a cero (SF=0).

Ejemplo:

SUB ax, bx ; AX=AX-BX

JNS etiqueta  ; Bifurca a ETIQUETA si no signo, es decir, AX > o = que BX

   .             ; (en este caso, si AX es mayor o igual que BX).

.

ETIQUETA:

* JP:   (Salto si paridad). Es equivalente a JPE (salto sin paridad par). El formato es: JP etiqueta. Salta a la etiqueta si el flag de paridad está a uno (PF=1).

Ejemplo:

AND ax, bx         ; AX=AX AND BX

JP etiqueta         ; Bifurca a ETIQUETA si paridad par, es decir

   .             ; si el número de "unos (1)" que hay en AX es par.

.

ETIQUETA:

* JNP:   (Salto si no paridad). Es equivalente a JPO (salto sin paridad impar). El formato es: JNP etiqueta. Salta a la etiqueta si el flag de paridad está a cero PF=0).

Ejemplo:

AND ax, bx         ; AX=AX AND BX

JNP etiqueta       ; Bifurca a ETIQUETA si paridad impar, es decir

.     ; si el número de "unos (1)" que hay en AX es impar.

.

ETIQUETA:

* LOOP:   Esta instrucción permite realizar "bucles" utilizando el registro CX como contador (CX en un contador que va de­crementándose). Un bucle es un conjunto de instrucciones que se ejecutan una serie de veces. Esta instrucción equi­vale al par: DEC CX // JNZ etiqueta.

El formato es: LOOP etiqueta.


Ejemplo:

MOV cx, 15 ; CX=15; 15 sería el número de veces que se va a ejecutar el bucle.

ETIQUETA:

; Aquí estarían las instrucciones que están dentro del bucle.

LOOP etiqueta           ; CX=CX-1 y bifurca a ETIQUETA si CX es distinto a cero.

* LOOPE:   Esta instrucción al igual que LOOP, permite realizar "bucles" utilizando el registro CX como contador (CX en un contador que va decrementándose) pero además el flag de cero debe estar a uno (ZF=1). Es equivalente a LOOPZ (Bucle si cero). Esta instrucción equivale al par: JNE FIN // LOOP OTRO. El formato es: LOOPE etiqueta.

Ejemplo:

MOV cx, Length tabla      ; CX=longitud de la TABLA.

            MOV si, inicio              ; Movemos a SI el inicio de la TABLA.

DEC si                ; Esto se hace para poder realizar el bucle

; que viene ahora

 OTRO: INC si         ; Movemos a SI su valor inicial.

CMP tabla[SI], 0  ; Comparamos cada valor de la TABLA con cero

LOOPE OTRO                 ; si el valor de TABLA es igual a cero realiza un

; LOOP normal, sino, no hace el LOOP.

* LOOPNE:    Esta instrucción al igual que LOOP, permite realizar "bucles" utilizando el registro CX como contador (CX en un contador que va decrementándose) pero además el flag de cero debe estar a cero (ZF=0). Es equivalente a LOOP­NZ (Bucle si no cero). Esta instrucción equivale al par: JE FIN // LOOP OTRO.

El formato es: LOOPNE etiqueta.

Ejemplo:

MOV cx, Length tabla      ; CX=longitud de la TABLA.

            MOV si, inicio              ; Movemos a SI el inicio de la TABLA.

DEC si                ; Esto se hace para poder realizar el bucle

; que viene ahora.

 OTRO: INC si                                            ; Movemos a SI su valor inicial.

CMP tabla[SI], 0  ; Comparamos cada valor de la TABLA con cero

LOOPNE OTRO               ; si el valor de TABLA es distinto a  LOOP normal,

                                                                                  ; sino, no hace el LOOP.

Instrucciones de Rotación y Traslación.

Este grupo de instrucciones nos permitirán tratar la informa­ción almacenada en registros o en memoria mediante el tratamiento unitario de sus bits.

* RCL:   (Rotar a la izquierda con acarreo).

El formato es: RCL operando, contador. Rota a la iz­quierda los bits del operando junto con la bandera de acarreo, CF, el número de bits especificado en el segun­do operando. Si el número a desplazar es 1, se puede especificar directamente (Por ejemplo: RCL AL, 1). Si es mayor que 1, su valor debe cargarse en CL y especificar CL como segundo operando.

Ejemplo:

MOV cl, 3           ; Rotar 3 bits

; AL = 0101 1110b, CF=0 (Flag de acarreo=0)

RCL al, cl                        ; AL = 1111 0001b, CF=0

Procedimiento:

Cuenta (CL)

Antes

Después

1

AL = 0101 1110b, CF=0

AL = 1011 1100b, CF=0

2

AL = 1011 1100b, CF=0

AL = 0111 1000b, CF=1

3

AL = 0111 1000b, CF=1

AL = 1111 0001b, CF=0

* RCR:  (Rotar a la derecha con acarreo).

El formato es: RCR operando, contador. Rota a la derecha los bits del operando junto con la bandera de acarreo, CF, el número de bits especificado en el segundo operan­do. Si el número a desplazar es 1, se puede especificar directamente (Por ejemplo: RCR AL, 1). Si es mayor que 1, su valor debe cargarse en CL y especificar CL como segun­do operando.

Ejemplo:

MOV cl, 3           ; Rotar 3 bits

; AL = 0101 1110b, CF=0 (Flag de acarreo=0)

RCR al, cl           ; AL = 1000 1011b, CF=1

Procedimiento:

Cuenta (CL)

Antes

Después

1

AL = 0101 1110b, CF=0

AL = 0010 1111b, CF=0

2

AL = 0010 1111b, CF=0

AL = 0001 0111b, CF=1

3

AL = 0001 0111b, CF=1

AL = 1000 1011b, CF=1

* ROR:  (Rotar a la derecha).

El formato es: ROR operando, contador. Rota a la derecha los bits del operando de tal forma que el bits del ex­tremo derecho del operando destino para al bit extremo izquierdo de dicho operando y al mismo tiem­po para el bit de acarreo (CF). Si el  número a desplazar es 1, se puede especificar directamente (Por ejemplo: ROR AL, 1). Si es mayor que 1, su valor debe cargarse en CL y espe­cificar CL como segundo operando.

Ejemplo:     MOV cl, 2            ; Rotar 2 bits

; AL = 0011 0011b, CF=0 (Flag de acarreo=0)

RCR al, cl      ; AL = 1100 1100b, CF=1

Procedimiento:

Cuenta (CL)

Antes

Después

1

AL = 0011 0011b, CF=0

AL = 1001 1001b, CF=1

2

AL = 1001 1001b, CF=1

AL = 1100 1100b, CF=1

* ROL:   (Rotar a la izquierda).

El formato es: ROL operando, contador. Rota a la iz­quierda los bits del operando de tal forma que el bits del extremo izquierdo del operando destino para al bit extremo derecho de dicho operando y al mismo tiempo para el bit de acarreo (CF). Si el  número a desplazar es 1, se puede especificar directamente (Por ejemplo: ROL AL, 1). Si es mayor que 1, su valor debe cargarse en CL y especificar CL como segundo operando.

Ejemplo:

MOV cl, 2           ; Rotar 2 bits

; AL = 1100 1100b, CF=0 (Flag de acarreo=0)

RCR al, cl           ; AL = 0011 0011b, CF=1

Procedimiento:

Cuenta (CL)

Antes

Después

1

AL = 1100 1100b, CF=0

AL = 1001 1001b, CF=1

2

AL = 1001 1001b, CF=1

AL = 0011 0011b, CF=1


* SAL:   (Desplazamiento aritmético a la izquierda). Es equivalente a SHL (Desplazamiento lógico a la izquierda).

El formato es: SAL operando, contador. SHL y SAL realizan la misma operación y son físicamente la misma instruc­ción. Copia en cada bit del operando el contenido previo del bit de su derecha. El bit de menor peso se pone a cero. El contenido previo del bit de mayor peso se copia en el flag de acarreo (CF). Es equivalente a multiplicar el operando por dos, tanto para números sin signo como para número en complemento a 2, siempre el resultado no se salga del rango. Si el  número de bits a desplazar es 1, se puede especificar directamente (Por ejemplo: SAL AL, 1). Si es mayor que 1, su valor debe cargarse en CL y especificar CL como segundo operando.

Ejemplo:

MOV cl, 2           ; Desplazar 2 bits

; AL = 1100 1100b, CF=0 (Flag de acarreo=0)

SAL al, cl            ; AL = 0011 0000b, CF=1

Procedimiento:

Cuenta (CL)

Antes

Después

1

AL = 1100 1100b, CF=0

AL = 1001 1000b, CF=1

2

AL = 1001 1000b, CF=1

AL = 0011 0000b, CF=1

* SAR:   (Desplazamiento aritmético hacia la derecha con extensión de signo). El formato es: SAR operando, contador. Copia en cada bit del operando el contenido previo del bit de su izquierda. El bit de mayor peso mantiene su valor ante­rior. El contenido previo del bit de menor peso se copia en el flag de acarreo (CF). Es equivalente a dividir el operando por dos  para números   en complemento a 2. Si el  número de bits a desplazar es 1, se puede especificar di­rectamente (Por ejemplo: SAR AL, 1). Si es mayor que 1, su valor debe cargarse en CL y especificar CL como segundo operando.

Ejemplo:

MOV cl, 2           ; Desplazar 2 bits

; AL = 1100 1100b, CF=0 (Flag de acarreo=0)

SAR al, cl           ; AL = 1111 0011b, CF=0

Procedimiento:

Cuenta (CL)

Antes

Después

1

AL = 1100 1100b, CF=0

AL = 1110 0110b, CF=0

2

AL = 1110 0110b, CF=0

AL = 1111 0011b, CF=0

* SHR:  (Desplazamiento aritmético hacia la derecha).

El formato es: SAR operando, contador. Copia en cada bit del operando el contenido previo del bit de la izquier­da. En el bit de mayor peso se almacena un 0. El conte­nido previo del bit de menor peso se copia en el flag de acarreo (CF). Es equi­valente a dividir el operando por dos para números sin signo. Si el número de bits a des­plazar es 1, se puede especificar directamente (Por ejem­plo: SHR AL, 1). Si es mayor que 1, su valor debe cargarse en CL y especificar CL como segundo operando.

Ejemplo:

MOV cl, 2           ; Desplazar 2 bits

; AL = 0011 0011b, CF=0 (Flag de acarreo=0)

SHR al, cl           ; AL = 0000 1100b, CF=1

Procedimiento:

Cuenta (CL)

Antes

Después

1

AL = 0011 0011b, CF=0

AL = 0001 1001b, CF=1

2

AL = 0001 1001b, CF=1

AL = 0000 1100b, CF=1

Ejercicios:

1.- Disponemos en memoria de una variable que nos ocupa una pala­bra, identificada con el símbolo UNO y que tiene el valor de 35 (dentro del segmento de datos: UNO DW 35), y disponemos de un byte identificado con el símbolo DOS y que posee un valor de 10 (dentro del segmento datos: DOS DB 10). Calcular la suma de estos datos.

2.- Acceder a un datos que está almacenado en la dirección 123Ah:00­08 en una palabra de memoria dentro del segmento extra, y calcular lo siguiente:

  a) Si los bits: 11, 9, 5 y 3 están a uno.

  b) El número de bits a uno que tiene ese dato.

  c) Si este dato es de paridad impar, debe saltar a una eti­quea que se llama FIN.

3.- Supongamos que tenemos cargados en variables de memoria (UNO, DOS, TRES, CUATRO, CINCO, SEIS, SIETE de tipo byte), siete infor­maciones de ficheros que hemos leido de un disco. Cada información puede tener, en sus cuatro bits menos signifactivos, los siguien­tes atributos:

 Si bit 3 a 1 - Atributo de Lectura.

 Si bit 2 a 1 - Atributo de Sistema.

 Si bit 1 a 1 - Fichero Oculto.

 Si bit 0 a 1 - Fichero Borrado.

Se quiere saber cuantos ficheros de estos siete son: de lectura, de sistema, ocultos, borrados, de lectura y sistema, de lectura y oculto, de sistema y oculto y de lectura y sistema y oculto.                         UNO      DB  1111 0111

DOS              DB  1111 1000

TRES                        DB  1111 0101

CUATRO      DB  1111 1110

CINCO          DB  1111 1111

SEIS             DB  1111 0010

SIETE           DB  1111 1110

4.- Realiza una rutina que nos permita multiplicar dos cantidades que estén almacenadas en dos palabras de memoria, que conocemos con los simbolos UNO y DOS, considerando que dicha multiplicación debe  realizarse mediante sumas sucesivas.

5.- Realizar una rutina que nos permita realizar la división de dos cantidades numéricas almacenadas en 2 dirección de memoria que vamos a conocer con los nombres UNO y DOS, considerando que dicha división se debe realizar mediante resta sucesivas.

6.- Disponemos de una cantidad almacenada en memoria identificada por 1 palabra mediante el símbolo UNO. Calcula el factorial del valor de la palabra.

La Pila.

La estructura de una PILA es similar a un montón de libros api­lados: los elementos se van ordenando cada uno detrás del último en llegar (es decir, los libros se van apilando cada uno encima del anterio), pero al sacarlos de la estructura se empieza por el último en llegar, acabando por el primero (al retirar los libros se comienza por el superior, y se acaba por el que queda abajo del todo).

A la operación de introducir un elemento en una pila se le suele dar el nombre de empujar un elemento (push en inglés). La opera­ción de extraer un elemento de una pila se le denomina pop.

Los elementos que puede almacenar la pila del microprocesador son valores de 16 bits, con lo cual el puntero de pila se debe incrementar o decrementar 2 unidades a la hora de sacar o introdu­cir valores en la pila (a meter un valor de 16 bits en la pila el puntero de la pila se decrementa en dos unidades, y a la hora de sacar un elemento de la pila el puntero se incrementa en dos uni­dades; la pila crece hacia abajo en lugar de hacia arriba).

El microprocesador tiene dos registros que se utilizan para gestionar la pila: el SS (Segmento de Pila) y el SP (Puntero de Pila). El par SS:SP da la dirección donde se encuentra el último valor empujado en la pila.

* PUSH:   Decrementa en 2 unidades el puntero de la pila, es decir, decrementa en 2 unidades el registro SP, y  a continua­ción almacena en la cima de la pila la palabra especifi­cada en el operando origen asociado a la instrucción.         Formato PUSH origen

Ejemplo:      PUSH ax            ;es equivalente a:  SP = SP-2  //  MOV ss:[sp], ax

El operando origen no puede ser un operando inmediato (ni el registro de segmento CS).

* POP:   Esta instrucción toma una palabra de la cima de la pila y la sitúen el operando destino asociado a la instrucción, incrementando, a continuación, en 2 unidades el puntero de la pila.

Formato POP origen

Ejemplo:    POP ax  ; es equivalente a: AX = SS:[SP] // SP = SP + 2

Cuando una instrucción PUSH o POP se ejecuta en un código de programa con el tamaño de registro de 32 bits (USE32), el ensamblador utiliza como valor de trasferecencia 4 bits en lugar de 2 bytes (una palabra), y las operaciones realiza­das con ESP se efectúan sobre unidades de 4 elementos.

* PUSHF:   Esta instrucción decrementa en 2 unidades el puntero de la pila y a continuación, almacena en la cima de la pila el registro de indicadores (FLAGS). No tiene ningún ope­rando.

* POPF:   Esta instrucción almacena en el registro de indicadores (FLAGS) la palabra situada en la cima de la pila aumen­tando en 2 unidades, a continuación, el puntero de la pila. No tiene ningún operando.


* PUSHA y POPA: Estas instruciones almacenan y sacan de la pila la información contenida en los registros siguientes y en el orden siguiente: AX, CX, DX, BX, SP, BP, SI y DI. El valor de SP es guardado en la pila antes de que el primer registro sea guardado. En el caso de utilizar registros de 32 bits la instrucciones serían: PUSHAD y POPAD.

Todo lo que entra en la pila, tiene que salir de la pi­la. El orden de situar y sacar palabras de la pila es el siguiente:

PUSH ax

PUSH bx

PUSH cx

PUSH dx

Rutina del programa

POP dx

POP cx

POP bx

POP ax

Ejercicios:

1.- Se pide calcular los números comprendidos entre dos cantidades numéricas almacenados en palabras y que vamos a identificar con los símbolos UNO y DOS. Se debe utilizar de forma obligatoria ins­trucciones que manejen la pila.

Interrupciones.

Una interrupción es una señal que provoca la suspensión del programa que se estaba ejecutando y provoca el comienzo de ejecu­ción de un programa de tratamiento que de solución a esa interrup­ción.

A ese programa se le conoce como RUTINA DE TRATAMIENTO de esa interrupción.

Este procesador nos presenta tres grupos de interrupciones:   

a) Interrupciones Hardware o Interrupciones Externas, que son aquellas provocadas por los dispositivos periféricos, controladas por un procesador especial de interrupciones (8259) o IPC (Con­tro­lador de Interrupciones Programable), y la rutina de tratamiento está "cableada".

b)Interrupciones Internas, que son aquellas provocadas dentro del propio procesador por una situación anormal de funcionamiento de alguna de sus partes.

C) Interrupciones de Software, Son aquellas que son programa­bles y que podemos cambiar. Las interrupciones de software podemos llegar a manejarlas y por ello el ensamblador nos proporciona una instrucción que nos permita poner en funcionamiento una determina­da rutina de interrupción; esta instrucción es INT.

* INT.  Formato INT núm_entero. Ese "núm_entero", asociado a la instrucción, es un iden­tificativo que nos dice mediante la aplicación de un algoritmo, la posición de Memoria Interna donde se encuentra almacenada la dirección de comienzo de la rutina de tratamiento de esa interrupción.

El ensamblador permite, normalmente, identificar 256 interrup­ciones. Una parte de ellas son las correspondientes a la ROM-BIOS y las proporciona el fabricante.

Otra parte de ellas forman del sistema operativo DOS, y otra parte de ellas queda libre para que el programador genere sus propias rutinas de interrupción.

Las interrupciones correspondientes a la parte de la BIOS y las correspondientes a la parte del DOS representas caracte­rísticas similares.

Existe un flag denominado IF (Interrupción Flag, Flaf de Inte­rrupción) que determina la reacción del microprocesador ante una interrpción. Si el flag está a uno, el rpocesador respon­de a la interrupción producida; pero si el flag IF está a cero, la petición de interrupción será ignorada completamente por el microprocesador.

En algunas secciones de código, resulta necesario deshabilitar las interrupciones (poner el flag IF a cero) durante algunos ciclos, y habilitarlas de nuevo después.

La familia 8086 provee dos instrucciones que realizan estas tareas:

STI   (Activar flag de interrupciones): Pone el flag IF a i, de forma que se premiten las interrupciones.

CLI   (Borrar flag de interrupciones): Pone el flag IF a 0, de modo que el microprocesador no responde a más interrup­ciones hasta que se ejecuta un STI o se altera el conte­nido de los flags (entre ellos el de IF) recuperándolos de la pila con POPF o IRET.

MOV ax, 8000h

CLI

MOV ss, ax

MOV sp, 2000h

STI

* IRET:  Retorno de interrupción. Formato: IRET (no tiene operan­dos). Retorna de una rutina de servicio a la interrup­ción, extrayendo de la pila los nuevos valores de IP y CS, en este orden, y el contenido del registro de flags. La ejecución continúa en la instrupción siguiente a la que se estaba ejecutando cuando ocurrió la interrupción.

Ejemplos de interrupciones del DOS.

Vamos a ver unos ejemplos de interrupciones del DOS (Vamos a ver unas interrupciones donde el "nº entero" va a ser 21h. Esta inte­rrupción presenta una gran cantidad de funciones diversas; por ello además de indicar el "nº entero", debemos indicar también el "nº función" que deseamos dentro de esa interrupción. Dicho número se almacena siempre el registro AH):

 - INT 21h.  Función 01h: Permite dar entrada a un carácter e te­clado y al mismo tiempo dicho carácter aparece en pantalla, en la posición en la que se encuentre el cursor. El carácter tecleado queda almacenado en AL. Si no hay ningún carácter disponible, se espera hasta que haya alguno.

MOV ah, 01h

INT 21h            ; El carácter tecleado queda en AL

 - INT 21h.  Función 02h: Permite llevar un carácter desde el po­cesador hacia la pantalla. Dicho carácter debe estar almacenado en el registro DL. Aparecerá en la posi­ción donde se encuentre el cursor.

MOV dl, carácter

MOV ah, 02h

INT 21h

 - INT 21h.  Función 08h: Permite dar una entrada de un carácter desde el teclado pero sin que aparezca en pantalla. El carácter tecleado queda almacenado en el registro Al. Si no hay un carácter disponible se espera hasta que lo haya.

MOV ah, 08h

INT 21h            ; El carácter tecleado queda en AL

 - INT 21h.  Función 09h: Visualización de una cadena de caracte­res. Nos permite llevar una cadena de  caracteres hacia la pantalla. Dicha cadena aparecerá a partir de la posición en la que se encuentre el cursor. Esta función necesita que en el registro DX se encuentre la dirección de comienzo de la cadena a presentar en pantalla.

MOV dx, offset cadena            ; En DX queda el desplazamiento que hay que hacer dentro

; de DS para llegar a la posición donde se encuentra

; "cadena" (DS:DX).

MOV ah, 08h

INT 21h

 - INT 21h.  Función 4Ch: Acabar el proceso con código de retorno. Permite realizar el retorno al Sistema Operativo. Acaba el proceso actual, enviando un código de retor­no al programa original. Se trata de uno de los di­versos métodos con los que se puede provocar una sa­lida definitiva de un programa.

MOV ah, 4ch

INT 21h

Otras instrucciones

* LEA: Formato: LEA destino, fuente. Transfiere el desplazamiento del operando fuente al operando destino. El operando fuen­te debe ser un operando de memoria. El operando destino es un registro, pero no un registro de segmento. LEA permite especificar regitros índices en el operando fuente, al contrario que con la instrucción OFFSET.

Ejemplo:

LEA dx, [bx+si+20] ; En DX quedaría el desplazamiento que habría

;que hacer dentro del segmento de datos (DS), para

; acceder a la información

; indicada por la suma de BX + SI + 20.

; DX - BX + SI + 20

; DS : DX = BX + SI + 20

(Segmento de Datos)

TEXTO db "ejemplo1$"

(Segmento de Código)

LEA dx, texto    ; Queda en DX el desplazamiento que hay que hacer dentro del

; segmento de datos (DS), para acceder a la información que tiene

; la variable TEXTO DS:DX= dirección del texto.

Si situamos todos los datos que emplea nuestro programa en un sólo segmento, apuntando por DS, la localización de memoria de un dato se puede dar por un desplazamiento (offset), suponiendo im­plícitamente que reside en el segmento apuntando por DS.

Este tipo de punteros (un puntero es un valor que indica la localización de otra variable) se denominan NEAR POINTERS (Puntero cercanos).

Pero si queremos especificar la dirección donde reside un dato que puede estar en cualquier lugar del megabyte direccionable, es necesario especificar tanto segmento donde se encuentra el dato como el desplazamiento dentro de dicho segmento; este tipo de pun­teros se denominan FAR POINTERS (Punteros lejanos).

Cuando almacenamos un puntero cercano en memoria, se almacena únicamente una palabra. Pero cuando alamacenamos un puntero leja­no, se almacena el desplazamiento y el segmente en palabras conse­cutivas en memoria.

Al cargar un puntero cercano, por ejemplo, SI, se carga directa­mente de memoria con instrucciones como MOV SI, mem, de manera que el par DS:SI contiene el puntero deseado. Pero al cargar un punte­ro lejano, es necesario cargar tanto un registro con el desplaza­miento (offest) como un registro de segmento del puntero (habi­tualmente se carga en ES, manteniendo DS siempre constante apun­tando a los datos de uso habitual del programa).

Existen 2 instrucciones que cargan de una sola vez tanto el desplazamiento como el segmento: LDS y LES.

LDS reg, mem               LDS si, cs:[di+2]

LES reg, mem               LES ax, [bp+si]

Ambas instrucciones cargan en el registro especificado con reg la palabra contenida en la dirección dada por mem, y en el regis­tro de segmento indicado (DS para LDS y ES para LES) la palabra contenida en la dirección indicada +2.

* OFFSET: Formato OFFSET variable o OFFSET etiqueta. Podemos uti­lizar la instrucción OFFSET para obtener el desplaza­miento dentro de un segmento de una etiqueta cualquie­ra.

Ejemplo:

(Segmento de Datos)

TABLA db 'ejemplo 1$'

(Segmento de Código)

MOV ax, offeset tabla           ; En AX queda el desplazamiento que hay que hacer

; dentro del segmento por defecto en curso para

; acceder al contenido de TABLA. 

; AX = desplazamiento de TABLA.

Estructuras de programación. Directivas.

* IF:  Las instrucciones que empiezan por "IF" son directivas con­dicionales. Sirven para que el ensamblador incluya o no las sentencias que vienen a continuación, según se cumpla o no una determinada condición.

El formato es:

.IF condicional

sentencias

[ .ELSELF condición2

sentencias ]

[ .ELSE

sentencias ]

.ENDIF

Ejemplo:

.IF cx == 20

MOVE dx, 20

.ELSE

MOVE dx, 30

.ENDIF

Algunos operadores utilizados para la comparaciones son:

==  Igual

         !=      Distinto (no igual)

         >    Mayor

         >= Mayor Igual

         <    Menor

         <= Menor Igual

         !        NOT Lógico

         &&   AND Lógico ("y")

         ||    OR Lógico ("o")   

* FOR:   Las instrucciones que empiezan por "FOR" son directivas de "ciclos".

El formato es:

FOR parámetro, <Lista de argumentos>

ENDM

Ejemplo:

MOV ax, 0

FOR arg, <1,2,3,4,5,6,7,8,9,10>

ADD ax, arg

ENDM  ; Esto lo que hace es sumar cada vez a AX el valor que

; aparece en la de argumentos.

; ( AX = AX + 1, AX = AX + 2, AX = AX + 3,...)

* WHILE: Las instrucciones que empiezan por "WHILE" son directi­vas de "ciclos".

 El formato es:

.WHILE condición

sentencias

.ENDW

Ejemplo:

(Segmento de Datos)

buf1        BYTE               "Esto es una cadena", '$'

buf2        BYTE  DUP (?)

(Segmento de Código)

XOR bx, bx

.WHILE  (but1[bx]!= '$')

MOV al, buf1[bx]

MOV buf2[bx], al

INC bx

.ENDW

* REPEAT:    Las instrucciones que empiezan por "REPEAT" son direc­tivas de "ciclos".

El formato es:

.REPEAT

sentencias

.UNTIL condición

Ejemplo:

(Segmento de Datos)

buffer     BYTE 100 DUP (0)

(Segmento de Código)

XOR bx, bx

.REPEAT

MOV ah, 01h

INT 21h

MOV buffer[bx], al

INC bx

.UNTIL (al==13)   ; En este caso la interrupción 21h con la función 01h deja en AL la tecla que se ha pulsado y la mete en "buffer". Si esta es

ENTER (13) se sale del bucle, sino sigue en él.

         Parte 1 Parte 2 Parte 3 Parte 4

Copyright © 1998-2012- DS Tecnologia® manager@dstecnologia.com.ar - Politica de Privacidad