Tarifas
Contacto

Cursos y Tutoriales

CURSOS   DE   PROGRAMACION

LENGUAJE   ENSAMBLADOR

Parte Segunda

Parte 1 Parte 2 Parte 3 Parte 4

Movimientos de datos.

En un micro-procesador 8086, el juego de registros es muy reducido. Evidentemente esto no es suficiente para llevar en registros todas las variables del programa Además, algunos de estos registros presentan peculiaridades (Ej: el registro de bandera) que los hacen inservibles para almacenar valores. Por todo esto, las variables de un programa se almacenan en memoria y se traen al registro sólo cuando son necesarias para algún calculo. Después, si es necesario actualizar su valor se vuelve a llevar a memoria el contenido del registro que proceda.

Algo ya mencionado es que muchos de los registros desempeñan papeles concretos en algunas instrucciones

Ejemplo: para un bucle, el contador se suele llevar casi siempre en el registro CX. O para una multiplicación es necesario cargar uno de los factores en AX).

Como ya vimos, para todas las operaciones de movimientos de datos existe una instrucción de lenguaje ensamblador denominada MOV, donde los operandos son 2, escritos separados por comas: el primero es el destino y el segundo el origen (Ej: MOV ax, bx).

Evidentemente, los operandos deben de tener la misma longitud (= número de bits). Pueden ser registros, posiciones de memoria, etc. Hacemos aquí un pequeño inciso para anotar que tradicionalmente los ensambladores no distinguen entre minúsculas y mayúsculas.

Tanto las instrucciones como los identificadores podemos escribirlos como queramos.

MOV ax,1

mov BX,2

MOV CX,3

mov dx,4

Estas instrucciones cargan AX con 1, BX con 2, ...

El dato que se carga en el registro va incluido en la propia instrucción siguiendo al código de operación que indica que se trata de una instrucción de transferencia y a que referencia hay que transferir.

Así, los código de las 4 instrucciones en hexadecimal son:

Código Operación

MOV ax,1

BB   0100

MOV bx,2

BB   0200

MOV cx,3

B9   0300

MOV dx,4

BA   0400

16 bits

La estructura de las 4 instrucciones es igual. De principio el primer byte es el código de operación que identifica la instrucción que se está tratando. Ya que con este código de operación es necesario un valor de este tamaño (16 bits) para completar la instrucción, como podemos apreciar en los otros 2 bytes.

Estos bytes constituyen un valor de 16 bits almacenados en el orden INTEL, es decir, el bit menos significativo el primero y el más significativo después.

AH

AL

OO

O1

AX

BH

BL

00

02

BX

CH

CL

00

03

CX

DH

DL

00

04

DX

Cuando queremos especificar al ensamblador que un numero debe ser interpretado como una dirección de memoria a la que acceder escribimos el número entre corchetes. Así la siguiente instrucción carga en AX la palabra almacenada en la dirección DS:0000. Es decir, carga en AL el byte contenido en DS:0000 y en AH el contenido en DS:0001

MOV ax, [0]

DS:0000

25

DS:0001

43

Memoria

Tamaño de Palabra 1 byte

El valor de AX sería:

AH

AL

43

25

En cambio la siguiente instrucción lo que hace es almacenar el valor 0 en el registro AX.  

 MOV ax, 0

Es importante comprender la diferencia entre las 2 instrucciones. La primera lleva corchetes, se accede a la memoria y el valor recogido se almacena en AX. En la segunda se almacena en AX el valor 0 directamente sin acceder a memoria. Por lo tanto el valor de AX quedaría:

AH

AL

0

0

También podemos escribir en una posición de memoria el contenido de un registro. Con MOV [0], al  almacenamos en el contenido de AL en DS:0000  Si AL es 25...

DS:0000

25

DS:0001

Memoria

Tamaño de Palabra 1 byte

Aunque así podemos acceder a cual quier posición de memoria, en el segmento apuntado por DS, a menudo, nos interesa acceder a la posición de memoria indicada por el contenido de un registro. Por omisión se asume que la dirección de un operando está en el segmento de datos y el registro de segmento a emplear es DS. Con el desplazamiento almacenado en BX, SI o DI.

Las instrucciones que hemos visto no nos sirven porque la dirección a la que accede va incluida en los código de instrucción. Para ello existe un formato de la instrucción MOV que nos permite acceder a la posición de memoria indicada por BX. Así si BX contiene el valor 55AAh se accederá a esta posición de memoria mientras que si BX contiene el valor 1000h se accederá a la posición 1000h. Para esto escribimos entre corchetes BX el lugar de dar directamente el número.

MOV bx, 2345h

MOV ax, [bx]

Con esto almacenamos en AX el contenido de la dirección 2345 y 2346 ya que AX es una palabra. Si fuera AL o AH solo se almacenaría 2345. Por tanto, en AH almacena 2345h y en AL 2346h.

Por supuesto podemos acceder a memoria usando el registro BX para la escritura:

MOV bx, 2345h

MOV [bx], al

En este caso, solo se modifica el contenido de la dirección 2345h y no el de la 2346h, ya que estamos escribiendo el contenido de un registros de 8 bits.

Hemos usado en los ejemplos los registros de datos BX, esto se debe a que el juego de instrucción de los 8086 permiten únicamente acceder a la dirección contenida en el registro de datos BX. No a la contenida en el registros de datos AX, CX o DX. Ya que solo disponer de un solo registro para acceder a memoria resulta incómodo los 8086 incorporan otros 2 registros índices: SI y DI.

Estos dos registros permiten todas las instrucciones vistas para BX, tanto para transferencia entre registros como para transferencia entre procesador y memoria.  Pero no hay ninguna forma de acceder por separado a los dos bytes que lo componen.

BH

BL

 BX

    16     

 SI

No tienen ni parte alta ni parte baja. Son compactos

    16     

 DI

Otro registro que se puede usar como BX, SI y DI es el registro de puntero de base BP. Al igual que en SI y Di no se puede acceder por separado a los 2 bytes de mayor y menor peso. Pero la mayor diferencia es que por defecto se usa el registro de segmento SS para completar la dirección de 20 bits.

DS

:

BX

SS

:

BP

SI

DI

Movimientos más generales realizados con MOV:

Formato de Instrucción

Ejemplo

MOV  reg , reg

 

MOV aex, ebx

MOV  mem , reg

 

MOV [bx], al

MOV  reg , mem

 

MOV ch, [40ffh]

MOV  mem , inmediato

 

MOV byte ptr [di], 25*80

MOV  reg , inmediato

 

MOV ebx, offffh

MOV  segmentoreg , reg 16

 

MOV ds, ax

MOV  reg 16 , segmentoreg

 

MOV ax, es

MOV  mem , segmentoreg

 

MOV [si], es

MOV  segmentoreg , mem

 

MOV ss, [1234h]

Hay varios puntos que debemos explicar de la tabla:

        

Reg: representa cualquier registro de 8, 16 o 32 bits pero con la restricción de que cuando la operación es MOV reg, reg ambos deben ser iguales.

     

Mem:  se refiere a posiciones de memoria.

 

Inmediato:  especifica que se debe tomar un valor incluido en los código de la propia instrucción como en el caso de MOV ax, 5 en donde 5 se denomina valor inmediato.

 

Segmentoreg: puede ser cualquier registro de segmento.

 

Reg 16: indica cualquier registro de 16 bits.

La exigencia en algunos formatos de registros de 16 bits se debe a que los registros de segmento normales y extendidos son de 16 bits  todas las operaciones de movimiento con estos registros se hacen con registros de 16 bits. Como vemos no es posible copiar directamente el contenido de un registro de segmento a otro. O cargar un registro de segmento con un valor inmediato, sino que es necesario pasar por un registro intermedio.

MOV es, ds  

MOV ax, ds

MOV es, ax

MOV es, 5  

MOV ax, 5

MOV ds, ax

Especificar el registro CS como destino de la instrucción MOV está prohibido, ya que haría que la ejecución saltase a otro punto. Esto solo se permite a la instrucción de salto. La mayoría de los 8086 paran la ejecución del programa al encontrarla.

Uno de los formatos MOV interesantes es: 

MOV mem, inmediato. 

Permite introducir directamente en memoria un valor sin alterar ningún registro. Pero esto presenta un inconveniente, en los demás formatos siempre hay un registro como destino u origen de forma que el ensamblador deduce el tamaño del valor a mover. Así en las instrucciones.

MOV ax, [4220h]

MOV al, [4220h]

La primera instrucción genera un acceso a memoria de 16 bits que se descarga en un registro de ese tamaño. La segunda genera una lectura de 8 bits ya que Al solo tiene esta longitud.

MOV [4220h], 0

Nada indica al compilador si el 0 es de 1 o de 2 bytes. Hay dos posibles instrucciones máquina para esta línea de lenguaje ensamblador:

1ª   Una instrucción de escritura de 16 bits poniendo a 0 los bits de las direcciones 4220h y 4221h.

2ª   Una instrucción de escritura de 8 bits poniendo a 0 solo los bits de la dirección 4220h.

Por ello se hace necesario indicar al ensamblador de cual de las dos se trata.

La sintaxis para esto se comprende mejor así: El número 4220h es análogo a un puntero ya que es un valor que se interpreta como direcciones de memoria usándose en realidad como el desplazamiento que completa la dirección con DS. Este puntero puede ser de dos tipos:

 

-  Puntero a 1 byte  se debe generar una instrucción de escritura de 8 bits.

 

-  Puntero a 1 palabra  se debe generar una instrucción de escritura de 16 bits.

Así para aclarar esto se usa:

MOV  byte ptr [4220h], 0                      ; pone a 0 solo el byte de la dirección 4220h

MOV word ptr [4220h], 0                      ; pone a 0 los bytes de las direcciones 4220h y 4221h

Hemos visto que podemos acceder a la memoria componiendo las direcciones de diferentes formas,  especificándolas directamente, en cuyo caso, el valor se incluye en la codificación de la instrucción por medio de los registros BX, SI, DI o BP. Pero en realidad hay muchas formas de indicar como se deben componer el desplazamiento.

Estas maneras de obtener la dirección se denominan Modos de Direccionamiento y cada uno tiene asignado un registro de segmento por defecto.

Modos de Direccionamiento

Denominación

Obtención Desplazamiento

Segmento

Ejemplo

Direccionamiento Absoluto

Inmediato

DS

MOV al, 0

Direccionamiento Indirecto con Base (BX)

BX+XX

DS

MOV cx, [bx+2]

Direccionamiento Indirecto con Indice (SI)

SI+XX

DS

MOV dx, [si+2]

Direccionamiento Indirecto con Indice (DI)

DI+XX

DS

MOV [di], es

Direccionamiento Indirecto con base (BP)

BP+XX

SS

MOV ax, [bp+4]

Direccionamiento Indirecto con Base (BX) e Indice (SI)

BX+SI+XX

DS

MOV [bx+si-2], cx

Direccionamiento Indirecto con Base (BX) e Indice (DI)

BX+DI+XX

DS

MOV dx, [bx+di]

Direccionamiento Indirecto con Base (BP) e Indice (SI)

BP+SI+XX

SS

MOV ds, [bp+si]

Direccionamiento Indirecto con Base (BP) e Indice (DI)

BP+DI+XX

SS

MOV ax, [bp+di]  

Puede apreciarse que todos los modos admiten que después de obtener el valor de desplazamiento de un registro o de la suma de dos, se añada una constante a éste, antes de generar la lectura, indicada por XX. Si se omite el valor XX se generan instrucciones que no añaden ningún valor al desplazamiento obtenido por los registros.

Hemos visto que cada modo usa un registro de segmento por defecto para componer la dirección completa pero siempre es posible que le CPU use, no el registro de segmento por defecto, sino uno especificado por nosotros.

A nivel de lenguaje máquina lo que se hace es añadir a la instrucción un prefijo de 1 byte que modifica el comportamiento de la siguiente instrucción haciendo que use el registro de segmento correspondiente al prefijo en lugar del registro por defecto.

Hay 4 prefijos distintos, uno para cada registro de segmento y se denominan Prefijos de Segmento por convenio se añade el prefijo inmediato antes de la apertura de corchetes o después de PTR, si este aparece. Así las siguientes instrucciones acceden a posición de memoria dentro del segmento de código de datos extra y segmento de pila, respectivamente.

MOV al, cs:[bx+4]

MOV word ptr ds:[bp-0fh], 0

MOV es:[di], al

MOV word ptr ss:[bx], 0

Es interesante tener en cuenta que por ejemplo:  

MOV [bx], ax  y  MOV ds:[bx], ax   son equivalentes. Ya que si no se indica nada el registro por defecto es DS. También es interesante resaltar que para acceder a una posición de un vector, que haya sido previamente definido en el segmento de datos, usamos los corchetes.

Segmento de datos...

tabla word 100 dup (0) ; Vector de 100 posición, cada posición sería de 1 palabra con valor inicial 0.

Segmento de código...

MOV ax, tabla[si]                       ; Donde SI actúa como índice del vector.

MOV bx, 0           ; Esto sería equivalente

MOV ax, tabla[5]                        ; todas las sentencias pasarían al registro AX

MOV ax, tabla+5                        ; el valor de la posición 5 de la tabla pasa AX.

MOV ax, tabla[bx]+5

MOV ax, tabla[bx][di]                 ; Todas estas instrucciones también son equivalentes

MOV ax, tabla[di][bx]                 ; todas las sentencias mueven la posición

MOV ax, tabla[bx+di]                ; indicada por BX+DI dentro de la tabla a AX.

MOV ax, [tabla+bx+di]

MOV ax, [bx][di]+tabla

Constantes.

Una constante entera es una serie de uno o más números seguidos de una base opcional especificada por una letra. 

MOV ax, 25    MOV ax, 0b3h.

Los números 25 y 0b3 son constantes enteras. La h indica la base hexadecimal. Los distintos tipos de base...

"b"  o  "y"

Binario: 'b' si la base es menor o igual que 10

"o"  o  "q"

Octal

"d"  o  "t"

Decimal: 'd' si la base es menor o igual que 10

"h"        

Hexadecimal

Pueden indicarse en mayúsculas o minúsculas. Si no se indica, el ensamblador la interpreta directamente con la base actual. Por defecto es la decimal, pero puede cambiarse con la sentencia RADIX...

radix 16    ; base=16 (hexadecimal)

db 11       ; se interpreta como valor 11h=17

db 11t         ; se interpreta como valor 11 (en decimal) =11

db 01at    ; genera un error, por que a no es un dígito decimal

     

radix 2         ; base=2 (binaria)

db 11       ; se interpreta como el valor 11 (binario) =3

radix 10    ; base=10 (decimal)

db11           ; se interpreta como el valor 11d=11

Los números hexadecimales siempre deben comenzar con un dígito del 0 al 9. Si no es así y comienzan por alguna letra hay que añadir un 0 al principio para distinguir entre símbolo hexadecimal y etiqueta.

abch  V.S.  0abch     abch es interpretado como una etiqueta y 0abch como un número hexadecimal

Los dígitos hexadecimales desde A a F pueden ser mayúsculas y minúsculas. Se pueden definir constantes enteras simbólicas por algunas de las siguientes asignaciones de datos o con EQU (o con el signo "=").

EQU.- Tiene como función la de asignar un nombre simbólico a valor de una expresión.

El formato es: nombre EQU expresión. La utilidad de esta directiva reside en hacer más clara y legible las sentencias de un programa fuente realizado en ensamblador. Al contrario que en la directiva "=", el nombre no puede redefinirse, es decir permanece invariable la expresión asociada a lo largo de todo el programa fuente (al intentar redefinir crea un error).

"Expresión" puede ser una constante numérica, una referencia de direcciones, cualquier combinación de símbolos y operaciones que pueda evaluarse como un valor numérico u otro nombre simbólico. Si un valor constante, o sea un nombre, usado en numerosos lugares del código fuente necesita ser cambiado se debe modificar la expresión en un lugar  solo, en vez de por todas las partes del código fuente.

Ejemplo:

col EQU 80    ; columna de una pantalla (col=80)

fil EQU 25      ; fila de una pantalla (fil=25)

pantalla EQU col*fil ; tamaño de una pantalla (2000)

línea EQU fil     

longitud dw 0    ; variable tipo palabra

byte EQU ptr longitud         ; byte=primer byte de longitud

cr EQU 13      ; retorno de carro

cf EQU 10      ; principio de línea

Por defecto, el tamaño de palabra para expresiones de MASM 6.0 es de 32 bits. Se puede modificar con:

 

   OPTION EXPRE 32           ; es erróneo cambiar el tamaño de palabra una vez ha sido fijada

 

   OPTION EXPRE 16           ; la dos últimas usan el tamaño fijo de palabra de 16 bits

 

   OPTION M510                     ;  opción para operaciones muy específicas del ensamblador

Operadores.

Un operador es un modificador que se usa en l campo de operandos de una sentencia en ensamblador. Se puede usar varios operadores con instrucciones del procesador.   MOV ax, [bx+2]    La palabra reservada "MOV" es una instrucción y el signo "+" es un operador. Entre los tipos de operadores hay:

 

-  Operador Aritmético, opera sobre valores numéricos.

 

-  Operador Lógico, opera sobre valores binarios bit a bit.

 

-  Operador Relacional, compara 2 valores numéricos o 2 direcciones de memoria del mismo segmento y produce  como resultado:   0  si la relación es falsa, 0ffffh  si es verdadera.

-  Operador de Atributos, permite redefinir el atributo de una variable o etiqueta. Los atributos para variables de memoria pueden ser:        

byte (1 byte)

sbyte (byte con signo)

word (palabra)        

sword (palabra con signo)

dword (doble palabra)

sdword  (doble palabra con signo)

fword (6 bytes)                   

qword (8 bytes)

tbyte (10 bytes)

Los atributos para etiquetas pueden ser:

near    cuando se puede referenciar desde dentro del segmento donde está definida la etiqueta.

far    cuando se puede referenciar desde fuera del segmento donde está definida la etiqueta.

El ensamblador evalúa expresiones que contienen más de un operando según las siguientes reglas:

1ª   Siempre se ejecutan antes las operaciones entre paréntesis que las adyacentes.

2ª   Se ejecutan primero las operaciones binarias de más prioridad.

3ª   Las operaciones de igual prioridad se ejecutan de izquierda a derecha.

4ª   Operaciones unarias de igual prioridad se ejecutan de derecha a izquierda.

El orden de prioridad de todos los operadores está en la tabla:

Prioridad

Operador

1

( )    [ ]

2

LENGHT   SIZE   WIDTH   MASK

3

   (referencia un campo de un estructura)

4

:   (usado en prefijos de segmento)

5

CROOFFSET   OFFSET   SEG   THIS   TYPE

6

HIGH   HIGWORD   LOW   LOWWORD

7

+   -   (en operaciones unarias)

8

*   /   MOD   SHL   SHR

9

+   -   (en operaciones bianrias)

10

EQ   EN   LT   LE   GT   GE

11

NOT

12

AND

13

OR   XOR

14

OPATTR   SHRT   TYPE

INSTRUCCIONES

Instrucciones Aritméticas: ADD, ADC, SUB, SBB, MUL, IMUL, DIV, IDIV, INC, DEC

* ADD:  Realiza la suma de dos operandos identificándolos como origen y destino, quedando el resultado de la suma en el operando destino (ADD destino, origen). Los dos operandos deben ser del mismo tipo.

Ejemplo:           ADD ax, bx

ADD si,  di

ADD [0], ax

ADD ah, [bx]

ADD byte ptr[di-2], 2

MOV ebx, 43981

ADD eax, ebx

* ADC:  Se utiliza para realizar una suma de 32 bits con registros de 16 bits. La suma se realizaría igual, pero operando sobre 32 bits. En realidad, podemos descomponer una suma de 32 bits en dos sumas de 16 bits. Primero, deberíamos sumar los 16 bits de menor peso de cada operando,  almacenando los 16 bits resultantes como palabras baja del resultado. Después, deberíamos sumar los 16 bits de mayor peso de cada operando, pero además deberíamos sumar el acarreo del último bit de la palabras de menor peso. Así, llevamos efectivamente el acarreo del bit 15 de los operandos al bit 16 (esto se realiza utilizando el flag de acarreo CF).

Así, en el siguiente ejemplo, se le sumaría a el valor de 32 bits contenido en DXAX, el valor de 32 bits contenido en CXBX.

cx    bx

   +

dx    ax

dx    ax

ax=ax+bx

si cf=1 (si hay acarreo), dx=dx+cx+1

sino dx=dx+cx

Ejemplo:

ADD  ax, bx  ; Suma los 16 bits más bajos, dejando el acarreo(si se produce) en CF

; (Flag de Acarreo) preparado para sumárselo a los 16 bits más altos.

ADC dx, cx ; Suma los 16 bits más alto, y a ese resultado se le suma el acarreo (si existe) producido por la suma de bx + ax. El resultado de la suma queda en  ax (la parte baja) y en dx (la parte alta).

Nota:   La utilización de el Flag de acarreo (CF) puede producir a veces algún problema. Si fuese así, una solución sería que, después de ejecutar alguna operación que utilice este flag, ejecutar la  instrucción CLC (Borra la bandera de acarreo (CF) sin afectar a ninguna otra bandera).

* SUB:  Realiza la operación de resta de un operando origen sobre un operando destino. El resultado queda almacenado en el operando destino...

Formato SUB destino, origen; (destino = destino - origen).

Ejemplo:

SUB cl, dl      ; En Cl se almacena el valor resultante de CL - DL.

SUB es:[bx], dx      ; En la posición de memoria indicada, se almacena el valor

; resultante de restarle a la dirección indicada DX.

SUB al, [bp+4]

* SBB:   Se utiliza para realizar una resta de 32 bits utilizando registros de 16 bits. El formato es el mismo que con ACD; debemos, descomponer los operandos en fragmentos de 16 bits y comenzar a restar por la derecha. En cada resta después de la primera, debemos calcular la resta y del resultado restar el contenido del flag de acarreo (en las restas el acarreo se representa mediante acarreo negativo). Así, en el siguiente ejemplo se le restaría a un valor de 32 bits compuesto por DXAX, un valor de 32 bits compuesto por CXBX.

dx    ax

    -

cx    bx

dx    ax

ax=ax-bx

si CF=-1 (si hay acarreo) entonces DX=DX-CX-1

sino DX=DX-CX

Ejemplo:

SUB ax, bx ; Resta los 16 bits más bajos, deja el acarreo preparado para restar                                                                   ; los 16 bits más alto.

SBB dx, cx ; Resta los 16 bits más altos y además resta el acarreo dejado por                                                                        ; la anterior instrucción.

; Resultado de 32 bits en DX(palabras alta) y AX (palabras baja).

* MUL:  Formato MUL fuente.

Multiplica, sin considerar el signo, el acumulador (Al si el operando fuente es un byte, AX si el operando fuente es un número de 16 bits o EAX si el operando fuente es un número de 32 bits) por el operando fuente. Si el operando fuente es de tipo byte, el resultado se almacena en AX. Si el operando fuente es de tipo palabra, el resultado se almacena en AX (palabra inferior) y DX (palabra superior).

Si el operando fuente es de tipo doble palabra, el resultado se almacena en EAX (doble palabra inferior) y EDX (doble palabra superior).

Si la mitad superior del resultado (AH para el caso de operando tipo byte, DX para el caso operando tipo palabra o EDX para el caso de operando tipo doble palabra) no es cero, se activan las banderas CF y OF, indicando que esta mitad superior contiene dígitos significativos del resultado.

(fuente tipo byte) * AL = AHAL (AX) (AH parte más alta y AL parte más baja)

(fuente tipo palabra) * AX = DXAX (DX parte más alta y AX parte más baja)

(fuente tipo doble palabra) * EAX = EDXEAX (EDX parte más alta y EAX parte más baja)

Ejemplo:

MOV al, 10 ; Movemos a AL 10.

MOV bl, 12 ; Movemos a BL 12.

MUL bl    ; Fuente de tipo byte; el resultado queda en AX (AX=AL*BL).

;La parte más alta queda en AH y la más baja en AL

MOV ax, 20

MOV bx, 5

MUL bx ; Fuente de tipo palabra.

; El resultado queda en DXAX (DXAX=AX*BX).

; La parte alta queda en DX y la más baja en AX.

MOV eax, 5

MOV ebx, 2

MUL ebx  ; Fuente de tipo doble palabra; el resultado queda en

; EDXEAX (EDXEAX=EAX*EBX). La parte alta queda en EDX

; y la más baja en EAX

* IMUL:  Realiza la misma operación que MUL, solo que en este caso se contempla el signo.

* DIV:  Formato DIV fuente.

Divide, sin considerar el signo, el acumulador (AX (dividendo) si el operando fuente (divisor) es un byte, DXAX (dividendo) si el operando fuente (divisor) es un número de 16 bits o EDXEAX (dividendo) si el operando fuente (divisor) es un número de 32 bits) por el operando fuente.

Si el operando fuente es de tipo byte el cociente se almacena el AL y el resto se almacena en AH.

AX / fuente = AL (resto en AH)

Si el operando fuente es de tipo palabra, el cociente se almacena en AX y el resto se almacena en DX.                 

DXAX / fuente =  AX  (Resto en DX)

Si el operando fuente es de tipo doble palabra, el cociente se almacena en EAX y el resto en EDX.    

EDXEAX / fuente   =  EAX  (Resto en EDX)                                                                                                  

Ejemplo:

MOV ax, 12   ; Movemos a AX 12.

MOV bl, 10 ; Movemos a BL 10.

DIV bl      ; fuente de tipo byte.

; el cociente queda en AL (AL=1), y el resto queda en AH(AH=2).

MOV ax, es:[si]

MOV bx, es:[si+2]   ; Movemos en DXAX un valor almacenado en memoria,

; por ejemplo, 123567.

MOV bx, 65000

DIV BX    ; Fuente de tipo palabra; el cociente queda en AX y el resto

; queda almacenado en DX.

MOV eax, es:[si]

MOV ebx, es:[si+4] ; Movemos a EDXEAX un valor almacenado en memoria.

MOV ebx, 50000

DIV ebx         ; Fuente de tipo doble palabra; el cociente queda en EAX y                                                                               ; el resto queda almacenado en EDX.

* IDIV: Realiza la misma operación que DIV, sólo que en este caso se contempla el signo.

* INC: Se utiliza para incrementar el contenido de un registro o de una posición de memoria.

Ejemplo:

MOV ax, 5     ; a AX se le pasa el valor 5.

INC ax        ; AX incrementa en una unidad su valor (AX=6).

INC byte ptr[bp+si]  ; EL byte al que apunta la suma de "BP + SI" en la memoria

; se ve incrementado en una unidad.

INC word ptr[bp+si] ; Lo mismo pero para una palabra.

* DEC:   Se utiliza para decrementar el contenido de un registro o de una posición de memoria.

Ejemplo:

MOV ax, 5     ; a AX se le pasa el valor 5

DEC ax      ; AX decrementado en una unidad su valor (AX=4)

DEC byte ptr[bp+si]   ; El byte al que apunta la suma de "BP+SI" en la memoria

; se ve decrementado en una unidad.

DEC word ptr[bp+si]  ; Lo mismo pero para una palabra.

Instrucciones Lógicas: NEG, NOT, AND, OR, XOR

* NEG:   Esta instrucción lo que hace es calcular el complemento a dos del operando, y almacenando en el mismo lugar. Esto es, efectivamente, equivalente a cambiar de signo el operando de la instrucción.

Ejemplo:

MOV ax, 5        ; a AX se le pasa el valor 5.

NEG ax         ; Se haya el complemento a 2 de AX y se guarda en AX (AX= -5).

NEG byte ptr es:[bx+si+2]; Se haya el complemento a 2 de la posición de memoria

; (dentro del Segmento Extra) indicada por el de "BX+SI+2"

* NOT:   Se realiza el NOT lógico del operando bit a bit. El NOT lógico bit a bit consiste en invertir cada bit del operando (pasar los 0 a 1 y los 1 a 0; 10100 -> 01011)

Ejemplo:

NOT si        ; El valor que tenga SI pasa los 0 a 1 y los 1 a 0.

NOT word ptr es:[0] ; Lo mismo pero en una posición de memoria.

* AND:   Operación "y lógico" a nivel de bit entre los dos operandos. El resultado se almacena en el destino.

Formato AND destino, fuente.

0  0 - 0

0  1 - 0

1  0 - 0

1  1 - 1

Ejemplo:

AND ax, bx ; AND lógico entre AX y BX. El resultado queda en AX.

AND es:[0], dx  ; Lo mismo pero con posiciones de memoria.

AND di, es:[si]

AND byte ptr[9], 3   ; Lo mismo pero con valores inmediatos.

* OR:   Operación "o lógico exclusivo" a nivel entre los dos operandos. El resultado se almacena en el destino.

               Formato OR destino, fuente.

0  0 - 0

0  1 - 1

1  0 - 1

1  1 - 1

Ejemplo:

OR al, ah    ; Las mismas operaciones que con AND pero utilizando el OR.

OR [di], ch

OR cl, [bp+4]

OR byte ptr es:[si], 1

 

* XOR:   Operación "o lógico exclusivo" a nivel de bit entre los dos operandos. El resultado se almacena en destino.

Formato XOR destino, fuente.

0  0 - 0

0  1 - 1

1  0 - 1

1  1 - 0

Ejemplo:

XOR ax, ax ; El XOR entre dos bits con el mismo valor es siempre 0,

; independientemente del valor previo de AX (AX=0).

; Las ventajas de hacerlo así son dos: la ejecución de XOR reg, reg es más

; rápida que la de MOV reg, o que la de MOV ax,0 , y la codificación de la ; primera ocupa menos bytes que la segunda; Esta técnica no puede utilizar  ; se para poner a cero los registros de segmento.

XOR byte ptr[55aah], 4

XOR al, 00aah 

* XCHG:   Intercambia el contenido entre dos operandos. No pueden utilizarse registros de segmento como operandos.

Ejemplo:

XCHG si, di       ; Si SI tiene valor 45 y DI tiene valor 68, ahora, DI se queda con

; valor 45 y SI con 68.

XCHG al, [bx+4]

XCHG ss:[si], bx

* CMP:  Formato CMP destino, origen. (destino - origen) Esta instrucción realiza una resta de un operando origen sobre un operando destino, pero con la particularidad de no almacenar el resultado y no modificar ninguno de los 2 operandos, pero si se modifican los bits de indicadores (Flags). Los operandos deben ser del mismo tipo.

Esta modificación de los bits de indicadores, nos permitirá posteriormente, mediante la inspección de los mismos, poder realizar determinadas acciones. Normalmente después de una instrucción de comparación (CMP), hay una instrucción de salto.

Ejemplo:

CMP ax, bx   ; Comparamos AX con BX

JL menor ; Si AX es menor que BX saltamos a la etiqueta MENOR

 MENOR: 

CMP bl, cl

CMP bx, cx

CMP bl, byte ptr es:[si]

CMP word ptr es[si], bx

CMP bx, 30

CMP byte ptr es:[si], 01h          ; Normalmente, después de cada instrucción de

;comparación, viene una instrucción de salto.

         Parte 1 Parte 2 Parte 3 Parte 4

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