Ensamblador I

Name:
Location: Tijuana, Baja California N., Mexico

Soy un estudiante de Informatica en el TECNOLOGICO DE TIJUANA, y que trato de terminar mi carrera para poder hacer un profecionista exitoso. Pero lo mas Importante trato de ser un buen amigo aunque aveces me paso con la carrilla.

Google

Tuesday, January 31, 2006

Ejemplo 3: invertir cadena

.model small
.stack
.data
mensaje db 10,13, 'CLASE DE ENSAMBLADOR$'
mensaje1 db 10,13,'introduce cadena:$'
cv db 16 dup('$')
cvi db 16 dup('$')

.code
inicio:

mov ax,@data
mov ds,ax
mov es,ax

;desplegar mensages
mov ah,09h
mov dx,offset mensaje
int 21h

;cadena
mov ah,09h
mov dx,offset mensaje1
int 21h

;captura de cadena
mov ah,0ah
mov dx, offset cv
int 21h
cld

mov cx,16
lea si,cv

invertir:
lodsb
mov [di],al
dec di
loop invertir

mov di,cvi

;Imprimir cadena original
mov ah,09h
lea dx,cv
int 21h

;Imprimir cadena invertida
mov ah,09h
lea dx,cvi
int 21h

mov ah,4ch
int 21h
end

Ejemplo 2

;Lenguaje Ensamblador I
;practica 1 v3
;t2u2
;programa que despliega tres mensajes, captura un caracter y una cadena
;para despues imprimirlas

.model small
.stack
.data
mensaje db 10,13, 'CLASE DE ENSAMBLADOR$'
mensaje1 db 10,13,'introduce cadena:$'
mensaje2 db 10,13,'introduce caracter:$'
mensaje5 db 10,13,'Posicion:$'
mensaje6 db 10,13,'Numero de veces a insertar:$'
c_v db '$'
c db '$'
p db 0
n db 0

.code
inicio:

mov ax,@data
mov ds,ax

;desplegar mensages
mov ah,09h
mov dx,offset mensaje
int 21h

;cadena
mov ah,09h
mov dx,offset mensaje1
int 21h

;captura de cadena
mov ah,0ah
mov dx, offset c_v
int 21h


;caracter
mov ah,09h
mov dx,offset mensaje2
int 21h

;captura de caracter
mov ah,0ah
mov dx, offset c
int 21h

;caracter
mov ah,09h
mov dx,offset mensaje5
int 21h

;captura de caracter
mov ah,0ah
mov dx, offset p
int 21h

;caracter
mov ah,09h
mov dx,offset mensaje6
int 21h

;captura de caracter
mov ah,0ah
mov dx, offset n
int 21h

;busqueda de posicion en cadena,para insercion de caracter
mov al,c
lea di,c_v
add di,p
stosb

;desplegar cadena modificada
mov ah,09h
mov dx,offset c_v
int 21h

mov ah,4ch
int 21h
end

Sunday, November 13, 2005

Ejemplo 1

;Josafat Garcia Corral
;Lenguaje Ensamblador I
;practica 1 v3
;t2u2
;programa que despliega tres mensajes, captura un caracter y una cadena
;para despues imprimirlas

.model small
.stack
.data
mensaje db 10,13, 'CLASE DE ENSAMBLADOR$'
mensaje1 db 10,13,'introduce cadena:$'
mensaje2 db 10,13,'introduce caracter:$'
c_v db '$'
c db '$'

.code
inicio:

mov ax,@data
mov ds,ax

;desplegar mensages
mov ah,09h
mov dx,offset mensaje
int 21h

;cadena
mov ah,09h
mov dx,offset mensaje1
int 21h

;captura de cadena
mov ah,0ah
mov dx, offset c_v
mov c_v[0],8
int 21h


;caracter
mov ah,09h
mov dx,offset mensaje2
int 21h

;captura de caracter
mov ah,01h
int 21h

;despliegue de caracter
mov ah,09h
mov dx,offset c
int 21h

;despliegue de cadena
mov ah,0ah
mov dx, offset c_v
int 21h

mov ah,4ch
int 21h
end

Monday, October 31, 2005

COMENTARIO

AMIGOS MIO NO SEA FLOJOS Y ENTREN A CLASE NO ESTA DIFICIL ESTA RE FACIL ASIQ UE NO SEAN WEBAS.

Thursday, September 08, 2005

9. Programación híbrida


Pascal y ensamblador
Como ya se mencionó, la programación en lenguaje ensamblador proporciona un mayor control sobre el hardware de la computadora, pero también dificulta la buena estructuración de los programas.
La programación híbrida proporciona un mecanismo por medio del cual podemos aprovechar las ventajas del lenguaje ensamblador y los lenguajes de alto nivel, todo esto con el fin escribir programas más rápidos y eficientes.
En esta sección se mostrará la forma para crear programas híbridos utilizando el lenguaje ensamblador y Turbo Pascal.
Turbo Pascal permite escribir procedimientos y Funciones en código ensamblador e incluirlas como parte de los programas en lenguaje Pascal; para esto, Turbo Pascal cuenta con dos palabras reservadas: Assembler y Asm.
Assembler permite indicarle a Turbo Pascal que la rutina o procedimiento que se está escribiendo está totalmente escrita en código ensamblador.
Ejemplo de un procedimiento híbrido:
Procedure Limpia_Pantalla;
Assembler;
Asm
Mov AX,0600h
Mov BH,18h
Mov CX,0000h
Mov DX,184Fh
Int 10h
End;

El procedimiento del listado 23 utiliza la función 06h de la Int 10h del BIOS para limpiar la pantalla, este procedimiento es análogo al procedimiento ClrScr de la unidad CRT de Turbo Pascal.
Por otro lado, Asm nos permite incluir bloques de instrucciones en lenguaje ensamblador en cualquier parte del programa sin necesidad de escribir procedimientos completos en ensamblador.
Ejemplo de un programa con un bloque de instrucciones en ensamblador:
{ Este programa muestra como se construye un programa híbrido utilizando un bloque Asm... End; en Turbo Pascal.
El programa solicita que se introduzcan dos número, después calcula la suma por medio de la instrucción Add de
ensamblador y finalmente imprime el resultado en la pantalla.
}
Program hibrido;
Uses Crt;
Var
N1,N2,Res : integer;
Begin
Writeln("Introduce un número: ");
Readln(N1);
Writeln("Introduce un número: ");
Readln(N2);
Asm
Mov AX,N1;
Add AX,N2;
Mov Res,AX
End;
Writeln("El resultado de la suma es: ",Res);
Readln;
End.

El programa del listado 24 realiza la suma de dos cantidades enteras (N1 y N2) introducidas previamente por el usuario, después almacena el resultado en la variable Res y finalmente presenta el resultado en la pantalla.
El lenguaje ensamblador no cuenta con funciones de entrada y salida formateada, por lo cual es muy complicado escribir programas que sean interactivos, es decir, programas que soliciten informacion o datos al usuario. Es aquí donde podemos explotar la facilidad de la programación híbrida, en el programa anterior se utilizan las funciones Readln y Writeln para obtener y presentar información al usuario y dejamos los cálculos para las rutinas en ensamblador.
En el siguiente listado nos muestra la forma de escribir programas completos utilizando procedimientos híbridos.
{Este programa solicita al usuario que presione alguna tecla, cuando la tecla es presionada, ésta se utiliza para rellenar la pantalla.
El programa termina cuando se presiona la tecla enter.
El programa utiliza tres procedimientos:
Limpia_Pantalla: Este se encarga de borrar la pantalla
Cursor_XY: Este procedimiento reemplaza al GotoXY de Pascal
Imprime_Car: Este procedimiento imprime en pantalla el carácter que se le pasa como parámetro. }
Program Hibrido2;
Uses Crt;
Var
Car: Char;
i,j : integer;
{Este procedimiento limpia la pantalla y pone blanco sobre azul}
Procedure Limpia_Pantalla;
Assembler;
Asm
Mov AX,0600h
Mov Bh,17h
Mov CX,0000h
Mov DX,184Fh
Int 10h
End;
{Este procedimiento imprime el carácter en la pantalla}
Procedure Imprime_Car(C: Char);
Assembler;
Asm
Mov Ah,02h
Mov Dl,C
Int 21h
End;
{Este procedimiento tiene la misma función que el procedimiento GotoXY de Turbo Pascal}
Procedure Cursor_XY(X,Y: Byte);
Assembler;
Asm
Mov Ah,02h
Mov Bh,00h
Mov Dh,Y
Mov Dl,X
Int 10h
End;
Begin
Limpia_Pantalla;
Repeat
Limpia_Pantalla;
Cursor_XY(0,0);
Write('Introduce un carácter: ');
Car:=ReadKey;
Imprime_Car(Car);
Limpia_Pantalla;
If car <> #13 then
Begin
For i:=0 to 24 do
For j:=0 to 79 do
Begin
Cursor_XY(j,i);
Imprime_Car(Car);
End;
Cursor_XY(30,24);
Write('Presiona enter para salir u otro para seguir...');
Readln;
Until car = #13;
End.

8.5.BIBLIOTECAS DE MACROS.

Definir una macro y usarla solo una vez en un programa no es muy productivo. El enfoque habitual es catalogar las macros en una biblioteca en disco bajo un nombre descriptivo, como MACRO.LIB. Usted solo tiene que reunir todas las definiciones de sus macros en un archivo y almacenar el archivo en disco:

Macro1 MACRO
....
ENDM

Macro2 MACRO
....
ENDM


Para usar cualquiera de las macros catalogadas, en lugar de codificar las definiciones MACRO al inicio del programa utilice la directiva INCLUDE así:

INCLUDE C: MACRO.LIB
Macro1
Macro2


El ensamblador accesa el archivo llamado MACRO en la unidad C e incluye ambas definiciones de macro, Macro1 y Macro2, en el programa. El listado ensamblado contendrá una copia de las definiciones de las macros.

La Directiva PURGE.

La ejecución de una instrucción INCLUDE hace que el ensamblador incluya todas las definiciones de macros que están especificadas en la biblioteca. Sin embargo, suponga que una biblioteca contiene las macros SUMA, RESTA, DIVIDE, pero que el programa solo necesita SUMA. La directiva PURGE permite que usted "elimine" la macros RESTA y DIVIDE que no necesita del ensamblado actual:

IF1
INCLUDE C:\MACRO.LIB ;Incluye la biblioteca completa
ENDIF

PURGE RESTA, DIVIDE ;Elimina la macros no necesarias

Una operación PURGE facilita solo el ensamblado de un programa y no tiene efecto sobre las macros almacenadas en la biblioteca.

8.4. MANEJO DE ETIQUETAS LOCALES.

Algunas macros necesitan que se definan elementos de datos y etiquetas de instrucciones dentro de la definición de la macro. Si utiliza la macro mas de una vez en el mismo programa y el ensamblador define los elementos de datos para cada aparición, los nombres duplicados harían que el ensamblador genere un mensaje de error. Para asegurar que cada nombre generado es único, hay que codificar la directiva LOCAL inmediatamente después de la instrucción MACRO. Su formato general es:

LOCAL Etiqueta1, Etiqueta2...Etiquetan.

8.3. MANEJO DE PARAMETROS.

Para hacer una macro flexible, puede definir nombres en ella como argumentos mudos (ficticios).La definición de la macro siguiente, llamada DESPLEGAR_MSG, proporciona el uso de la función 09H del DOS para desplegar cualquier mensaje. Cuando se usa la macroinstrucción el programador tiene que proporcionar el nombre del mensaje, el cual hace referencia a un área de datos terminada por un signo de dólar.

DESPLEGAR_MSG MACRO MENSAJE ; Argumento mudo
MOV AH, 09H
LEA DX, MENSAJE
INT 21H
ENDM ; Fin de la macro

Un argumento mudo en una definición de macro indica al ensamblador que haga coincidir su nombre con cualquier aparición del mismo nombre en el cuerpo de la macro. Por ejemplo, el argumento mudo MENSAJE también aparece en la instrucción LEA.

Cuando utiliza la macroinstrucción DESPLEGAR_MSG, usted proporciona un parámetro como el nombre real del mensaje que será desplegado, por ejemplo:

DESPLEGAR_MSG MENSAJE2


En este caso, MENSAJE2 tiene que estar apropiadamente definido en el segmento de dato. El parámetro en la microinstrucción corresponde al argumento mudo en la definición original de la macro:

Definición de macro: DESPLEGAR_MSG MACRO MENSAJE (Argumento)
Macroinstruccin: DESPLEGAR_MSG MENSAJE2 (Parametro)

El ensamblador ya ha hecho corresponder el argumento en la definición original de la macro con la instrucción LEA en el cuerpo de la macro. Ahora sustituye el (los) parámetro(s) de la macroinstrucción MENSAJE2 por la presencia de MENSAJE en la instrucción LEA y la sustituye por cualquier otra aparición de MENSAJE.

Un argumento mudo puede contener cualquier nombre valido, incluyendo un nombre de registro tal como CX. Puede definir una macro con cualquier numero de argumentos mudos, separados por coma, hasta la columna 120 de una línea. El ensamblador sustituye los parámetros de la macro instrucción por los argumentos mudos en la definición de la macro, entrada por entrada, de izquierda a derecha.

8.2. DEFINICION DE UNA MACRO.

Una definición de macro aparece antes de que cualquier definición de segmento. Examinemos una definición de una macro sencilla que inicializa los registros de segmento para un programa.EXE:

INICIAREGS MACRO ;Define macro
MOV AX, @data ; } Cuerpo de
MOV DS, AX ; } la definición
MOV ES, AX ; } de la macro
ENDM ; Fin de la macro

El nombre de esta macro es INICIAREGS, aunque es aceptable cualquier otro nombre valido que sea único. La directiva MACRO en la primer línea indica al ensamblador que las instrucciones que siguen, hasta ENDM ("fin de la macro"), son parte de la definición de la macro. La directiva ENDM termina la definición de la macro.

Los nombres a que se hace referencia en la definición de la macro, @data, AX, DS y ES, deben estar definidos en alguna parte del programa o deben ser dados a conocer de alguna otra forma al ensamblador.

En forma subsecuente se puede usar la macro-instruccion INICIAREGS en el segmento de código en donde quiera inicializar los registros. Cuando el ensamblador encuentra la macra-instruccion INICIAREGS, busca en una tabla de instrucciones simbólicas y, a falta de una entrada, busca macroinstrucciones. Ya que el programa contiene una definición de la macro INICIAREGS, el ensamblador sustituye el cuerpo de la definición generando instrucciones: la expansión de la macro.

Un programa usaría la macroinstruccion INICIAREGS solo una vez, aunque otras macros están diseñadas para ser utilizadas cualquier numero de veces y cada vez el ensamblador genera la misma expansión.

8.1. INTRODUCCION.

Para cada instrucción simbólica que usted codifica, el ensamblador genera una instrucción de lenguaje de maquina. El ensamblador tiene facilidades que el programador puede utilizar para definir macros. Primero hay que definir un nombre especifico para la macro, junto con el conjunto de instrucciones en lenguaje ensamblador que la macro va a generar. Después, siempre que necesite codificar el conjunto de instrucciones, solo hay que codificar el nombre de la macro y el ensamblador genera de forma automática las instrucciones que han sido definidas en la macro.

Las macros son útiles para los siguientes propósitos:

  • Simplificar y reducir la cantidad de codificación repetitiva.
  • Reducir errores causados por la codificación repetitiva.
  • Linealizar un programa en lenguaje ensamblador para hacerlo mas legible.

Unidad VIII: Macros

8.1.- Introduccion
8.2.- Definicion de una Macro
8.3.- Manejo de Parametros
8.4.- Manejo de Etiquetas Locales
8.5.- Bibliotecas de Macros

7.2. LLAMADA DE PROCEDIMIENTOS.

Hasta ahora los segmentos de código han consistido solo en un procedimiento, codificado como:

BEGIN PROC FAR
.
.
.
BEGIN ENDP


En este caso el operador FAR informa al sistema que la dirección indicada es el punto de entrada para la ejecución del programa, mientras que la directiva ENDP define el final del procedimiento. Sin embargo, un segmento de código puede tener cualquier numero de procedimientos, todos distinguidos por PROC y ENDP. Un procedimiento llamado (o subrutina) es una sección de código que realiza una tarea definida y clara (tal como ubicar el cursor o bien obtener entrada del teclado).

La organización de un programa en procedimientos proporciona los beneficios siguientes:

1. Reduce la cantidad de código, ya que un procedimiento común puede ser llamado desde cualquier lugar en el segmento de código.

2. Fortalece la mejor organización del programa.

3. Facilita la depuración del programa, ya que los errores pueden ser aislados con mayor claridad.

4. Ayuda en el mantenimiento progresivo de programas, ya que los procedimientos son identificados de forma rápida para su modificación.

Operaciones CALL y RET

La instrucción CALL transfiere el control a un procedimiento llamado, y la instrucción RET regresa del procedimiento llamado al procedimiento original que hizo la llamada. RET debe ser la ultima instrucción en un procedimiento llamado. Los formatos generales para CALL y RET son:





El código objeto particular que CALL y RET generan depende de si la operación implica un procedimiento NEAR (cercano) o un procedimiento FAR (lejano).

Llamada y regreso cercanos. Una llamada (CALL) a un procedimiento dentro del mismo segmento es cercana y realiza lo siguiente:

  • Disminuye el SP en 2 (una palabra)
  • Mete el IP (que contiene el desplazamiento de la instrucción que sigue al CALL) en la pila.
  • Inserta la dirección del desplazamiento del procedimiento llamado en el IP (esta operación vacía el resultado de la instrucción previamente procesada),
Un RET que regresa desde un procedimiento cercano realiza lo siguiente:
  • Saca el antiguo valor de IP de la pila y lo envía al IP (lo cual también vacía el resultado de la instrucción previamente procesada).
  • Incrementa el SP en 2.
Ahora el CS:IP apunta a la instrucción que sigue al CALL original en la llamada del procedimiento, en donde se reasume la ejecución. Llamada y regreso lejanos. Una llamada (CALL) lejana llama a un procedimiento etiquetado con FAR, tal vez en un segmento de código separado. Un CALL lejano mete a la pila al CS y al IP, y RET los saca de la pila.
page 60,132
TITLE P08CALLP (EXE) Llamada a procedimientos
.MODEL SMALL
.STACK 64
.DATA
;---------------------------------------------------------------------
.CODE
BEGIN PROC FAR
CALL B10 ;Llama a B10
; ...
MOV AX,4C00H ;Salida a DOS
INT 21H
BEGIN ENDP
;---------------------------------------------------------------------
B10 PROC NEAR
CALL C10 ;Llama a C10
; ...
RET ;De regreso
B10 ENDP ;Quien llama
;---------------------------------------------------------------------
END BEGIN

7.1. DEFINICION.

El segmento de código contiene el código ejecutable de un programa. También tiene uno o mas procedimientos, definidos con la directiva PROC. Un segmento que tiene solo un procedimiento puede aparecer como sigue:

NOMBRE OPERACION OPERANDO COMENTARIO

nomsegmento SEGMENT PARA
nomproc PROC FAR ;Un
. ;procedimiento
. ;dentro
. ;del segmento
nomproc ENDP ;de código
nomsegmento ENDS

El nombre del procedimiento debe estar presente, ser único y seguir las reglas para la formación de nombres del lenguaje. El operando far en este caso esta relacionado con la ejecución del programa. Cuando usted solicita la ejecución de un programa, el cargador de programas del DOS utiliza este nombre de procedimiento como el punto de entrada para la primera instrucción a ejecutar.

La directiva ENDP indica el fin de un procedimiento y contiene el mismo nombre que el enunciado PROC para permitir que el ensamblador relacione a los dos. Ya que los procedimientos deben estar por completo dentro de un segmento, ENDP define el final de un procedimiento antes que ENDS defina el final de un segmento.

Unidad VII: Procedimientos




7.1.- Definicion
7.2.- Llamada

6.7. SALTOS CONDICIONALES E INCONDICIONALES.

Hasta este punto los programas que hemos examinado han sido ejecutados en forma lineal, esto es con una instrucción secuencialmente a continuación de otra. Sin embargo, rara vez un programa programable es tan sencillo. La mayoría de los programas constan de varios ciclos en los que una serie de pasos se repite hasta alcanzar un requisito especifico y varias pruebas para determinar que acción se realiza de entre varias posibles.

Requisitos como este implican la transferencia de control a la dirección de una instrucción que no sigue de inmediato de la que se esta ejecutando actualmente. Una transferencia de control puede ser hacia adelante, para ejecutar una serie de pasos nuevos, o hacia atrás, para volver a ejecutar los mismos pasos.

Ciertas instrucciones pueden transferir el control fuera del flujo secuencial normal añadiendo un valor de desplazamiento al IP.

Direcciones Corta, cercana y lejana

Una operación de salto alcanza una dirección corta por medio de un desplazamiento de un byte, limitado a una distancia de -128 a 127 bytes. Una operación de salto alcanza una dirección cercana por medio de un desplazamiento de una palabra, limitado a una distancia de -32, 768 a 32, 767 bytes dentro del mismo segmento. Una dirección lejana puede estar en otro segmento y es alcanzada por medio de una dirección de segmento y un desplazamiento; CALL es la instrucción normal para este propósito.

La tabla siguiente indica las reglas sobre distancias para la operaciones JMP, LOOP y CALL. Hay poca necesidad de memorizar estas reglas, ya que el uso normal de estas instrucciones en rara ocasión causa problemas.






Etiquetas de instrucciones

Las instrucciones JMP, Jnnn (salto condicional) y LOOP requieren un operando que se refiere a la etiqueta de una instrucción. El ejemplo siguiente salta a A90, que es una etiqueta dada a una instrucción MOV:

JMP A90
. . .
A90: MOV AH, 00
. . .


La etiqueta de una instrucción, tal como A90:, terminada con dos puntos (:) para darle atributo de cercana - esto es, la etiqueta esta dentro de un procedimiento en el mismo segmento de código.

Cuidado: Un error común es la omisión de los dos puntos. Note que una etiqueta de dirección en un operando de instrucción (como JMP A90) no tiene un carácter de dos puntos.

La instrucción JMP (Salto incondicional)

Una instrucción usada comúnmente para la transferencia de control es la instrucción JMP (jump, salto, bifurcación). Un salto es incondicional, ya que la operación transfiere el control bajo cualquier circunstancia. También JMP vacía el resultado de la instrucción previamente procesada; por lo que, un programa con muchas operaciones de salto puede perder velocidad de procesamiento. El formato general para JMP es:

| [etiqueta] | JMP | dirección corta, cercana o lejana |

Una operación JMP dentro del mismo segmento puede ser corta o cercana (o de manera técnica, lejana, si el destino es un procedimiento con el atributo FAR). En su primer paso por un programa fuente, el ensamblador genera la longitud de cada instrucción. Sin embargo, una instrucción JMP puede ser de dos o tres bytes de longitud. Una operación JMP a una etiqueta dentro de -128 a + 127 bytes es un salto corto.

El ensamblador genera un byte para la operación (EB) y un byte para el operando. El operando actúa como un valor de desplazamiento que la computadora suma al registro IP cuando se ejecuta el programa. El ensamblador ya puede haber encontrado el operando designado (un salto hacia atrás) dentro de -128 bytes, como en:

A50:
. . .
JMP A50


En este caso, el ensamblador genera una instrucción de maquina de dos bytes. Una JMP que excede -128 a 127 bytes se convierte en un salto cercano, para que el ensamblador genere un código de maquina diferente (E9) y un operando de dos bytes (procesadores 8088/8086) o un operando de cuatro bytes (procesadores 80386 y posteriores). En un salto hacia adelante, el ensamblador aun no ha encontrado el operando designado:

JMP A90
. . .
A90:


Ya que algunas versiones del ensamblador no saben en este punto si el salto es corto o cercano, generan de forma automática una instrucción de tres bytes.

Page 60,132
TITLE P08JUMP (COM) Uso de JMP para iterar
.MODEL SMALL
.CODE
ORG 100H
MAIN PROC NEAR
MOV AX,01 ;Iniciación de AX,
MOV BX,01 ;BX y
MOV CX,01 ;CX a 01
A20:
ADD AX, 01 ;Sumar 01 a AX
ADD BX, AX ;Sumar AX a BX
SHL CX, 1 ;Multiplicar por dos a CX
JMP A20 ;Saltar a la etiqueta A20
MAIN ENDP
END MAIN


La instrucción LOOP

La instrucción LOOP, requiere un valor inicial en el registro CX. En cada iteración, LOOP de forma automática disminuye 1 de CX. Si el valor en el CX es cero, el control pasa a la instrucción que sigue; si el valor en el CX no es cero, el control pasa a la dirección del operando. La distancia debe ser un salto corto, desde -128 hasta +127 bytes. Para una operación que exceda este limite, el ensamblador envía un mensaje como "salto relativo fuera de rango". El formato general de la instrucción LOOP es:

| [etiqueta:] | LOOP | dirección corta |

El siguiente programa muestra el funcionamiento de la instrucción LOOP.

Page 60,132
TITLE P08LOOP (COM) Ilustración de LOOP
.MODEL SMALL
.CODE
ORG 100H
MAIN PROC NEAR
MOV AX,01 ;Iniciación de AX,
MOV BX,01 ;BX y
MOV CX,01 ;CX a 01
MOV CX,10 ;Iniciar
A20: ;Número de iteraciones
ADD AX, 01 ;Sumar 01 a AX
ADD BX, AX ;Sumar AX a BX
SHL DX, 1 ;Multiplicar por dos a DX
LOOP A20 ;Iterar si es diferente de cero
MOV AX, 4C00H ;Salida a DOS
MAIN ENDP
END MAIN

Existen dos variaciones de la instrucción LOOP, ambas también decrementan el CX en 1. LOOPE/LOOPZ (repite el ciclo mientras sea igual o repite el ciclo mientras sea cero) continua el ciclo mientras que el valor en el CX es cero o la condición de cero esta establecida.

LOOPNE/LOOPNZ (repite el ciclo mientras no sea igual o repite el ciclo mientras sea cero) continua el ciclo mientras el valor en el CX no es cero o la condición de cero no esta establecida.

INSTRUCCIONES DE SALTO CONDICIONAL

El ensamblador permite usar una variedad de instrucciones de salto condicional que transfieren el control dependiendo de las configuraciones en el registro de banderas. Por ejemplo, puede comparar dos campos y después saltar de acuerdo con los valores de las banderas que la comparación establece. El formato general para el salto condicional es:

| [etiqueta:] | Jnnn | dirección corta |

Como ya se explico la instrucción LOOP disminuye el registro CX; si es diferente de cero, transfiere el control a la dirección del operando. podría reemplazar el enunciado LOOP A20 de la figura anterior con dos enunciados - uno que decremente el CX y otro que realice un salto condicional:

DEC CX ;Equivalente a LOOP
JNZ A20
. . .


DEC y JNZ realizan exactamente lo que hace LOOP. DEC decrementa en 1 CX y pone a 1 o a 0 la bandera de cero (ZF) en el registro de banderas. Después JNZ prueba la configuración de la bandera de cero; si el CX es diferente de cero, el control pasa a A20, y si el CX es cero el control pasa a la siguiente instrucción hacia abajo

Datos con signo y sin signo

Distinguir el propósito de los saltos condicionales debe clarificar su uso. El tipo de datos (sin signo o con signo) sobre los que se realizan las comparaciones o la aritmética puede determinar cual es la instrucción a utilizar. Un dato sin signo trata todos los bits como bits de datos; ejemplos típicos son las cadenas de caracteres, tal como nombres o direcciones, y valores numéricos tal como números de cliente. Un dato con signo trata el bit de mas a la izquierda como un signo, en donde 0 es positivo y 1 es negativo.

En el ejemplo siguiente, el AX contiene 11000110 y el BX contiene 00010110. La siguiente instrucción

CMP AX, BX


compara el contenido de AX con el contenido del BX. Para datos sin signo, el valor AX es mayor; sin embargo, para datos con signo el valor AX es menor a causa del signo negativo.

Saltos con base en datos sin signo

Las instrucciones siguientes de salto condicional se aplican a datos sin signo:





Cada una de estas pruebas las puede expresar en uno de dos códigos simbólicos de operación.

Saltos con base en datos con signo

Las instrucciones siguientes de salto condicional se aplican a datos con signo:






Pruebas aritméticas especiales

Las siguientes instrucciones de salto condicional tienen usos especiales:

No espere memorizar todas estas instrucciones; sin embargo, como recordatorio note que un salto para datos sin signo es igual, superior o inferior, mientras que un salto para datos con signo es igual, mayor que o menor. Los saltos que prueban banderas de acarreo, de desbordamiento y de paridad tienen propósitos únicos.

6.6. COMPARACION.

  • LA INSTRUCCION CMP
La instrucción CMP pro lo común es utilizada para comparar dos campos de datos, uno de los cuales están contenidos en un registro. El formato general para CMP es:

| [etiqueta:] | CMP | {registro/memoria}, {registro/memoria/inmediato} |

El resultado de una operación CMP afecta la banderas AF, CF, OF, PF, SF y ZF, aunque no tiene que probar estas banderas de forma individual. El código siguiente prueba el registro BX por un valor cero:

X CMP BX, 00 ;Compara Bx con cero
JZ B50 ;Si es cero salta aB50
. ;(Acción si es diferente de cero)
.
B50: ... ;Destino del salto, si BX es cero


Si el BX tiene cero, cmp establece ZF a 1 y puede o no cambiar la configuración de otras banderas. La instrucción JZ (salta si es cero) solo prueba la bandera ZF. Ya que ZF tiene 1 (que significa una condición cero), JZ transfiere el control (salta) a la dirección indicada por el operando B50.

Observe que la operación compara el primer operando con el segundo; por ejemplo, el valor del primer operando es mayor que, igual o menor que el valor del segundo operando?

  • LA INSTRUCCION CMPS
CMPS compara el contenido de una localidad de memoria (direccionada por DS:SI). Dependiendo de la bandera de dirección, CMPS incrementa o disminuye también los registros SI y DI en 1 para bytes, en 2 para palabras y en 4 para palabras dobles. La operación establece las banderas AF, CF, OF, PF, SF y ZF.

Cuando se combinan con un prefijo REP y una longitud en el CX, de manera sucesiva CMPS puede comparar cadenas de cualquier longitud.
Pero observe que CMPS proporciona una comparación alfanumérica, esto es, una comparación de acuerdo a con los valores ASCII. Considere la comparación de dos cadenas que contienen JEAN y JOAN. Una comparación de izquierda a derecha, tiene el resultado siguiente:

J:J Iguales
E:O Diferentes (E es menor)
A:A Iguales
N:N Iguales


Una comparación de los 4 bytes termina con una comparación de N con N (iguales). Ahora ya que los dos nombres no son idénticos, la operación debe terminar tan pronto como la comparación entre 2 caracteres sea diferente.

Algunas derivaciones de CMPS son las siguientes:

  • CMPSB. Compara bytes.
  • CMPSD. Compara palabras dobles.
  • CMPSW. Compara palabras.

A continuación se muestra la codificación del uso del CMPS y sus derivaciones:
TITLE P12CMPST (COM) Uso de CMPS para operaciones en cadenas
.MODEL SMALL
.CODE
ORG 100H
BEGIN: JMP SHORT MAIN
;-------------------------------------------------------------------------------------
NOM1 DB 'Assemblers' ;Elementos de datos
NOM2 DB 'Assemblers'
NOM3 DB 10 DUP (' ')
;-------------------------------------------------------------------------------------
MAIN PROC NEAR ;Procedimiento principal
CLD ;Izquierda a derecha
MOV CX, 10 ;Iniciar para 10 bytes
LEA DI, NOM2
LEA SI, NOM1
REPE CMPSB ;Compare NOM1:NOM2
JNE G20 ;No es igual, saltarlo
MOV BH,01 ;Igual, fijar BH

G20:
MOV CX, 10 ;Iniciar para 10 bytes
LEA DI, NOM3
LEA SI, NOM2
REPE CMPSB ;Compare NOM2:NOM3
JE G30 ;Igual, salir
MOV BL, 02 ;No es igual, fijar BL
G30:
MOV AX, 4C00H ;Salir a DOS
INT 21H
MAIN ENDP
END BEGIN

6.5. MULTIPLICACION Y DIVISION.

  • MULTIPLICACION


Para la multiplicación, la instrucción MUL maneja datos sin signo y la instrucción IMUL (multiplicación entera) maneja datos con signo. Ambas instrucciones afectan las banderas de acarreo y de desbordamiento. Como programador, usted tiene el control sobre el formato de los datos que procesa, y tiene la responsabilidad de seleccionar la instrucción de multiplicación apropiada. El formato general de MUL e IMUL es :

| [etiqueta:] | MUL/IMUL | registro/memoria |

Las operaciones de multiplicación básicas son byte a byte, palabra por palabra y palabras dobles por palabra dobles.

Byte por byte

Para multiplicar dos números de un byte, el multiplicando esta en el registro AL y el multiplicador es un byte en memoria o en otro registro. Para la instrucción MUL DL, la operación multiplica el contenido del AL por el contenido del DL. El producto generado esta en el registro AX. La operación ignora y borra cualquier información que pueda estar en el AH.




Palabra por palabra

Para multiplicar dos números de una palabra, el multiplicando esta en el registro AX y el multiplicador es una palabra en memoria o en otro registro. Para la instrucción MUL DX, la operación multiplica el contenido del AX por el contenido del DX. El producto generado es una palabra doble que necesita dos registros: la parte de orden alto (mas a la izquierda) en el DX y la parte de orden bajo (mas a la derecha) en el AX. La operación ignora y borra cualquier información que puede estar en el DX.

Palabra doble por palabra doble

Para multiplicar dos números de palabras dobles, el multiplicando esta en el registro EAX y el multiplicador es una palabra doble en memoria o en otro registro. El producto es generado en el par EDX:EAX. La operación ignora y borra cualquier información que ya este en el EDX.






En los ejemplos siguientes, el multiplicador esta en un registro, el cual especifica el tipo de operación:

INSTRUCCION MULTIPLICADOR MULTIPLICANDO PRODUCTO

MUL CL byte AL AX
MUL BX palabra AX DX:AX
MUL EBX palabra doble EAX EDX:EAX

En los ejemplos siguientes, los multiplicadores están definidos en memoria:

BYTE1 DB ?
WORD1 DW ?
DWORD1 DD ?

OPERACION MULTIPLICADOR MULTIPLIANDO PRODUCTO

MUL BYTE1 BYTE1 AL AX
MUL WORD1 WORD1 AX DX:AX
MUL DWORD1 DWORD1 EAX EDX:EAX

  • DIVISION
Para la división, la instrucción DIV (dividir) maneja datos sin signo y la IDIV (división entera) maneja datos con signo. Usted es responsable de seleccionar la instrucción apropiada. El formato general para DIV/IDIV es:

| [etiqueta:] | IDIV/DIV | {registro/memoria} |

Las operaciones de multiplicación básicas son byte entre byte, palabra entre palabra y palabras dobles entre palabra dobles.

Palabra entre palabra

Aquí el dividendo esta en el AX y el divisor es un byte en memoria o en otro registro. Después de la división, el residuo esta en el AH y el cociente esta en el AL. Ya que un cociente de un byte es muy pequeño -si es sin signo, un máximo de +255 (FFH) y con signo +127 (7FH)- esta operación tiene un uso limitado.






Palabra doble entre palabra

Para esta operación, el dividendo esta en el par DX:AX y el divisor es una palabra en memoria o en otro registro. Después de la división, el residuo esta en el DX y el cociente esta en el AX. El cociente de una palabra permite para datos sin signo un máximo de +32, 767 (FFFFH) y con signo +16, 383 (7FFFH). Tenemos:




Palabra cuádruple entre palabra doble

Al dividir una palabra cuádruple entre una palabra doble, el dividendo esta en el par EDX:EAX y el divisor esta en una palabra doble en memoria o en otro registro. Después de la división, el residuo esta en el EDX y el cociente en el AEX.


En los ejemplos siguientes, de DIV, los divisores están en un registro, que determina el tipo de operación:

OPERACION DIVISOR DIVIDENDO COCIENTE RESIDUO

DIV CL byte AX AL AH
DIV CX palabra DX:AX Ax DX
DIV EBX palabra doble EDX:EAX EAX EDX

En los ejemplos siguientes de DIV, los divisores están definidos en memoria:

BYTE1 DB ?
WORD1 DW ?
DWORD1 DD ?
... DIVISOR DIVIDENDO COCIENTE RESIDUO

DIV BYTE1 BYTE1 AX AL AH
DIV WORD1 WORD1 DX:AX AX DX
DIV DWORD1 DWORD1 EDX:EAX EAX EDX