El tutorial se enfoca completamente hacia las computadoras que operan con procesadores de la familia x86 de Intel y, considerando que el ensamblador basa su funcionamiento en los recursos internos del procesador, los ejemplos descritos no son compatibles con ninguna otra arquitectura.
Se estructura la información en forma de unidades para permitir el fácil acceso a cada uno de los típicos y facilitar el seguimiento del tutorial.
En la sección introductoria se mencionan algunos de los conceptos elementales acerca de los sistemas de cómputo así como del ensamblador mismo, y continúa con el tutorial propiamente dicho.
CONTENIDO:
Descripción básica de un sistema de cómputo ........................3
El porqué aprender lenguaje ensamblador ...............................6
Acercamiento al lenguaje ensamblador.
Esta primera parte esta enfocada al conocimiento de algunas de las características de las computadoras y del ensamblador.
UNIDAD 1: Conceptos básicos...............................................7
UNIDAD 2: Programación en ensamblador............................28
Las instrucciones del ensamblador.
En esta segunda parte se profundiza un poco mas en la descripción de las instrucciones del lenguaje ensamblador.
UNIDAD 3: Instrucciones de operación sobre datos....................41
UNIDAD 4: Instrucciones lógicas y aritméticas...........................50
UNIDAD 5: Instrucciones para control de procesos.....................58
Interrupciones y manejo de archivos.
UNIDAD 6: Interrupciones........................................................74
UNIDAD 7: Introducción al manejo de archivos.........................102
Introducción a las macros.
UNIDAD 8: Macros y procedimientos......................................109
Ejemplos.................................................................................114
En esta sección se exponen algunos programas de ejemplo en los que se utilizan los elementos explicados en el tutorial.
Desplegar un mensaje en pantalla
Desplegar números hexadecimales del 15 al 0
Operaciones básicas
Directorio y bibliografía..........................................128
Descripcion básica de un sistema de cómputo.
Esta sección tiene como finalidad dar una breve reseña de las partes principales de un sistema de cómputo a un nivel básico, que permita al usuario un mayor entendimiento de los conceptos que se trataran a lo largo del tutorial.
* Unidades de Entrada y Salida
* Unidades de Memoria Auxiliar
Sistema de cómputo.
Le llamamos sistema de cómputo a la configuración completa de una computadora, incluyendo las unidades perif‚ricas y la programación de sistemas que la hacen un aparato útil y funcional para un fin determinado.
Esta parte es conocida también como unidad central de procesamiento o UCP. formada a su vez por la unidad de control y la unidad aritmética y lógica. Sus funciones consisten en leer y escribir contenidos de las celdas de memoria, llevar y traer datos entre celdas de memoria y registros especiales y decodificar y ejecutar las instrucciónes de un programa.
El procesador cuenta con una serie de celdas de memoria que se útilizan con mucha frecuencia y que, por ende, forman parte de la UCP.
Estas celdas son conocidas con el nombre de registros. Un procesador puede tener una docena o dos de estos registros. La unidad aritmética y lógica de la UCP realiza las operaciones relacionadas con los cálculos numéricos y simbólicos. Típicamente estas unidades sólo tienen capacidad de efectuar operaciones muy elementales como: suma y resta de dos números de punto fijo, multiplicación y división de punto fijo, manipulación de bits de los registros y comparación del contenido de dos registros.
Las computadoras personales pueden clasificarse por lo que se conoce como tamaño de palabra, esto es, la cantidad de bits que el procesador puede manejar a la vez.
Es un conjunto de celdas (actualmente fabricadas con semiconductores) usadas para procesos generales, tales como la ejecución de programas y el almacenamiento de información para las operaciones.
Cada una de las celdas puede contener un valor numérico y tienen la propiedad de ser direcciónables, esto es, que se pueden distinguir una de otra por medio de un número único o dirección para cada celda.
El nombre genérico de estas memorias es Random Access Memory (Memoria de acceso aleatorio) o RAM por sus siglas en inglés. La principal desventaja de este tipo de memoria es que los circuitos integrados pierden la información que tienen almacenada cuando se interrumpe la alimentación eléctrica. Esto llev— a la creación de memorias cuya información no se pierda cuando se apaga el sistema. Estas memorias reciben el nombre de Read Only Memory (Memoria de solo lectura) o ROM.
Para que una computadora nos sea útil es necesario que el procesador se comunique al exterior por medio de interfaces que permiten la entrada y la salida de datos del procesador y la memoria. Haciendo uso de estas comunicaciones es posible introducir datos para su procesamiento y la posterior visualización de los datos ya procesados.
Algunas de las unidades de entrada mas comunes son teclados, lectoras de tarjetas (ya en desuso), mouse, etc. Las unidades de salida mas comunes son las terminales de video y las impresoras.
Como la memoria central de una computadora es costosa y, considerando las aplicaciones actuales, muy limitada, surge entonces la necesidad de crear sistemas de almacenamiento de información prácticos y económicos. Adem s, la memoria central pierde su contenido al apagarse la máquina, por lo que no es conveniente útilizarla para almacenamiento permanente de datos.
Estos y otros incovenientes dan lugar a la creación de unidades periféricas de memoria que reciben el nombre de memoria auxiliar o secundaria. De estas unidades periféricas las más comunes son las cintas y los discos magnéticos.
La información almacenada en estos medios magnéticos recibe el nombre de archivo. Un archivo está formado por un número variable de registros, generalmente de tamaño fijo; los registros pueden contener datos o programas.
La primera razón para trabajar con ensamblador es que proporciona la oportunidad de conocer más a fondo la operación de su PC, lo que permite el desarrollo de software de una manera más consistente.
La segunda razón es el control total de la PC que se tiene con el uso del mismo.
Otra razón es que los programas de ensamblador son más rápidos, más compactos y tienen mayor capacidad que los creados en otros lenguajes.
Por último el ensamblador permite una optimización ideal en los programas tanto en su tamaño como en su ejecución.
Software
En terminos de computación es todo aquel proceso o programa que útiliza los recursos de la computadora para lograr el objetivo trazado por su dise–ador o programador.
Información en las computadoras.
Convertir números binarios a decimales
Convertir números decimales a binarios
Métodos de representación de datos en una computadora.
Representación de punto flotante
Trabajando con el lenguaje ensamblador.
Proceso de creación de un programa
Guardar y cargar los programas
Condiciones, ciclos y bifurcaciones
Para que la PC pueda procesar la información es necesario que está se encuentre en celdas especiales llamadas registros.
Los registros son conjuntos de 8 o 16 flip-flops (basculadores o biestables).
Un flip-flop es un dispositivo capaz de almacenar dos niveles de voltaje, uno bajo, regularmente de 0.5 volts y otro alto comunmente de 5 volts. El nivel bajo de energ'a en el flip-flop se interpreta como apagado o 0, y el nivel alto como prendido o 1. A estos estados se les conoce usualmente como bits, que son la unidad más peque–a de información en una computadora.
A un grupo de 16 bits se le conoce como palabra, una palabra puede ser dividida en grupos de 8 bits llamados bytes, y a los grupos de 4 bits les llamamos nibbles.
El sistema numérico que útilizamos a diario es el sistema decimal, pero este sistema no es conveniente para las máquinas debido a que la información se maneja codificada en forma de bits prendidos o apagados; esta forma de codificación nos lleva a la necesidad de conocer el cálculo posicional que nos permita expresar un número en cualquier base que lo necesitemos.
Es posible representar un número determinado en cualquier base mediante la siguiente formula:
Donde n es la posición del dígito empezando de derecha a izquierda y numerando a partir de cero. D es el dígito sobre el cual operamos y B es la base num‚rica empleada.
Convertir números binarios a decimales
Trabajando en el lenguaje ensamblador nos encontramos con la necesidad de convertir números del sistema binario, que es el empleado por las computadoras, al sistema decimal útilizado por las personas.
El sistema binario está basado en unicamente dos condiciones o estados, ya sea encendido (1) o apagado (0), por lo tanto su base es dos.
Para la conversi—n podemos útilizar la formula de valor posicional:
Por ejemplo, si tenemos el número binario 10011, tomamos de derecha a izquierda cada dígito y lo multiplicamos por la base elevada a la nueva posición que ocupan:
Binario: 1 1 0 0 1
Decimal: 1*2^0 + 1*2^1 + 0*2^2 + 0*2^3 + 1*2^4
= 1 + 2 + 0 + 0 + 16 = 19 decimal.
El caracter ^ es útilizado en computación como símbolo de potenciación y el caracter * se usa para representar la multiplicación.
Convertir números decimales a binarios
Existen varios métodos de conversión de números decimales a binarios; aqu' solo se analizará uno.
Naturalmente es mucho más fácil una conversión con una calculadora cient'fica, pero no siempre se cuenta con ella, así que es conveniente conocer por lo menos una forma manual para hacerlo.
El método que se explicará útiliza la división sucesiva entre dos, guardando el residuo como dígito binario y el resultado como la siguiente cantidad a dividir.
Tomemos como ejemplo el número 43 decimal.
43/2 = 21 y su residuo es 1
21/2 = 10 y su residuo es 1
10/2 = 5 y su residuo es 0
5/2 = 2 y su residuo es 1
2/2 = 1 y su residuo es 0
1/2 = 0 y su residuo es 1
Armando el número de abajo hacia arriba tenemos que el resultado en binario es 101011
En la base hexadecimal tenemos 16 dígitos que van del 0 al 9 y de la letra A hasta la F (estas letras representan los números del 10 al 15). Por lo tanto, contamos 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E y F.
La conversión entre numeración binaria y hexadecimal es sencilla. Lo primero que se hace para una conversión de un número binario a hexadecimal es dividirlo en grupos de 4 bits, empezando de derecha a izquierda. En caso de que el último grupo (el que quede más a la izquierda) sea menor de 4 bits se rellenan los faltantes con ceros.
Tomando como ejemplo el número binario 101011 lo dividimos en grupos de 4 bits y nos queda:
10; 1011
Rellenando con ceros el último grupo (el de la izquierda):
0010; 1011
después tomamos cada grupo como un número independiente y consideramos su valor en decimal:
0010 = 2; 1011 = 11
Pero como no podemos representar este número hexadecimal como 211 porqué sería un error, tenemos que sustituir todos los valores mayores a 9 por su respectiva representación en hexadecimal, con lo que obtenemos:
2BH (Donde la H representa la base hexadecimal)
Para convertir un número de hexadecimal a binario solo es necesario invertir estos pasos: se toma el primer dígito hexadecimal y se convierte a binario, y luego el segundo, y así sucesivamente hasta completar el número.
código ASCII
ASCII generalmente se pronuncia "aski", es un acrónimo de American Standard Code for Information Interchange.
Este código asigna a las letras del alfabeto, a los dígitos decimales del 0 al 9 y a varios símbolos adicionales un número binario de 7 bits (poni‚ndose el bit 8 en su estado de apagado o 0).
De esta forma cada letra, dígito o caracter especial ocupa un byte en la memoria de la computadora.
Podemos observar que este método de representación de datos es muy ineficiente en el aspecto numérico, ya que en formato binario nos basta un solo byte para representar números de 0 a 255, en cambio con el código ASCII un byte puede representar unicamente un dígito.
Debido a esta ineficiencia, el código ASCII es principalmente útilizado en la memoria para representar texto.
método BCD
BCD es un acrónimo de Binary Coded Decimal.
En esta notación se útilizan grupos de 4 bits para representar cada dígito decimal del 0 al 9. Con este método podemos representar dos dígitos por byte de información.
A£n cuando este método es mucho más práctico para representación de números en la memoria en comparación al ASCII, todav'a se queda por debajo del binario, ya que con un byte en el método BCD solo podemos representar dígitos del 0 al 99, en cambio, en formato binario podemos representar todos los dígitos desde 0 hasta 255.
Este formato es útilizado principalmente para representar números muy grandes en aplicaciones mercantiles ya que fácilita las operaciones con los mismos evitando errores de redondeo.
Representación de punto flotante
Esta representación esta basada en la notación científica, esto es, representar un número en dos partes: su mantisa y su exponente.
Poniendo como ejemplo el número 1234000, podemos representarlo como 1.123*10^6, en esta última notación el exponente nos indica el número de espacios que hay que mover el espacio hacia la derecha para obtener el resultado original.
En caso de que el exponente fuera negativo nos estaría indicando el número de espacios que hay que recorrer el punto decimal hacia la izquierda para obtener el original.
Proceso de creación de un programa
Para la creación de un programa es necesario seguir cinco pasos: diseño del algoritmo, codificación del mismo, su traducción a lenguaje máquina, la prueba del programa y la depuración.
En la etapa de diseño se plantea el problema a resolver y se propone la mejor solución, creando diagramas esquemáticos útilizados para el mejor planteamiento de la solución.
La codificación del programa consiste en escribir el programa en algún lenguaje de programación; en este caso específico en ensamblador, tomando como base la solución propuesta en el paso anterior.
La traducción al lenguaje máquina es la creación del programa objeto, esto es, el programa escrito como una secuencia de ceros y unos que pueda ser interpretado por el procesador.
La prueba del programa consiste en verificar que el programa funcione sin errores, o sea, que haga lo que tiene que hacer.
La última etapa es la eliminación de las fallas detectadas en el programa durante la fase de prueba. La corrección de una falla normalmente requiere la repetición de los pasos comenzando desde el primero o el segundo.
Para crear un programa en ensamblador existen dos opciones, la primera es útilizar el MASM (Macro Assembler, de Microsoft), y la segunda es útilizar el debugger, en esta primera sección útilizaremos este último ya que se encuentra en cualquier PC con el sistema operativo MS-DOS, lo cual lo pone al alcance de cualquier usuario que tenga acceso a una máquina con estas caracteristicas.
Debug solo puede crear archivos con extensión .COM, y por las características de este tipo de programas no pueden ser mayores de 64 kb, además deben comenzar en el desplazamiento, offset, o dirección de memoria 0100H dentro del segmento específico.
Registros de la UCP
La UCP tiene 14 registros internos, cada uno de 16 bits. Los primeros cuatro, AX, BX, CX, y DX son registros de uso general y también pueden ser útilizados como registros de 8 bits, para útilizarlos como tales es necesario referirse a ellos como por ejemplo: AH y AL, que son los bytes alto (high) y bajo (low) del registro AX. Esta nomenclatura es aplicable también a los registros BX, CX y DX.
Los registros son conocidos por sus nombres específicos:
C:\> Debug [Enter]
En la siguiente linea aparecera un guión, éste es el indicador del Debug, en éste momento se pueden introducir las instrucciónes del Debug. útilizando el comando:
- r [Enter]
Se desplegaran todos los contenidos de los registros internos de la UCP; una forma alternativa de mostrarlos es usar el comando "r" útilizando como parametro el nombre del registro cuyo valor se quiera visualizar. Por ejemplo:
- rbx
Esta instrucción desplegará unicamente el contenido del registro BX y cambia el indicador del Debug de " - " a " : "
Estando así el prompt es posible cambiar el valor del registro que se visualizo tecleando el nuevo valor y a continuación [Enter], o se puede dejar el valor anterior presionando [Enter] sin telclear ning£n valor.
Es posible cambiar el valor del registro de banderas, así como útilizarlo como estructura de control en nuestros programas como se verá más adelante. Cada bit del registro tiene un nombre y significado especial, la lista dada a continuación describe el valor de cada bit, tanto apagado como prendido y su relación con las operaciones del procesador:
En el lenguaje ensamblador las lineas de código constan de dos partes, la primera es el nombre de la instrucción que se va a ejecutar y la segunda son los parámetros del comando u operandos. Por ejemplo:
add ah bh
Aquí "add" es el comando a ejecutar (en éste caso una adición) y tanto "ah" como "bh" son los parámetros.
El nombre de las instrucciónes en éste lenguaje esta formado por dos, tres o cuatro letras. a estas instrucciónes también se les llama nombres mnemúnicos o códigos de operación, ya que representan algúna función que habr de realizar el procesador.
Existen algúnos comandos que no requieren parámetros para su operación, así como otros que requieren solo un par metro.
algúnas veces se utilizaran las instrucciónes como sigue:
add al,[170]
Los corchetes en el segundo parámetro nos indican que vamos a trabajar con el contenido de la casilla de memoria número 170 y no con el valor 170, a ‚sto se le conoce como direcciónamiento directo.
Nuestro primer programa
Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo, lo que haremos será una suma de dos valores que introduciremos directamente en el programa:
El primer paso es iniciar el Debug, éste paso consiste unicamente en teclear debug [Enter] en el prompt del sistema operativo.
Para ensamblar un programa en el Debug se útiliza el comando "a" (assemble); cuando se útiliza éste comando se le puede dar como parámetro la dirección donde se desea que se inicie el ensamblado.
Si se omite el parámetro el ensamblado se iniciará en la localidad especificada por CS:IP, usualmente 0100H, que es la localidad donde deben iniciar los programas con extensión .COM, y sera la localidad que útilizaremos debido a que debug solo puede crear éste tipo específico de programas.
Aunque en éste momento no es necesario darle un parámetro al comando "a" es recomendable hacerlo para evitar problemás una vez que se haga uso de los registros CS:IP, por lo tanto tecleamos:
- a0100 [Enter]
Al hacer ésto aparacerá en la pantalla algo como: 0C1B:0100 y el cursor se posiciona a la derecha de éstos números, nótese que los primeros cuatro dígitos (en sistema hexagesimal) pueden ser diferentes, pero los últimos cuatro deben ser 0100, ya que es la dirección que indicamos como inicio. Ahora podemos introducir las instrucciónes:
0C1B:0100 mov ax,0002 ;coloca el valor 0002 en el registro ax 0C1B:0103 mov bx,0004 ;coloca el valor 0004 en el registro bx 0C1B:0106 add ax,bx ;le adiciona al contenido de ax el contenido de bx 0C1B:0108 int 20 ; provoca la terminación del programa. 0C1B:010A
No es necesario escribir los comentarios que van después del ";". Una vez digitado el último comando, int 20, se le da [Enter] sin escribir nada mas, para volver al prompt del debuger.
La última linea escrita no es propiamente una instrucción de ensamblador, es una llamada a una interrupción del sistema operativo, estas interrupciones ser n tratadas más a fondo en un capítulo posterior, por el momento solo es necesario saber que nos ahorran un gran número de lineas y son muy útiles para accesar a funciones del sistema operativo.
Para ejecutar el programa que escribimos se utliza el comando "g", al útilizarlo veremos que aparece un mensaje que dice: "Program terminated normally". Naturalmente con un mensaje como éste no podemos estar seguros que el programa haya hecho la suma, pero existe una forma sencilla de verificarlo, útilizando el comando "r" del Debug podemos ver los contenidos de todos los registros del procesador, simplemente teclee:
- r [Enter]
aparacerá en pantalla cada registro con su respectivo valor actual:
AX=0006BX=0004CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000
DS=0C1BES=0C1BSS=0C1BCS=0C1BIP=010A NV UP EI PL NZ NA PO NC
0C1B:010A 0F DB oF
Existe la posibilidad de que los registros contengan valores diferentes, pero AX y BX deben ser los mismos, ya que son los que acabamos de modificar.
Otra forma de ver los valores, mientras se ejecuta el programa es útilizando como parámetro para "g" la dirección donde queremos que termine la ejecución y muestre los valores de los registros, en éste caso sería: g108, esta instrucción ejecuta el programa, se detiene en la dirección 108 y muestra los contenidos de los registros.
también se puede llevar un seguimiento de lo que pasa en los registros útilizando el comando "t" (trace), la función de éste comando es ejecutar linea por linea lo que se ensambl— mostrando cada vez los contenidos de los regitros.
Para salir del Debug se útiliza el comando "q" (quit).
Guardar y cargar los programas
No sería práctico tener que digitar todo un programa cada vez que se necesite, para evitar eso es posible guardar un programa en el disco, con la enorme ventaja de que ya ensamblado no ser necesario correr de nuevo debug para ejecutarlo.
Los pasos a seguir para guardar un programa ya almacenado en la memoria son:
Obtener la longitud del programa restando la dirección final de la dirección inicial, naturalmente en sistema hexadecimal. Darle un nombre al programa y extensión Poner la longitud del programa en el registro CX Ordenar a Debug que escriba el programa en el disco.
útilizando como ejemplo el programa del capítulo anterior tendremos una idea más clara de como llevar éstos pasos:
Al terminar de ensamblar el programa se vería así:
0C1B:0100 mov ax,0002
0C1B:0103 mov bx,0004
0C1B:0106 add ax,bx
0C1B:0108 int 20
0C1B:010A
- h 10a 100
020a 000a
- n prueba.com
- rcx
CX 0000
:000a
-w
Writing 000A bytes
Para obtener la longitud de un programa se útiliza el comando "h", el cual nos muestra la suma y resta de dos números en hexadecimal. Para obtener la longitud del nuestro le proporcionamos como parámetros el valor de la dirección final de nuestro programa (10A) y el valor de la dirección inicial (100). El primer resultado que nos muestra el comando es la suma de los parámetros y el segundo es la resta.
El comando "n" nos permite poner un nombre al programa.
El comando "rcx" nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamaño del archivo con "h", en éste caso 000a, ya que nos interesa el resultado de la resta de la dirección inicial a la dirección final.
Por último el comando w escribe nuestro programa en el disco, indicandonos cuantos bytes escribió.
Para cargar un archivo ya guardado son necesarios dos pasos:
Proporcionar el nombre del archivo que se cargará.
Cargarlo útilizando el comando "l" (load).
Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior.
Dentro del Debug escribimos lo siguiente:
- n prueba.com
- l
- u 100 109
0C3D:0100 B80200 MOV AX,0002
0C3D:0103 BB0400 MOV BX,0004
0C3D:0106 01D8 ADD AX,BX
0C3D:0108 CD20 INT 20
El último comando, "u", se útiliza para verificar que el programa se carg— en memoria, lo que hace es desensamblar el código y mostrarlo ya desensamblado. Los parámetros le indican a Debug desde donde y hasta donde desensamblar.
Debug siempre carga los programas en memoria en la dirección 100H, a menos que se le indique algúna otra.
Condiciones, ciclos y bifurcaciones
Estas estructuras, o formas de control le dan a la máquina un cierto grado de desición basado en la información que recibe.
La forma más sencilla de comprender éste tema es por medio de ejemplos.
Vamos a crear tres programas que hagan lo mismo: desplegar un número determinado de veces una cadena de caracteres en la pantalla.
- a100
0C1B:0100 jmp 125 ; brinca a la dirección 125H
0C1B:0102 [Enter]
- e 102 'Cadena a visualizar 15 vecesi 0d 0a '$'
- a125
0C1B:0125 MOV CX,000F ; veces que se desplegará la cadena
0C1B:0128 MOV DX,0102 ; copia cadena al registro DX
0C1B:012B MOV AH,09 ; copia valor 09 al registro AH
0C1B:012D INT 21 ; despliega cadena
0C1B:012F LOOP 012D ; si CX>0 brinca a 012D
0C1B:0131 INT 20 ; termina el programa.
Por medio del comando "e" es posible introducir una cadena de caracteres en una determinada localidad de memoria, dada como parámetro, la cadena se introduce entre comillas, le sigue un espacio, luego el valor hexadecimal del retorno de carro, un espacio, el valor de linea nueva y por último el simbolo '$' que el ensamblador interpreta como final de la cadena. La interrupción 21 útiliza el valor almacenado en el registro AH para ejecutar una determinada función, en éste caso mostrar la cadena en pantalla, la cadena que muestra es la que está almacenada en el registro DX. La instrucción LOOP decrementa automaticamente el registro CX en uno y si no ha llegado el valor de éste registro a cero brinca a la casilla indicada como parámetro, lo cual crea un ciclo que se repite el número de veces especificado por el valor de CX. La interrupción 20 termina la ejecución del programa.
Otra forma de realizar la misma función pero sin útilizar el comando LOOP es la siguiente:
- a100
0C1B:0100 jmp 125 ; brinca a la dirección 125H
0C1B:0102 [Enter]
- e 102 'Cadena a visualizar 15 vecesi 0d 0a '$'
- a125
0C1B:0125 MOV BX,000F ; veces que se desplegará la cadena
0C1B:0128 MOV DX,0102 ; copia cadena al registro DX
0C1B:012B MOV AH,09 ; copia valor 09 al registro AH
0C1B:012D INT 21 ; despliega cadena
0C1B:012F DEC BX ; decrementa en 1 a BX
0C1B:0130 JNZ 012D ; si BX es diferente a 0 brinca a 012D
0C1B:0132 INT 20 ; termina el programa.
En éste caso se útiliza el registro BX como contador para el programa, y por medio de la instrucción "DEC" se disminuye su valor en 1. La instrucción "JNZ" verifica si el valor de B es diferente a 0, ésto con base en la bandera NZ, en caso afirmativo brinca hacia la dirección 012D. En caso contrario contin£a la ejecución normal del programa y por lo tanto se termina.
Una £tima variante del programa es útilizando de nuevo a CX como contador, pero en lugar de útilizar LOOP útilizaremos decrementos a CX y comparación de CX a 0.
- a100
0C1B:0100 jmp 125 ; brinca a la dirección 125H
0C1B:0102 [Enter]
- e 102 'Cadena a visualizar 15 vecesi 0d 0a '$'
- a125
0C1B:0125 MOV DX,0102 ; copia cadena al registro DX
0C1B:0128 MOV CX,000F ; veces que se desplegará la cadena
0C1B:012B MOV AH,09 ; copia valor 09 al registro AH
0C1B:012D INT 21 ; despliega cadena
0C1B:012F DEC CX ; decrementa en 1 a CX
0C1B:0130 JCXZ 0134 ; si CX es igual a 0 brinca a 0134
0C1B:0132 JMP 012D ; brinca a la direcci&oaute;n 012D
0C1B:0134 INT 20 ; termina el programa
En éste ejemplo se usa la instrucción JCXZ para controlar la condición de salto, el significado de tal función es: brinca si CX=0
El tipo de control a útilizar dependerá de las necesidades de programación en determinado momento.
Interrupciones
Definición de interrupción:
Una interrupción es una instrucción que detiene la ejecución de un programa para permitir el uso de la UCP a un proceso prioritario. Una vez concluido éste último proceso se devuelve el control a la aplicación anterior.
Por ejemplo, cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones, se detiene temporalmente la aplicación que estabamos útilizando para permitir el uso del procesador al manejo de la información que está llegando en ese momento. Una vez terminada la transferencia de información se reanudan las funciones normales del procesador de palabras.
Las interrupciones ocurren muy seguido, sencillamente la interrupción que actualiza la hora del día ocurre aproximadamente 18 veces por segundo. Para lograr administrar todas estas interrupciones, la computadora cuenta con un espacio de memoria, llamado memoria baja, donde se almacenan las direcciónes de cierta localidad de memoria donde se encuentran un juego de instrucciónes que la UCP ejecutar para después regresar a la aplicación en proceso.
En los programas anteriores hicimos uso de la interrupcion número 20H para terminar la ejecución de nuestros programas, ahora útilizaremos otra interrupción para mostrar información en pantalla:
útilizando Debug tecleamos:
- a100
2C1B:0100 JMP 011D
2C1B:0102 [ENTER]
- E 102 'Hola, como estas.' 0D 0A '$'
- A011D
2C1B:011D MOV DX,0102
2C1B:0120 MOV AH,09
2C1B:0122 INT 21
2C1B:0123 INT 20
En éste programa la interrupción 21H manda al monitor la cadena localizada en la dirección a la que apunta el registro DX.
El valor que se le da a AH determina cual de las opciones de la interrupción 21H sera útilizada, ya que esta interrupción cuenta con varias opciones.
El manejo directo de interrupciones es una de las partes más fuertes del lenguaje ensamblador, ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida.