Lenguaje ensamblador basico (capitulo 9 )

Ejemplos

Desplegar un mensaje en pantalla

Uno de los programas más sencillos, pero en cierta forma práctico, es uno que despliegue una cadena de caracteres en la pantalla. Eso es lo que hace el siguiente programa:

Programa :

; Primero definimos el modelo de memoria, en este caso small

.MODEL SMALL
.CODE ; Declaramos el área que contendrá el código
Inicio: ; Etiqueta de inicio del programa:
MOV AX,@DATA ; Vamos a colocar la dirección del segmento de datos

MOV DS,AX ; en DS, usando como intermediario a AX

MOV DX,OFFSET Cadena ; Colocamos en DX la dirección, dentro del

; segmento, de la cadena a desplegar

MOV AH,09 ; Utilizaremos la función 09 de la interrupción

INT 21H ; 21H para desplegar la cadena.

MOV AH,4CH ; Por medio de la función 4CH de la interrupción

INT 21H ; 21H terminaremos nuestro programa

.DATA ; Declaramos el semento de datos

Cadena DB 'Mensaje del programa.$' ; Cadena a desplegar

.STACK ; Declaramos la pila

END Inicio ; Final de nuestro programa

Ya se explicó en el tutorial un programa casi igual a este, por lo tanto no requiere ningún comentario adicional.

Cuando se crea un programa no es necesario escribir los comentarios que van despues de las comillas, sin embargo es una técnica recomendable para que en caso de errores o mejoras al código sea más sencillo encontrar la parte deseada.

Para ensamblar este programa primero se guarda en formato ASCII con un nombre válido, por ejemplo: program1.asm

Para ensamblarlo se utiliza el MASM, el comando de ensamble es: masm program1;

Para enlazarlo y hacerlo ejecutable tecleamos: link program1;

Una vez terminados estos pasos es posible ejecutarlo tecleando: program1 [Enter]

Para utilizar el programa directamente en su computadora guarde este archivo como ASCII o texto, llévelo a su PC, con algun editor elimine todos estos comentarios y los comentarios del principio y ensámblelo.

Desplegar números hexadecimales del 15 al 0

Este programa despliega los 16 caracteres correspondientes al código hexadecimal en orden descendente.

Programa:

; Inicio del programa, definimos el modelo de memoria a usar y el segmento

; de código

.MODEL SMALL ; Modelo de memoria

.CODE ; Area de código

Inicio: ; Etiqueta de inicio del programa

MOV AX,@DATA ; Inicializa el registro DS con la dirección dada

MOV DS,AX ; por @DATA (Segmento de datos).

MOV DX, OFFSET Titulo ; Obtiene la dirección de la cadena de caracteres

MOV AH,09 ; Usamos la función 09H de la interrupción 21H

INT 21H ; para desplegar la cadena cuya dirección obtuvimos.

MOV CX,16 ; Contador de caracteres que se mostrarán

MOV BX, OFFSET Cadena ; Permite acceso a la cadena donde se encuentran los

; valores a desplegar

Ciclo: ; Etiqueta para generar un ciclo

MOV AL,CL ; Coloca en AL el número a traducir y lo traduce

XLAT ; usando la instrucción XLAT

MOV DL,AL ; Coloca en DL el valor a ser desplegado por medio de la

MOV AH,02 ; función 2 de la interrupción 21H

INT 21H ; Despliega el caracter

MOV DL,10 ; Salta una linea desplegando el caracter 10

INT 21H ; Despliega el caracter

MOV DL,13 ; Produce un retorno de carro desplegando el caracter 13

INT 21H ; Despliega el retorno de carro

LOOP Ciclo ; Decrementa en uno a CX y brinca a la etiqueta Ciclo

; siempre y cuando CX no sea igual a cero

MOV AH,4C ; Utiliza la función 4C de la interrupción 21H para

INT 21H ; finalizar el programa

; Inicio del segmento de datos

.DATA ;Define el segmento de datos

Titulo DB 13,10,'Desplegar los números hexadecimales del 15 al 1'

DB 13,10,'$' ; Cadena a desplegar al inicio del programa

Cadena DB '0123456789ABCDEF' ; Cadena con los d'gitos hexadecimales

; Declaración del segmento de la pila

.STACK

END Inicio ;Declaración del final del programa

El comando XLAT busca la cadena o tabla localizada en BX, el registro AL contiene el número de bytes, a partir de la dirección de inicio, que se recorrerá el apuntador para buscar un dato, el contenido de AL es remplazado por el byte donde se encuentra el apuntador.

El proceso de ensamblado es igual al del ejemplo anterior.

Operaciones básicas

En el siguiente ejemplo se utilizan la mayor parte de las instrucciones vistas en el tutorial, su objetivo es realizar las operaciones de suma, resta, multiplicación o división de dos cantidades.

Para accesar a cada una de las opciones disponibles se hace uso de un menú en el que se presentan las operaciones disponibles.

Programa:

.MODEL SMALL ; Define el modelo de memoria

.DATA ; Define el segmentos de datos

ErrorCAP DB 0 ;Bandera de error en la captura de las cantidades

Cantidad DB 0 ;Cantidad sobre la que se opera. Si es 0 la cantidad

; será la 1, y si es 1 será la 2.

CantUnoR DW 0 ;Guardará la cantidad 1 convertida en binario

CantDosR DW 0 ;Guardará la cantidad 2 convertida en binario

CantUnoN DB 6,0,6 DUP(?) ;Variable que almacena la cantidad 1

CantDosN DB 6,0,6 DUP(?) ;Variable que almacena la cantidad 2

Funcion DB 0 ;Variable que almacena la opción a realizar

Resulta DB 13,10,'Resultado: $'

ResultaR DB 11 DUP(?)

Mensaje DB 13,10,'Operaciones básicas entre dos números'

DB 13,10,13,10,'$'

Pregunta DB 13,10,'Presione: ',13,10

DB ' 1 Multiplicación ',13,10

DB ' 2 División ',13,10

DB ' 3 Suma ',13,10

DB ' 4 Resta ',13,10

DB ' 5 Salir ',13,10,'$'

Error DB 7,13,10,'Selección inválida (1-5)',13,10,'$'

Error1 DB 7,13,10,'Cantidad 1 inválida. ',13,10,'$'

Error2 DB 7,13,10,'Cantidad 2 inválida. ',13,10,'$'

Error3 DB 7,13,10,'Cantidad fuera de rango (65535) ',13,10,'$'

Error4 DB 7,13,10,'Intento de división por cero. ',13,10,'$'

CantUnoM DB 13,10,'Introduzca la cantidad 1 (Menor a 65535): $'

CantDosM DB 13,10,'Introduzca la cantidad 2 (Menor a 65535): $'

; Tabla de potencias para conversión binaria/ASCII

Potencia DW 0001h, 000Ah, 0064h, 03E8h, 2710h

PotenciaF DW $

.CODE ;Define el área de código

Empieza: ;Etiqueta de inicio del programa

Mov AH, 0Fh ;Obtiene modo de video actual

Int 10h

Mov AH, 00 ;Cambia el modo de video al mismo anterior

Int 10h ; con la finalidad de que se borre la pantalla

Mov AX, @Data ;Obtiene la dirección del segmento de datos

Mov Ds, Ax ;Inicializa a DS con esa dirección

Mov Dx, Offset Mensaje ;Despliega el t'tulo del programa

Call Imprime ;Llama a un procedimiento

Mov Si, Offset ResultaR ;Inicializa la variable ResultaR

Add Si,11

Mov Al,'$'

Mov [Si], Al

OTRA:

Mov Dx,Offset Pregunta ;Despliega menú de opciones

Call Imprime

Call ObtenTecla ;Espera a que se presione la opción deseada

Cmp Al, 49 ;Compara la selección con el d'gito 1 ASCII

Jae SIGUE ;Si la opción es mayor a 1 brinca a SIGUE

Mov Dx, Offset Error ;Despliega mensaje de error

Call Imprime

Jmp OTRA ;Brinca a OTRA para volver a preguntar

SIGUE:

Cmp Al,53 ;Compara la selección con el d'gito 5 ASCII

Jbe TODOBIEN ;Si es menor a 5 brinca a TODOBIEN, sino continúa

Mov Dx, Offset Error ;Si la opción fué mayor a 5 despiega el error

Call Imprime

Jmp OTRA

TODOBIEN:

Cmp Al,53 ;Compara la seleción con el d'gito 5 ASCII

Jnz CHECATODO ;Si no es igual brinca a CHECATODO

Jmp FUNCION5 ;Si es igual brinca a FUNCION5 para terminar

CHECATODO:

Mov Funcion, Al ;Guarda el número de función a realizar

CAPCANT01:

Mov Dx, Offset CantUnoM ;Mensaje de captura de la cantidad 1

Call Imprime

Mov Ah, 0Ah ;Captura la cantidad (hasta 8 d'gitos)

Mov Dx, Offset CantUnoN

Int 21h

Mov ErrorCAP, 0 ;Supone que no hay errores y que se está

Mov Cantidad, 0 ; operando sobre la cantidad 1

Call ConvNUM ;Convierte cantidad 1 a binario

Cmp ErrorCAP, 1 ;Verifica si hubo error

Jz CAPCANT01 ;En caso afirmativo regresa a la captura.

Mov CantUnoR, Bx ;Guarda el resultado de la conversión

CAPCANT02:

Mov ErrorCAP, 0 ;Supone que no hay error

Mov Cantidad, 1 ;Indica a ConvNUM que se trabajará con cantidad 2

Mov Dx, Offset CantDosM ;Mensaje de captura de cantidad 2

Call Imprime

Mov Ah, 0Ah ;Captura de la cantidad 2

Mov Dx, Offset CantDosM

Int 21H

Call ConvNum ;Convierte la cantidad 2 a binario

Cmp ErrorCAP, 1 ;Verifica si existi— algun error

Jz, CAPCANT02 ;En caso afirmativo regresa a la captura

Mov CantDosR, Bx ;Almacena el valor binario de cantidad 2

;La siguiente parte es el proceso de selección de la operación

;Que se realizara:

Mov Al, Funcion ;Carga en Al la función que seleccion— el usuario

Cmp Al, 31h ;Revisa si es 1

Jne FUNCION2 ;Si no es brinca a FUNCION2

Call Multiplica ;Multiplica las cantidades

Jmp OTRA ;Regresa al menú principal

FUNCION2:

Cmp Al, 32h ;Revisa si es 2

Jne FUNCION3 ;Si no es brinca a FUNCION3

Call Divide ;Divide las cantidades

Jmp OTRA

FUNCION3:

Cmp Al, 33h ;Revisa si es 3

Jne FUNCION4 ;Si no es brinca a FUNCION4

Call Suma ;Suma las cantidades

Jmp OTRA

FUNCION4:

Cmp Al, 34h ;Revisa si es 4

Jne FUNCION5 ;Si no es brinca a FUNCION5

Call Resta ;Resta las cantidades

Jmp OTRA

FUNCION5:

Mov Ax, 4C00h ;Esta función termina la ejecución

Int 21h ;del programa

; Procedimientos o rutinas del programa

Multiplica Proc Near ;Indicador de inicio de procedimiento

Xor Dx, Dx ;Dx = 0

Mov Ax, CantUnoR ;Primera cantidad

Mov Bx, CantDosR ;Segunda cantidad

Mul Bx ;Multiplica

Call ConvASCII ;Convierte en ASCII

Mov Dx, Offset Resulta ;Imprime mensaje del resultado

Call Imprime

Mov Dx, Offset ResultaR ;Imprime resultado

Call Imprime

Ret ;Regresa al programa principal

Multiplica Endp ;Indicador de fin de procedimiento

Divide Proc Near

Mov Ax, CantUnoR ;Carga la cantidad 1 (dividendo)

Mov Bx, CantDosR ;Carga la cantidad 2 (divisor)

Cmp Bx, 0 ;Revisa que el divisor no sea cero

Jnz DIVIDE01 ;Si no es cero brinca a DIVIDE01

Mov Cantidad, 3 ;Hubo error asi que despliega el mensaje y regresa al

programa

Call HuboError

Ret

DIVIDE01:

Div Bx ;Efectúa la división

Xor Dx, Dx ;Dx = 0. El residuo no es utilizado

Call ConvASCII ;Convierte en ASCII el resultado

Mov Dx, Offset Resulta ;Despliega el mensaje del resultado

Call Imprime

Mov Dx, Offset ResultaR ;Depliega el resultado

Call Imprime

Ret

Divide Endp

Suma Proc Near

Xor Dx, Dx ;Dx = 0 por si acaso existe acarreo

Mov Ax, CantUnoR ;Cantidad 1

Mov Bx, CantDosR ;Cantidad 2

Add Ax, Bx ;Realiza la suma

Jnc SUMACONV ;Si no existi— acarreo brinca a SUMACONV

Adc Dx,0 ;Si existi—

SUMACONV:

Call ConvASCII ;Convierte en ASCII el resultado

Mov Dx, Offset Resulta ;Despliega el mensaje del resultado

Call Imprime

Mov Dx, Offset ResultaR ;Despliega el resultado

Call Imprime

Ret

Suma Endp

Resta Proc Near

Xor Dx, Dx ;Dx = 0 por si existe acarreo

Mov Ax, CantUnoR ;Ax = cantidad 1

Mov Bx, CantDosR ;Bx = cantidad 2

Sub Ax, Bx ;Realiza la resta

Jnc RESTACONV ;Si no hay acarreo brinca a RESTACONV

Sbb Dx,0 ;Si hay acarreo

RESTACONV:

Call ConvASCII ;Convierte en ASCII el resultado

Mov Dx, Offset Resulta ;Despliega el mensaje del resultado

Call Imprime

Mov Dx, Offset ResultaR ;Despliega el resultado

Call Imprime

Ret

Resta Endp

Imprime Proc Near

Mov Ah, 09 ;Utiliza la función 9 de la interrupción

Int 21h ;21h para desplegar una cadena

Ret

Imprime Endp

ObtenTecla Proc Near

Mov ah, 0 ;Utiliza la interrupción 16h para

Int 16h ; leer una tecla

Ret

ObtenTecla Endp

ConvNum Proc Near

Mov Dx, 0Ah ;Multiplicador es 10

Cmp Cantidad, 0 ;Verifica si es la cantidad 1

Jnz CONVNUM01 ;No fué, entonces es cantidad 2 y brinca

Mov Di, Offset CantUnoN + 1 ;Bytes leidos en la cantidad 1

Mov Cx, [Di]

Mov Si, Offset CantUnoN + 2 ;La cantidad 1

Jmp CONVNUM02

CONVNUM01:

Mov Di, Offset CantDosN + 1 ;Bytes leidos de la cantidad 2

Mov Cx, [Di]

Mov Si, Offset CantDosN + 2 ;La cantidad 2

CONVNUM02:

Xor Ch, Ch ;CH = 0

Mov Di, Offset Potencia ;Dirección de la tabla de potencias

Dec Si

Add Si, Cx

Xor Bx, Bx

Std

CONVNUM3:

Lodsb ;Carga en AL el byte cuya dirección es DS:SI

Cmp Al, 0 ;Compara el byte con el d'gito 0

Jb CONVNUM04 ;Si es menor es inválido y brinca

Cmp Al, 9 ;Compara el byte con el d'gito 9

Ja CONVNUM04 ;Si es mayor es inválido y brinca

Sub Al, 30h ;Convierte el d'gito de ASCII a binario

Cbw ;Convierte a palabra

Mov Dx, [Di] ;Obtiene la potencia a ser usada para multiplicar

Mul Dx ;Multiplica el número

Jc CONVNUM05 ;Si hay acarreo brinca (fué mayor a 65535)

Add Bx, Ax ;Suma el resultado a BX

Jc CONVNUM05 ;Si hay acarreo brinca

Add Di, 2 ;Va a la siguiente potencia de 10

Loop CONVNUM03 ;Brinca hasta que CX sea igual a 0

Jmp CONVNUM06

CONVNUM04:

Call HuboERROR ;Hubo algun error, depliega mensaje

Jmp CONVNUM06 ;Brinca a CONVNUM06

CONVNUM05:

Mov Cantidad, 2 ;Hubo acareo en la conversión, lo que

Call HuboERROR ; significa que la cantidad es mayor a 65535

CONVNUM06:

Cld ;Regresa la bandera de dirección a su estado

Ret ; normal

ConvNum Endp

ConvASCII Proc Near

Push Dx

Push Ax ;Guarda el resultado en la pila

Mov Si, Offset ResultaR ;Inicializa la variable ResultaR

Mov Cx, 10 ; llenandola con asteriscos

Mov Al, '*'

ConvASCII01:

Mov [Si], Al

Inc Si

Loop ConvASCII01

Pop Ax

Pop Bx

Mov Bx, Ax ;Palabra baja de la cantidad

Mov Ax, Dx ;Palabra alta de la cantidad

Mov Si, Offset ResultaR ;Cadena donde se guarda el resultado

Add Si, 11

Mov Cx, 10 ;Divisor = 10

OBTENDIGITO:

Dec Si

Xor Dx, Dx ;DX contrendrá el residuo

Div Cx ;Divide la palabra alta

Mov Di, Ax ;Guarda cociente en DI

Mov Ax, Bx ;Carga palabra baja en AX

Div Cx ;DX contiene registro de la división

Mov Bx, Ax ;Guarda el cociente

Mov Ax, Di ;Regresa la palabra alta

Add Dl, 30h ;Convierte residuo en ASCII

Mov [Si], Dl ;Lo almacena

Or Ax, Ax ;Si la palabra alta no es cero

Jnz OBTENDIGITO ; brinca a OBTENDIGITO

Or Bx, Bx ;Si la palabra baja no es cero

Jnz OBTENDIGITO ; brinca a OBTENDIGITO

Ret

ConvASCII Endp

HuboERROR Proc Near

Cmp Cantidad,0 ;Es la cantidad 1?

Jnz HUBOERROR02 ;no

Mov Dx, Offset Error1

Call Imprime

Mov ErrorCAP, 1 ;Enciende la bandera de error

Jmp HUBOERROR05

HUBOERROR02:

Cmp Cantidad, 1 ;Es la cantidad 2?

Jnz HUBOERROR03 ;no

Mov Dx, Offset Error2

Call Imprime

Mov ErrorCAP, 1

jmp HUBOERROR05

HUBOERROR03:

Cmp Cantidad, 2 ;Es una cantidad fuera de rango?

Jnz HUBOERROR04 ;no

Mov Dx, Offset Error3

Call Imprime

Mov ErrorCAP, 1

Jmp HUBOERROR05

HUBOERROR04:

Mov Dx, Offset Error4 ;Error de división por cero

Call Imprime

Mov ErrorCAP, 1

HUBOERROR05:

Ret

HuboERROR Endp

.STACK

End Empieza

Directorio y bibliografía

Créditos

Ing. M—nico Brise–o C.

Idea original

Hugo Eduardo Pérez P.

Desarrollo e implementación

Bibliograf'a

Lenguaje Ensamblador Para Microcomputadoras IBM

J. Terry Godfrey

Ed. Prentice Hall Hispanoamericana, S.A.

México

Ensamblador Básico

A. Rojas

Ed. Computec Editores S.A. de C.V.

México

IBM Personal Computer Assembly Languaje Tutorial

Joshua Auerbach

Yale University