Está en la página 1de 125

CAPITULO I

INTRODUCCION

1.1 Por qu programar en Ensamblador?


En la programacin de computadoras existe un axioma: Primero consigue que un programa trabaje bien y.... despus haz que trabaje ms rpido y qu pasa si no puedo hacer que mi programa sea ms rpido?. Entonces slo queda una sola solucin: codificarlo en lenguaje Ensamblador. Un programa escrito en lenguaje Ensamblador requiere considerablemente menos memoria y tiempo de ejecucin que un programa escrito en un lenguaje de alto nivel. h Sin embargo el lenguaje Ensamblador tiene una gran desventaja: es difcil de aprender por que como el lenguaje C++ utiliza punteros o sea direcciones a memoria y adems requiere mucho cdigo, que se traduce en realizar ms trabajo que el habitual en comparacin con los lenguajes de alto nivel, y por tanto consume mayor tiempo de programacin. Para los informticos la productividad siempre ha sido algo muy importante, los sistemas de informacin tienen que desarrollarse en el menor tiempo posible, y esto ha ocasionado que los lenguajes hayan evolucionado desde los lenguajes de mquina, pasando por el lenguaje Ensamblador, seguir con los lenguajes de alto nivel, hasta llegar actualmente a los lenguajes visuales y orientados a objetos, llamados de quinta generacin. En los inicios de la computacin en las dcadas de los 50s y 60s, se empez programando en lenguaje de mquina, es decir con 1s y 0s; se continu programando en lenguaje Ensamblador que sustituy los nmeros binarios por nemnicos que son las instrucciones del Ensamblador, y en esta bsqueda incensante de aumentar la productividad de los programadores, aparecen los lenguajes de alto nivel y entre ellos el lenguaje C, que evolucion hasta llegar al C++, que ha desplazado al Pascal, y en la actualidad se ha constituido en el lenguaje acadmico en las universidades; es el lenguaje que ms rpido cambia, por eso lo han dotado de capacidades para trabajar en el nivel ms bajo posible y tambin el ms alto, y sus diseadores han conseguido que su cdigo sea muy rpido y eficiente; prcticamente ha desplazado en mucho al lenguaje Ensamblador. Hace poco muchos productos para mostrar su calidad se jactaban de decir hecho ntegramente en lenguaje Ensamblador. Con la aparicin del lenguaje C++, podemos afirmar que casi todos los sistemas operativos, protocolos de redes, utilitarios de los sistemas, compiladores de lenguajes, etc., estn construidos utilizando el lenguaje C++.
1

Sin embargo, siempre existen mdulos que a pesar de estar hechos con C++, siguen siendo lentos. Ah entra a tallar el lenguaje Ensamblador. Por eso, el binomio: C++ & Ensamblador resulta insustituible, es la herramienta ms poderosa que existe para programar la computadora. Debido a su cdigo eficiente, la mayora de libros de Ensamblador afirman que el lenguaje Ensamblador se aprende por las siguientes razones: 1. Conocer en mayor profundidad el funcionamiento bsico de la mquina. 2. Ganar rapidez en la ejecucin de los programas. 3. Tener acceso a posibilidades de la mquina que son inaccesibles desde otros lenguajes. 4. Entender mejor cmo funciona un lenguaje de alto nivel. 5. Utilizar las posibilidades de la mquina desde los propios lenguajes de alto nivel con interface de estos lenguajes con el Ensamblador. Sin embargo, para los informticos, existe otra razn muy poderosa para aprender a programar en lenguaje Ensamblador: este lenguaje es formativo. Ningn lenguaje de programacin, con excepcin del Ensamblador, muestra al programador, cmo trabaja internamente la computadora; sta es una mquina esttica, que se convierte en una caja negra a la que se le ingresan datos para obtener resultados. Cmo lo hace?. Como es una mquina que no se mueve, aparentemente su funcionamiento es un misterio. El Ensamblador es el nico lenguaje de programacin que no tiene libreras, y si no las tiene, no queda otra salida: hay que construirlas; por que sin libreras, programar en Ensamblador es muy tedioso, se requiere escribir mucho cdigo, y esto desanima a cualquiera en seguir programando en este lenguaje. El esfuerzo de construir estas libreras es muy grande, y lo lograrn solamente quienes lleguen a niveles avanzados de programacin en Ensamblador, cuya curva de aprendizaje tiene una pendiente muy elevada. La actividad de programar, cualquiera que sea el lenguaje elegido, en general es un arte. Sin embargo, cuando se trata del ensamblador se convierte en un arte de maestros. Cuando se llega a entender la filosofa de cmo trabaja el procesador internamente, este lenguaje de lo complicado y difcil que parece a un comienzo se va transformando en sencillo, claro, puro y va directo al grano. Es cmo encontrar las respuestas a las siguientes preguntas en forma consciente: 1. Cul es el objetivo? 2. Cmo logro el objetivo?
2

3. Cmo optimizo lo logrado? Ponderemos un poco lo anterior siguiendo una lgica secuencial, en la que cada paso dependa del anterior. Finalmente, de los tres pasos el ms difcil es el tercero, y ah, en algunos casos, es donde entra en escena el lenguaje ensamblador.

1.1.1.

COMPUTADORAS Y PROGRAMAS

LA COMPUTADORA UNA MAQUINA MARAVILLOSA?


El hombre moderno tiene la idea de que las mquinas le disminuyen una parte de su trabajo. Esto es realmente cierto porque la generalidad de las mquinas tienen como finalidad inmediata mover o transformar objetos fsicos. La utilizacin de las mquinas en forma intensiva ha ocasionado un avance insospechado de nuestra civilizacin, por eso se habla de la Era Industrial que corresponde a la etapa en que el hombre ha intensificado el uso de las mquinas. A partir del siglo XVIII, la revolucin industrial gener un cambio en los sistemas de produccin, e introdujo un nuevo sistema de fabricacin mediante mquinas impulsadas por una nueva fuerza: el vapor. Hasta entonces los artculos se haban fabricado a mano por los artesanos en los talleres. De aquella revolucin surge el mundo industrial moderno y nace una nueva clase: el obrero industrial, que trabaja en las fbricas bajo nuevas y difciles condiciones. Se inventaron mquinas de procedimientos mecnicos, surgieron nuevos mtodos de produccin logrando as fabricar mayor cantidad de artculos a menor precio y con mayor rapidez. Hoy da se hace esto automticamente casi sin la intervencin humana y lo que se busca antes que nada es la calidad de lo que se produce. En la dcada de los 50 el hombre inventa otro tipo de mquinas, que no realizan trabajo fsico, pero tienen la capacidad de procesar informacin; estas mquinas han resultado tan importantes que a la presente era se le llama Era de la Informacin. Estas mquinas se llaman computadoras u ordenadores. La computadora, como hemos puntualizado anteriormente, es una mquina que no realiza ningn trabajo fsico, pero sin embargo ha contribuido a crear nuevos paradigmas en todo el quehacer humano, desplazando el punto central de los recursos del capital hacia los recursos humanos y de informacin. Las computadoras han logrado conformar un nuevo paradigma en la situacin geopoltica del mundo que a su vez ha generado un
3

nuevo paradigma en el ambiente internacional de negocios. Las computadoras y las redes de computadoras han logrado el ascenso de la nueva empresa abierta e interconectada que constituye un nuevo paradigma organizacional.

1.2. EL HOMBRE Y LA COMPUTADORA SON MAQUINAS DE PROCESO DE DATOS


Cada proceso de la informacin tiene como meta la transformacin de datos; esto es vlido independientemente de que el proceso de la informacin sea manual a travs de una persona competente o automtico cuando se utiliza una mquina. Solamente existen dos mquinas que procesan la imformacin, el hombre y las mquinas que el hombre ha inventado para procesar informacin.
Estos datos Datos de entrada Hombre o mquina Datos de salida

deben tener un valor especfico para el usuario

El procesamiento automtico de la informacin se efecta con la ayuda de las mquinas de proceso de informacin. Un ejemplo muy difundido de una mquina de proceso de informacin es la calculadora de bolsillo, donde los datos de entrada son dados a travs de un teclado y los datos de salida son devueltos por medio de un sealizador de diodos emisores de luz o en forma impresa. Las calculadoras de bolsillo disponen con frecuencia de dispositivos para almacenar internamente una o ms constantes. Los datos de salida resultan, en este caso, de un proceso en el que participan datos de entrada y datos almacenados internamente.

Al lado de las calculadoras de bolsillo existen muchos otros tipos de mquinas de proceso de informacin. Como ejemplos tenemos: la mquina Turing la Learning Matrix el Perceptron la Computadora Analgica el Analizador Diferencial Digital (Digital Differential Analyzer) Un caso especial adicional es la Computadora digital u Ordenador, que en un concepto ms amplio es designado como
4

Sistema de Proceso de Datos. Comparadas con otros tipos de mquinas de proceso de informacin, las computadoras digitales son mucho ms eficientes. La parte predominante del proceso automtico de la informacin se lleva a cabo hoy da por medio de las computadoras digitales.

1.3.

DESDE EL PUNTO DE VISTA DE UN PROGRAMADOR QUE PUEDE HACER UNA COMPUTADORA DIGITAL ?

A las computadoras se les asignan muchas propiedades poderosas y asombrosas. Lo nico que hacen es recibir datos, llamados datos de entrada, y producen datos de salida que tienen mayor valor que los datos de entrada. A partir de estos datos de salida el hombre moderno toma decisiones que de alguna manera pueden contribuir al movimiento o a la modificacin de objetos fsicos. Sin embargo la computadora solamente trabaja con programas y el hombre es quien hace estos programas. La computadora sin programas no es nada, sera un montn de fierros intiles. Y desde el punto de vista de un programador, todas las computadoras, sean ellas las ms grandes o las ms pequeas, son simples colecciones de componentes electrnicos que tienen siete capacidades bsicas: Primera: Almacenar datos en un medio fsico, que llamaremos memoria principal Segunda: Hacer aritmtica multiplicacin y divisin simple: suma, resta,

Tercera: Entrada y salida de datos; sin estos dos procesos estas mquinas no tendran mucho uso no es cierto?. Cuarta: Capacidad de programa almacenado; ejecutar un programa tiene que cargarse ntegramente en la memoria principal. Quinta: para

Tomar decisiones simples, como consecuencia de comparar dos nmeros

Sexta: Persistencia de los datos, en un segundo medio fsico, llamado archivo o memoria secundaria Setima: adelante Reutilizacin, concepto que explicaremos ms

1.4. Porqu usamos las computadoras?


Desde que todas las computadoras solamente tienen estas siete capacidades bsicas, tan elementales: capacidad de guardar datos en memoria, hacer aritmtica simple, tomar decisiones triviales, almacenar un programa en memoria para correrlo, ejecutar entrada/salida de datos, almacenar y acceder a grandes cantidades de datos en almacenamientos secundarios, y la reutilizacin, entonces, si pensamos un poco, nos damos cuenta que tambin el hombre tiene estas capacidades bsicas, resulta natural preguntarse lo siguiente: Porqu usamos las computadoras?. La respuesta es la siguiente: Existen quizs tres buenas razones para usar estas mquinas a pesar de sus limitadas capacidades: 1.-) LAS USAMOS POR SU VELOCIDAD Las computadoras son capaces de hacer estas siete capacidades bsicas (almacenar datos en memoria, aritmtica simple, tomar decisiones simples, cargar programas en memoria, operaciones de entrada/salida, almacenar y acceder a grandes cantidades de informacin y la reutilizacin) a tremendas velocidades. Para apreciar esto digamos que el nmero de sumas que ejecuta la computadora en un segundo, probablemente requerira a una persona trabajando 40 horas semanales durante unos veinte aos. Velocidades para hacer otros tipos de operaciones aritmticas y tomar decisiones simples son comparables a la indicada para las sumas. Sin embargo las operaciones de entrada/salida que envuelven movimientos de componentes mecnicos de mquinas como las impresoras o los discos duros resultan mucho ms lentas. En un sistema de computacin tpico con una impresora de alta velocidad se pueden imprimir miles de lneas por minuto y en una impresora conectada a una PC unos 300 caracteres por segundo. 2.-) LAS USAMOS CONFIABILIDAD
A L H O M B R

A L A M A Q U I N A

I N H E R E N T E S

POR

SU

EXACTITUD

Las computadoras son exactas y confiables. Todo lo que hacen lo hacen a gran velocidad y sin equivocarse. Como son mquinas fabricadas por los hombres ocasionalmente pueden malograrse y tienen que ser reparadas. Cuando en un proceso con la computadora se comete un error este siempre se debe

al hombre. 3.-) LAS USAMOS POR LA CAPACIDAD DEL HOMBRE DE DESCOMPONER UN PROBLEMA GRANDE EN UN CONJUNTO DE PEQUEOS PROBLEMAS La razn ms importante de usar las computadoras est dada por el hecho de que el hombre puede resolver muchos problemas utilizando programas de computadora debido a su capacidad de enfrentar la complejidad no resolviendo directamente los problemas difciles, sino por el contrario solucionando equivalentemente un conjunto de pequeos problemas -uno despus de otro-; con la aclaracin de que las soluciones a estos pequeos problemas pueden ser obtenidos usando las limitadas capacidades que poseen todas las computadoras. Desde que las computadoras pueden hacer todas estas cosas con exactitud y a altas velocidades, la razn para utilizarlas es obvia. Podemos resumir entonces que:

LA COMPUTADORA ES: Extremadamente rpida. para manejar informacin. Precisa, nunca se equivoca. propenso a cometer errores. Estpida, es una esclava repetidora. la facultad de crear, por eso

EL HOMBRE ES: Increblemente lento Impreciso, es Brillante, porque tiene es el amo.

ADEMAS: La computadora trabaja con datos. con informacin. El hombre trabaja

Cuando la computadora lee transfiere Cuando el hombre lee, adquiere informacin datos de un medio electromagntico (disco, interpretando un conjunto de datos. La lectura pantalla,etc.)a otro medio electromagntico es un fenmeno extraordinariamente complejo. llamado memoria.
7

Cuando la computadora escribe transfiere hombre escribe plasmando un datos de la memoria a otro medio un lenguaje. electromagntico (disco, pantalla, etc.)

Unicamente el pensamiento en

incalculable

Ambos constituyen un binomio de una riqueza

El conocimiento es poder y la computadora es una mquina amplificadora de ese poder, es una innovadora vital y fructfera. La computadora crea valor mediante la transformacin del poder cerebral de los trabajadores del conocimiento, con poco consumo de energa y materiales nuevos.

Estas siete capacidades bsicas, son tan importantes, que su entendimiento nos mostrar la filosofa de cmo trabaja internamente una computadora digital, y el programador entienda cmo opera la computadora internamente, por eso las estudiaremos con detenimiento en el siguiente captulo; pero para su completo entendimiento tambin estudiaremos la herramienta que nos ayudar a entender estas siete capacidades bsicas, nos referimos concretamente al programa debug.exe, que aprenderemos a manejar ms adelante en el captulo II. Analicemos una a una las siete capacidades bsicas de una computadora digital: 1.4.1. PRIMERA CAPACIDAD BASICA Cada computadora tiene circuitos electrnicos que permiten almacenar y recuperar datos en su memoria en forma directa, utilizando expresiones que se llaman instrucciones de asignacin. Qu tipos de datos puede almacenar y recuperar?. Solamente datos numricos binarios, compuestos de dgitos 1s y 0s. De ah el nombre de computadoras digitales Si un programador quiere guardar la letra A en la memoria de la computadora, utiliza el nmero binario 01000001 2 o su equivalente hexadecimal 4116, o tambin 41h la h significa que est en el sistema hexadecimal y el nombre de una variable, que es un nombre que comienza con una letra, por ejemplo X, y si recurre al lenguaje Cobol tiene que escribir: move A to X, en lenguaje C: X = A;, en Object Pascal: X := A; y en Ensamblador:

mov X, 41h que debemos leer almacena 41h en la direccin de la memoria a la que apunta X, o en forma ms simple para no mencionar la memoria, almacena 41h en X, o mejor todava asigna 41h a X o esta otra mueve 41h a X. En lenguaje de mquina, como veremos mas adelante, no se pueden usar nombres de variables, y escribiremos: mov byte ptr [0000],41 En que parte de la memoria, se almacena el valor 41h que contiene X?. Para el programador de un lenguaje de alto nivel como el COBOL o el C, eso no importa, el sistema operativo y el compilador respectivo se encargan de verificar en que parte de la memoria almacena el resultado. Pero en el lenguaje de nivel bajo como el Ensamblador el programador previamente tiene que elegir en que parte de la memoria puede guardar el numero hexadecimal 4116 A expresiones del tipo mov X,41h, en las que a la izquierda de la coma aparece una variable, que es un nombre que comienza con una letra, y a la derecha de la coma aparece un nmero, de ahora en adelante las llamaremos instrucciones de asignacin. 1.4.2. SEGUNDA CAPACIDAD BASICA Cada computadora tiene circuitos electrnicos que son diferentes a la memoria y que se encuentran en la CPU, que se llaman registros y que sirven para hacer aritmtica. Qu clase de aritmtica pueden hacer?. Las cuatro clases de operaciones aritmticas: + - * /. Esto es suma, resta multiplicacin y divisin. Adems de hacer operaciones aritmticas la computadora guarda en memoria los resultados parciales y finales obtenidos con esas operaciones, y tal como lo hace el hombre, requiere almacenar esos datos en un medio fsico para poder manipularlos. Por eso recurre a ciertos recursos electrnicos llamados registros. Por ejemplo si queremos calcular la suma: 3 + 5, utilizamos un medio registro de nombre al el registro ax contiene dos medios registros ah y al y procedemos as: mov al,3 add al,5 ; al = 3 ; al = al + 5

Si quiere calcular 8 3, escribimos: mov al,8 ; al =8 sub al,3 ; al = al 3 Si quiere calcular 3 * 8, en este caso tiene que utilizar dos medios registros de nombres al y bl, y escribimos: mov al,3 mov bl,8 ; al=3 ; bl=8
9

mul bl

; ah:al = 3 * 8

la instruccin mul bl, siempre multiplica el valor que se guarda en al por el valor que existe en bl y el resultado lo guarda en dos medios registros, par que designamos asi: ah:al. Para dividir 10 entre 2, escribimos lo siguiente: mov ah,0 mov al,10 mov bl,2 div bl ; ah=0 ; al=10 ; bl=2 ; al = 8/2=4

la instruccin div bl, siempre divide el valor que se guarda en ah:al por el valor que existe en bl y el cociente se guarda en al, y el resto en ah. 1.4.3. TERCERA CAPACIDAD BASICA Esta capacidad se llama capacidad de interface de entrada/salida y se ejecuta mediante instrucciones de entrada/salida. Cada computadora tiene un medio de comunicarse con Ud. o con la persona que la utiliza. De todas maneras, si nosotros no pudiramos introducir nmeros y obtener resultados, estas mquinas no tendran mucho uso no es cierto?. La forma ms comn de suministrar informacin a la computadora es por medio del teclado y los datos de respuesta los visualizamos en la pantalla. El teclado sirve para leer los datos y poder guardarlos en la memoria de la computadora. En forma opuesta la pantalla sirve para mostrar los datos que se encuentran en la memoria de la computadora. Tanto el teclado como la pantalla estn conectados a la computadora y se les denomina perifricos de entrada y salida. Todos los lenguajes de programacin tienen una manera de leer datos de teclado y escribir datos en la pantalla. El lenguaje Ensamblador realiza las operaciones de entrada y salida utilizando llamadas a interrupciones del sistema operativo. La ms conocida de estas es la interrupcin de nombre int 21h, que tiene varias funciones que vienen especificadas en el valor que tome el medio registro ah. Por ejemplo si ah=1 la interrupcin 21h hace que la computadora lea de teclado un carcter ASCII y lo almacene en el medio registro al, y si ah=2 la interrupcin 21h hace que la computadora escriba en pantalla el carcter ASCII cuyo valor est en dl. Veamos como se hace esto: Si queremos leer el numero 4 de teclado y guardarlo en memoria,
10

debemos utilizar el nombre de una variable, por ejemplo x, que tiene que ser del mismo tamao que al. As escribiremos en lenguaje Ensamblador: mov ah,1 ; ah=1, funcin para leer un carcter de teclado int 21h ; lee el nmero 4 y lo guarda en el medio registro al mov x,al ; almacena el carcter 4 en la variable x en memoria Si ejecutamos este cdigo, nosotros deberemos digitar la tecla con el nmero 4, el nmero 4 se asigna a al y despus se mueve a x que est en memoria. Si queremos escribir en pantalla el nmero 4, que ya tenemos almacenado en memoria en la direccin a la que apunta la variable x, escribiremos este otro cdigo: en pantalla mov ah,2 mov dl,0Ah int 21h mov dl,x int 21h mov ah,4ch int 21h ; se prepara para escribir un carcter ; en dl el salto de lnea ; salta de lnea ; en dl el nmero 4 ; escribe 4 en pantalla ; se prepara para terminar ; termina el programa y pasa el control ; operativo DOS

al sistema

y veremos que la computadora escribe en la pantalla el nmero 4. 1.4.4. CUARTA CAPACIDAD BASICA Esta capacidad se llama capacidad de programa almacenado. Qu es un programa de computadora digital? Una computadora digital es una mquina que explora secuencialmente una informacin almacenada en su memoria, llamada programa, y lo ejecuta siguiendo el principio de Von Neumann. Por eso es que a las computadoras digitales tambin se les llama computadoras de programa almacenado porque para ejecutar un programa tienen que cargarlo ntegramente en la memoria antes de correrlo. Aclaremos este concepto: las computadoras o sistemas de proceso de datos se caracterizan por el proceso digital de la informacin, as como por la diferenciacin en instrucciones (programas) y datos de la informacin ambos representados digitalmente en la memoria principal.
11

Todo programa tiene dos componentes o partes: El primer componente es el algoritmo y el segundo componente son los datos. El profesor Niklaus Wirth --inventor del Pascal y Modula 2-titul a uno de sus ms famosos libros: "Algoritmos + Estructuras de datos = Programas". Pero... Qu es un algoritmo?. Contestamos: "Un algoritmo es un mtodo para resolver un problema en un nmero finito de pasos". Cada paso de un algoritmo se llama sentencia o instruccin. Un ejemplo ilustrativo El siguiente es un programa escrito en lenguaje de mquina mediante el programa debug.exe que escribe en pantalla la palabra algoritmo

programa

1693:100 1693:103 1693:105 1693:107 1693:109

mov dx, 109 mov ah ,9 int 21 int 20 db algoritmo$

algoritmo datos

El algoritmo de este programa contiene 4 instrucciones, empieza en la instruccin: mov dx,109; y termina con la instruccin int 20. La instruccin mov dx,109 se encuentra en la direccin relativa 100, y la seudo instruccin: db algoritmo , se encuentra en la direccin relativa 109, y declara los datos. secuencias de 1s y 0s
Programa Se carga en memoria Datos

MEMORIA

Programa en disco Para comprobar el funcionamiento de este programa, que repetimos est escrito en lenguaje de mquina, lenguaje que es muy semejante al Ensamblador, utilizaremos el programa debug.exe, que est siempre accesible desde el DOS. Para ingresar a su ambiente de desarrollo, haga lo siguiente: Pulse el boton inicio del windows, en el men emergente elija la opcin ejecutar, en la ventana abrir digite cmd y acto seguido ingresar al modo DOS del Windows. Proceda a
12

digitar debug y pulsar la tecla enter, en ese momento aparece un guin esto le indica que ya puede empezar a trabajar con el , debug.exe. Despus del guin digite la letra A y luego pulse la tecla de entrada <ENTER>. La letra a representa al comando Ensamblador para poder ingresar desde el teclado lineas de cdigo en lenguaje de mquina; y a continuacin digite el programa anterior. Seguidamente para correr el programa, se digita el comando (go), y usted ver desplegarse en pantalla la palabra g algoritmo y en la siguiente linea el mensaje Program terminate normally, generado por el programa debug.exe.

El principio de Von Neumann El cientifico hngaro-estadounidense John Von Neumann concibi la computadora digital, como una mquina que cargaba en memoria un programa y lo ejecutaba instruccin por instruccin. Segn el principio de Von Neumann, la ejecucin de cada instruccin comprenda dos tiempos: memoria Tiempo de instruccin Leer la instruccin de que apunta el registro IP Decodificarla, esto es interpretar qu significa cada instruccin Ejecutar la instruccin Guardar los resultados en memoria

Instruccin Tiempo de ejecucin

13

El programa debug.exe, es una herramienta muy apropiada para verificar cmo funciona el principio de Von Neumann, por que a diferencia del comando g (go), que ejecuta nuestro programa a una velocidad tan grande que no nos permite verificar lo que pasa en cada instruccin, por eso recurriremos al comando p (proceed), que nos permite ejecutar el programa instruccin por intruccin, como describimos a continuacin. Comencemos verificando que el programa que digitamos ms arriba est almacenado en la memoria de la computadora. Para ello digitamos el comando u (unEnsamblador, esto es desemsambla los 1s y 0s decodifica y muestra el codigo) y dar entrada y obtendr lo siguiente:

Observe cmo el procesador utilizando el comando u (unEnsamblador), permite verificar el tiempo de instruccin del principio de Von Neuman, ya que decodifica pero sin ejecutar, todos los 1s y 0s contenidos en la memoria y muestra el resultado de esta decodificacin como instrucciones de lenguaje de mquina que figuran en la columna tres y cuatro de la figura anterior. As mismo en la primera columna aparece la direccin de memoria donde se encuentra almacenada cada instruccin y en la segunda columna el contenido de la memoria, interpretado no en 1s y 0s si no en su equivalente hexadecimal. Las instrucciones de mquina que usted ve en pantalla su alcance va ms alla de lo que es el programa que digitamos inicialmente y que abarca, desde el desplazamiento 0100 hasta el 011C., seran las instrucciones que se ejecutaran si se corre el programa con el comando G (Go). Por eso un programa en lenguaje de mquina, obligatoriamente tiene que tener una instruccin int 20, para terminar el programa, caso contrario seguira decodificandoejecutantando todos los 1s y 0s de la

14

memoria. 1.4.5. QUINTA CAPACIDAD BASICA Las computadoras tienen circuitos electrnicos que pueden tomar decisiones simples. La clase de decisiones que pueden hacer los circuitos no es del tipo: "Quin ganar el partido de ftbol que se juega esta noche?" o "Cul es la ciudad ms grande del Per?". Desafortunadamente las computadoras slo pueden decidir la verdad o falsedad de la comparacin de dos nmeros, uno de los cuales o los dos deben estar almacenados no en la memoria si no ms bien en uno de los 13 registros, o tambin medios registros, que ya mencionamos anteriormente, que son unos dispositivos que tienen las computadoras para almacenar datos numricos, tal como lo hace en la memoria, y constituyen dispositivos auxiliares que son muy importantes. Por ejemplo si los medios registros ch y cl, contienen nmeros, la computadora puede saber si cualquiera de las siguientes afirmaciones es verdadera o falsa: (1) ch < cl ( es el numero en ch menor que el numero en cl?) (2) ch cl ( es el numero en ch menor o igual que el numero en cl?) (3) ch > cl ( es el numero en ch mayor que el numero en cl?) (4) ch cl ( es el numero en ch mayor o igual que el numero en cl?) (5) ch cl ( es el numero en ch diferente que el numero en cl?) Si queremos que cuando ch<cl sea verdad se escriba en pantalla el valor de ch, y que cuando ch<cl sea falsa escriba en pantalla primero el calor de cl y despus el valor de ch, en castellano, deberamos especificar lo siguiente: pantalla cl y cl Si ch < cl es verdad entonces escribe en

e n caso contrario escribe en pantalla ch

que traducido al lenguaje Ensamblador y para ch=3 y cl=5, se convierte en mov ah,2 mov ch,5 mov cl,3 cmp ch, cl jl salgo ; ; ; ;

si es menor)

; jl significa jump if less (salta continua con estas instrucciones si es falso

mov dl,ch int 21h mov dl,0Ah int 21h salgo: mov dl,cl int 21h

15

Como en este caso ch<cl es falsa, escribir en pantalla primero el ASCII 5 y a continuacin en la siguiente lnea el ASCII 3. A estas instrucciones que permiten comparar dos nmeros se les llama instrucciones de control o instrucciones de seleccin simple. Para que ms nos sirven las comparaciones?. La respuesta es simple: para controlar la ejecucin del programa; por ejemplo para lograr que un grupo de instrucciones se repita un numero determinado de veces. Esto se estudiar ms adelante con todo detalle. Ya hemos indicado que una vez que todas las instrucciones de programa han sido cargados en memoria, la computadora empieza a ejecutar una instruccin cada vez, desde la primera hasta la ultima, que debe ser una instruccin int 20. Para hacerlo la computadora tiene un dispositivo de almacenamiento magntico, llamado registro IP, que est en la CPU, fuera de la memoria, cuyo contenido indica la direccin de memoria donde est almacenada la instruccin que proximamente se va a ejecutar. Cada vez que se ejecuta una instruccin, el valor de IP se incrementa automticamente para apuntar a la siguiente instruccin a ejecutar. Por ejemplo el siguiente programa ejecuta 299 instrucciones antes de terminar: (las instrucciones mov ax,1 y int 20h, 1 vez, y las instrucciones add ax,1, cmp ax,100 y jl sigo, 99 veces cada una) mov ax,1 sigo: add ax,1 cmp ax,100 jl sigo Int 20

a sigo)

; Compara ax con 100 ; jump if less (si ax < 100 es verdad bifurca

1.4.6. SEXTA CAPACIDAD BASICA Esta capacidad se llama persistencia de los datos. En la mayora de las aplicaciones la capacidad de las computadoras de almacenar y acceder a grandes cantidades de informacin desempea la parte dominante y se considera como su caracterstica principal; su capacidad de contar o computar, es decir, calcular y realizar operaciones aritmticas, en muchos casos se ha vuelto casi irrelevante. Para lograr la persistencia se utiliza un dispositivo de almacenamiento secundario llamado archivo y que no forma parte de la memoria. Para entender esto mejor, hagamos una abstraccin de lo que acabamos de decir. Imaginemos que un archivo es un rectngulo cuyo nombre es DATOS.DAT que est contenido en un disco (ver la siguiente figura) y queremos almacenar el dato numrico 3 en el disco, para utilizarlo posteriormente, entonces escribimos las
16

siguientes instrucciones en lenguaje Ensamblador:

.model small .data arch db 'a:\DATOS.DAT',0 Nhandle dw 0 dato db 33h dato_leido db ? .code main proc mov ax,@data ; lee direccin del segmento de datos mov ds,ax ; guarda esta direccin en el registro ds mov ah,3ch ; se prepara para crear el archivo xor cx,cx ; cx=0, debe tener 0 bytes lea dx,arch ; arch apunta a nombre a:DATOS.DAT int 21h ; crea el archivo mov ah,3dh ; se prepara para abrir el archivo mov al,1 ; ah=1 significa para escritura lea dx,arch ; arch apunta a nombre 'a:\DATOS.DAT' int 21h ; abre el archivo y asigna ax un # (handle) mov Nhandle,ax ; Nhandle = # (nmero asignado a arch) mov ah,40h ; se prepara para escribir archivo con #andel en bx mov bx,Nhandle ; identifica el archivo por su handle mov cx,1 ; en cx el # de bytes a escribir, en este caso 1 lea dx,dato ; en dx la direccin de memoria donde esta el dato a escribir int 21h ; escribe en el archivo, mueve el 3 de memoria a disco mov ah,3eh ; se prepara para cerrar archivo con #handle en bx mov bx,Nhandle ; identifica al archivo por su handle int 21h ; cierra el archivo mov ah,4ch ; se prepara para pasar control al DOS int 21h ; termina y pasa el control al DOS main endp end main

Da
17

to se mueve de memoria a disco programa


X

MEMORIA
3 3

.DAT

datos

DATOS

Cuando se ejecuta las dos ultimas instrucciones: mov ah,4ch y int 21h, el programa termina y se descarga de memoria, y por tanto el dato, que es el nmero 3, que estaba almacenado en memoria se pierde y nunca ms lo podremos recuperar. Pero si cargamos en memoria y luego ejecutamos el siguiente programa: .model small .data arch db 'a:\DATOS.DAT',0 handle dw 0 dato db 33h dato_leido db ? .code main proc mov ax,@data ; lee direccion del segmento de datos mov ds,ax ; guarda la dirrecion en ds dx mov ah,3dh ; se prepara para abrir un archivo que apunta ; al = 0 significa para lectura ; dx apunta a nombre 'a:\DATOS.DAT', ; abre archivo y asigna en ax (# ; Nhandle = # handle ; se prepara para leer archivo de #handle ; Identifica en bx el #handle ; bytes a leer 1 ; dx= direccin de memoria donde ; lee archivo, mueve dato de disco a ; dl = dato leido de archivo ; se prepara para escribir ASCII dl en ; escribe ASCII de dl en pantalla
18

mov al,0h lea dx,arch int 21h handle) mov Nhandle,ax mov ah,3fh en bx mov bx,Nhandle mov cx,1 lea dx,dato_leido guardar dato que lee int 21h memoria mov dl,dato_leido mov ah,2 pantalla int 21h

mov ah,4ch int 21h main endp end main

; se prepara para terminar ; termina y pasa el control al DOS

El resultado logrado sera que el dato numrico 3 que esta en el archivo A.\DATOS.DAT se lee y se guarda en memoria en dato_leido, este se mueve a dl y luego se muestra en la pantalla de la computadora, es decir que en esta forma hemos recuperado el valor del nmero 3, creado con el primer programa y grabado en el archivo, que de otra forma se hubiera perdido para siempre. programa MEMORIA
y 3

DATOS.DAT disco
3

dato se mueve de disco a memoria

1.4.7. SETIMA CAPACIDAD BASICA Concepto de reutilizacin La mayora de los programas se construyen a medida en vez de ensamblando componentes existentes. Considere, como comparacin, la forma en que se disea y fabrica el hardware de una computadora. El ingeniero de diseo construye un esquema sencillo de circuitera digital, hace algn anlisis fundamental para asegurar que se realiza la funcin adecuada y va al catalogo de ventas de los componentes digitales existentes. Cada circuito integrado tiene un nmero de pieza, una funcin definida y validada, una interfaz bien definida y un conjunto estndar de criterios de integracin. Despus de seleccionar cada componente, puede ordenarse la compra. Por desgracia los programadores no disponen del lujo descrito anteriormente. Con unas cuantas excepciones, no existen catlogos para componentes de software. Es posible pedir software ya hecho, pero solo como una unidad completa, no como componentes que pueden reensamblarse en nuevos programas. Aunque se ha escrito mucho sobre la reutilizacin del software, hasta el momento se han conseguido pocos xitos tangibles, los ms
19

importantes son: las bibliotecas de subprogramas en la programacin tradicional, casi en desuso, y ahora ltimo, las bibliotecas de clases en la programacin orientada a objetos y el reuso de cdigo binario de una aplicacin, que son piezas reusables de cdigo que se llaman componentes, y la habilidad para usar componentes, para intercomunicarse, se llama interoperatibilidad. Es decir las formas de reuso que existen son las siguientes: objeto) Programacin tradicional ( libreras estticas de mdulos

Reuso Programacin de cdigo fuente ( librerias de clases componentware) Orientada a Objetos de cdigo binario de una aplicacin ( componentes binarios dinamicos) La reutilizacin que describiremos a continuacin, es la de bibliotecas de subprogramas, utilizando un subprograma de nombre fsqrt, que obtiene la raiz cuadrada de un nmero Un ejemplo concreto sobre la reutilizacin La computadora como hemos dicho anteriormente solo puede hacer aritmtica simple: sumar, restar, multiplicar y dividir. Si nos encontramos con el problema de calcular la raz cuadrada de un nmero, cmo resolvemos el problema?. Muy sencillo, recurrimos a la capacidad bsica de la computadora: la reutilizacin. El siguiente es un programa en lenguaje Ensamblador que calcula la raz cuadrada de cualquier nmero ledo de teclado, digitado con formato flotante:

; Programas Ejem07B.asm y Ejem07BCap_Bas7Reutilizacin.asm .model small .386 .data x dq ? mensa1 db 'Ingrese un numero: $' mensa2 db 'Raiz cuadrada : $' .code extrn crlf:near,lee_float:near,escribe_float:near main proc mov ax,@data mov ds,ax
20

lea dx,mensa1 mov ah,9 int 21h call lee_float mov dword ptr x,eax mov dword ptr x+4,edx call crlf lea dx,mensa2 mov ah,9 int 21h finit fld x fsqrt ; obtiene la raiz cuadrada de x fst x mov eax,dword ptr x mov edx, dword ptr x+4 call escribe_float mov ah,1 int 21h mov ah,4ch int 21h main endp end main La instruccin que utiliza la capacidad de reutilizacin es fsqrt;. Aqu el nombre de variable fsqrt, es el nombre de una funcin que calcula la raz cuadrada de x. Lo que estamos haciendo es simplemente reutilizar un programa que calcula la funcin fsqrt (raz_cuadrada en aritmtica flotante), que ya fue escrito y probado anteriormente por otro programador. No es necesario que nos desgastemos en escribir este programa, lo que tenemos que hacer es reutilizarlo. Para que reinventar la rueda si ya existe?. Es lgico que podemos disear un programa en Assembler u otro lenguaje para calcular la raiz cuadrada de un nmero flotante. Podemos afirmar que programar en Ensamblador, utilizando las librerias estticas de objetos, es un caso concreto de reutilizacin. Para programar en Ensamblador, usando estas libreras, hay que conocer las instrucciones de mquina y las instrucciones de Ensamblador, saber cmo declarar variables, construir expresiones, conocer las estructuras de control y adquirir los conocimientos fundamentales de sus capacidades de controlar la ejecucin de ciclos de repeticin. Consecuentemente, el conocimiento del lenguaje Ensamblador es de suma importancia, ya que de lo contrario difcilmente podremos escribir nada de cdigo, y eso es lo que pretendemos con este libro: empezar desde 0.

21

CAPITULO II

El entorno del programa Debug.exe

2.1 Introduccin.
Lo primero que tenemos que hacer, es aprender cules son los pasos para programar en lenguaje de mquina, que es el lenguaje ms cercano a la computadora o sea del nivel ms bajo, en relacin a todos los lenguajes de programacin que existen y que tambin se les llama lenguajes artificiales y que son de alto nivel porque estn
22

ms cerca de los lenguajes que emplea el hombre, tales como el espaol, el ingls, etc. a los que se les denomina lenguajes naturales. Empezaremos a familiarizamos con el entorno del debugger. Esto es, utilizaremos el programa que se llama debug.exe, al que hemos hecho referencia en el primer captulo, pero de forma muy superficial. Este programa nos servir para ensamblar y ejecutar nuestros primeros programas. El nombre de debugger, proviene de bug que es un trmino muy utilizado en ingls para describir una falla en la secuencia de instrucciones de un programa, que impide a ste operar correctamente. Dicha falla puede ser desde un error sintctico hasta un error lgico. Por lo tanto depurar es la accin de corregir dichas fallas, y es uno de los tantos usos que se le da al debug.exe. El debug.exe es una utilera que nos ayuda a realizar tres tareas: Ver el contenido de las memorias RAM y ROM. Ejecutar un programa, ya sea en su totalidad o de una en una instruccin. Ensamblar y ejecutar programas sobre la marcha. Usando el debug.exe podremos trabajar inmediatamente con las instrucciones de mquina sin necesidad de conocer todos sus requerimientos formales, para as darse cuenta de su podero y potencial.

2.1 Elementos iniciales del programa Debug.exe


Se puede iniciar debug.exe, en la siguiente forma:
1.

Pulsar el botn Start (Inicio) del Windows. En el men emergente elija la opcin Run (Ejecutar). En la ventana Open (Abrir) digitar debug.exe y pulsar botn OK (Aceptar). En forma inmediata el Windows muestra en pantalla un guin ( como indicacin que se ha cargado en memoria el ) programa debug.exe Para crear un archivo o examinar memoria, teclee debug sin especificar ningn nombre de archivo: debug <enter>

2.

3. Para modificar o depurar un programa (.COM o .EXE) o para modificar un archivo cualquiera o por ejemplo, modificar el programa prueba.com, que se encuentra grabado en un disquete, teclee debug con una especificacin de archivo, como debug a:prueba.com. <enter> El DOS carga a debug.exe en la memoria y muestra un guin ( ) como indicacin de que l es el programa almacenado en memoria.
23

A continuacin damos una descripcin de cada comando debug, en orden alfabtico, en los que direccin es un nmero de una direccin en memoria. A (direccin) obligatorio los parntesis indican que el dato direccin es

A significa Ensamblador (del Assembler en ingles). Se utiliza para ingresar cdigo fuente en lenguaje de mquina que es muy cercano al lenguaje Ensamblador, pero que veremos tiene muchas limitaciones, con respecto a este ltimo. D (direccin) D significa Dump en ingls vaciar o dumpear en castellano. Significa volcar el contenido de una parte de la memoria, desplegando en pantalla, este contenido en notacin hexadecimal y/o smbolos ASCII. E (direccin) E significa enter en ingles o ingresar en castellano. Sirve para ingresar datos numricos a memoria en base hexadecimal, de dos en dos dgitos hexadecimales por vez, y la pulsacin del tecla espacio para pasar a los siguientes dos datos. Los datos ingresados se almacenan en la direccin que obligatoriamente tiene que digitarse despus de escribir la letra E. G [direccin] direccin aqu los corchetes indican que es opcional la

G significa go en ingls y correr o ir en castellano. Sirve para ejecutar un programa en lenguaje de mquina que se est examinando, hasta un punto de interrupcin especificado en [direccin] que es opcional. Si no se especifica la direccin, el programa contina hasta terminar. H (nmeros hexadecimales) H significa Hexadecimal. Sirve para mostrar la suma y diferencia de dos nmeros hexadecimales. La longitud mxima de los datos es de cuatro dgitos hexadecimales. N [nombre_del_archivo] N significa name o nombre en castellano. Pone nombre a un programa o archivo que se desea grabar en disco. P [direccin] [valor]

24

P significa proceed en ingles o procedimiento en castellano. Efecta una llamada a una subrutina (call), iteracin (loop), interrupcin (int) o repite una cadena de instruccin (REP) hasta la siguiente instruccin. El formato general es: P [direccin] [valor], donde direccin es un nmero que da la direccin de inicio que es opcional y valor es el nmero de instrucciones, tambin opcional, para proceder con ellas. Si no se especifica la direccin se ejecuta la instruccin a la que est apuntando el registro IP, registro que describiremos ms adelante. Q Q significa Quit en ingles quitarse o salir en castellano. Sirve para salir del ambiente de trabajo del Debug.exe R [nombre_de_registro]

R significa Register en ingles o registro en castellano. Sirve para desplegar el contenido del registro que figura en nombre_de_registro y abre la opcin de modificar su valor. Si no se especifica [nombre_de_registro], despliega todos los registros sin opcin al cambio de sus contenidos. T [direccin][valor]

T significa Trace en ingls o rastreo en castellano. Ejecuta un programa en modo de un solo paso. La entrada opcional [direccin] le indica a debug.exe en donde inicia el rastreo y el valor opcional le indica el nmero de instrucciones por rastrear. La omisin de los operandos provoca que debug.exe ejecute la instruccin siguiente a la que apunta el registro IP. U [direccin o rango] U significa en ingls Unemsamble o desensamblar en castellano. Desemsambla instrucciones de mquina. El registro por omisin es la pareja CS:IP. Y si se omite la direccin o el rango desensambla 32 bytes desde el ultimo U si hubo uno previo. W [direccin [unidad sector_inicial nmero_de_sectores]] W significa en ingls write y en castellano escribir. Graba en disco un archivo con las caractersticas de nombre y tamao, previamente indicadas. Si no se utilizan operandos, anticipadamente hay que poner nombre al archivo con el comando N, y el nmero de registros con el comando R CX, que permite ingresar como valor en el registro CX, el nmero de bytes a grabar PASOS PARA PROGRAMAR EN LENGUAJE DE MAQUINA CON EL
25

DEBUG.EXE Ejemplo 0 El siguiente programa, es clebre por que era el primer ejemplo que apareca en 1978 en el primer libro para aprender a programar en C, escrito por Kermighan y Ritchie, titulado The C Programming Language, que atrajo gran atencin sobre este lenguaje, y que se convirti en uno de los libros cientficos de computadoras de ms xito de todos los tiempos: Void main() { printf(Hola mundo); getch(); } Escribamos este programa en lenguaje de mquina siguiendo los siguientes pasos (trabajando con Windows 2000):
PRIMER PASO

Este paso ya fue descrito anteriormente. Comenzamos pulsando el botn Start (Inicio) del Windows. En el men emergente elija la opcin Run (Ejecutar). En la ventana Open (Abrir) digitar debug.exe y pulsar botn OK (Aceptar). En forma inmediata el Windows muestra en pantalla un guin ( como indicacin que se ha ) cargado en memoria el programa debug.exe
SEGUNDO PASO

A la derecha del guin digite la letra A y pulse la tecla enter (entrada). A continuacin digite el siguiente cdigo una instruccin por lnea seguida de un enter para pasar a la siguiente lnea: A <enter> mov dx,109 <enter> mov ah,9 <enter>

cadena

el $ significa fin de

int 21 <enter> int 20 <enter> db Hola mundo, desde el Assembler!$ <enter> <enter>

El ltimo <enter> le sirve para salir del modo A (Ensamblador), que slo se utiliza para ingresar o modificar cdigo fuente.
TERCER PASO

Verifique que el cdigo digitado es idntico al que figura ms arriba. No se olvide del smbolo $ en la ltima instruccin, antes de la doble comilla. Para correr el programa digite G (Go) y el programa se ejecutar sin ningn problema, siempre y cuando no haya cometido un error al
26

ingresar el cdigo. El resultado ser el siguiente: En la pantalla aparece el mensaje: Hola mundo, desde el Assembler! Y a continuacin un mensaje del DOS, indicando que el programa se ejecut normalmente: Program terminated normally
CUARTO PASO

Procedemos a dar un nombre al programa y grabarlo en disco, ejecutando lo siguiente: Digite N Ejem00.com <enter>, siendo Ejem00.com el nombre que hemos elegido para el programa que est en memoria. Establezcamos el tamao en bytes que va a tener el archivo en disco. Como el desplazamiento va desde cs:100 hasta cs:012B, sumamos 1 a la diferencia de 012B menos 0100, y obtenemos 2C bytes (= 012B - 0100 + 1) de longitud del programa. En el sistema decimal esto equivale a 2*16+12 = 44 bytes. Por tanto este tamao se guarda en el registro cx. Debido a eso es que utilizamos el comando R CX <enter> y luego se digita el valor calculado 2C y se da <enter>. A continuacin grabamos el programa prueba.com en disco, digitando W sin ningn operador. El DOS con el mensaje Writing 0002C, nos avisa que ha grabado el archivo en disco.
QUINTO PASO

Podemos verificar el programa que est almacenado en memoria utilizando el comando: U (UnEnsamblador). Pero para que no aparezca ms informacin que la que se necesita digitamos: U 100 109, que comprende el cdigo que v desde el desplazamiento 100 hasta el 109, como se ve en la siguiente pantalla:
SEXTO PASO

Para salir digitamos Q (quit) y retornamos al panel principal del Windows.

27

Ejecucin del programa Ejem00.com desde el DOS Si deseamos volver a ejecutar el programa Ejem00.com, pero ahora desde el DOS, sin recurrir al debug.exe, procedemos en la siguiente forma:
PRIMER PASO

Pulsar el botn Start (Inicio) del Windows. En el men emergente elija la opcin Run (Ejecutar). En la ventana Open (Abrir) digitar cmd y pulsar botn OK (Aceptar). En forma inmediata el Windows muestra la pantalla del sistema operativo DOS.
SEGUNDO PASO

Verifiquemos si el programa prueba.com se encuentra en el disco duro, digitando: dir Ejem00.com, si este programa est en el disco muestra su nombre, tamao y fecha de creacin. Si no lo encuentra despliega un mensaje de error, y tiene que vol ver a ejecutar todo el procedimiento que se ha descrito.
TERCER PASO

Para ejecutar el programa Ejem0.com, digite solamente el nombre Ejem00, no es necesario utilizar la extensin .com. Acto seguido el programa muestra en pantalla el mensaje: Hola mundo, desde el Assembler! La siguiente pantalla muestra el resultado de correr el programa

28

Ejem0.com:

NOTACION SIERRA Cuando tengamos escritos varios programas Ejem00.com, Ejem01.com, . . . , Ejem12.com, . . . , Ejem26.asm, ..., etc., en el caso particular de uno de ellos, por ejemplo, el nombre Ejem00.com, del programa que acabamos de crear con el debug.exe, no nos dice nada referente a lo que hace el programa, y esto nos puede traer a confusin. Para evitar esto, recurrimos a la facilidad que nos da el Windows, que nos permite utilizar nombres de hasta 255 caracteres, usando la llamada notacin sierra, en alusin a los dientes de una sierra, que consiste en escriber el nombre de un archivo, empezando cada palabra del nombre del archivo con una letra mayscula. En esta forma mantendremos para cada programa dos nombres: el primer nombre que es permitido por el DOS, con un mximo de 8 caracteres para el nombre y 3 caracteres para la extensin, y el segundo nombre, que es permitido por el Windows, con notacin sierra, que nos recuerde lo que hace el programa. As por ejemplo para el caso del programa Ejem00.com conservaremos este nombre y este otro en notacin sierra: Ejem00EscribeHolaMundo.com. Para obtener este ltimo digitamos lo siguiente: Copy Ejem00.com Ejem00EscribeHolaMundo.com El de notacin corta Ejem00.com nos sirve para ejecutarlo, digitando simplemente: Ejem00 <enter> As mismo, si deseamos modificar o depurar el programa Ejem00.com recurrimos al programa debug.exe escribiendo:

29

debug Ejem00.com <enter>. En cambio el otro con nombre ms largo, nos sirve para indicarnos lo que hace el programa; en este caso concreto el nombre que le hemos asignado nos recuerda que este programa escribe en pantalla el mensaje hola mundo desde el Ensamblador. Si por alguna circunstancia ha perdido el Ejem00.com, pero conserva el que tiene nombre en notacin sierra, puede recuperar el primero escribiendo: copy Ejem00*.com Ejem00.com <Enter> y quedar recuperado el programa Ejem00.com

2.2. Los recursos de la programacin en lenguaje de mquina y en lenguaje Ensamblador:


La filosofa de los que disearon el lenguaje Ensamblador tiene que ser muy diferente de la que utilizaron los diseadores de los lenguajes de alto nivel. Esto se ha hecho as en estos ltimos, para aumentar la productividad del programador. La sintaxis de un lenguaje de alto nivel, presenta al programador instrucciones que son potentes, si se comparan con las del Ensamblador. En promedio, por cada instruccin de un lenguaje de alto nivel se generan de 10 a 20 instrucciones de mquina. En cambio por cada instruccin del Ensamblador se genera una sola instruccin de mquina. Por eso programar en Ensamblador es completamente diferente a cmo se hace en un lenguaje de alto nivel, cuya sintaxis debe aproximarse lo ms posible al idioma ingls mientras ms se aproxima al lenguaje natural que es el ingls, mayor es su nivel y ms aceptacin tendr en los programadores; el COBOL naci con esta filosofa, que es el lenguaje humano, en el que se codifican las instrucciones de los programas fuente de casi todos los compiladores que existen en el mercado. Si se entiende bien cul es la filosofa de la programacin en Ensamblador, mayores posibilidades de xito se tendr en la difcil tarea de programar en este lenguaje. Un programa en lenguaje Ensamblador es un cdigo que combina, de la forma ms optima posible, la utilizacin de los siguientes cuatro recursos: (1)Memoria

30

(2)Registros (3)Interrupciones y (4)Instrucciones de Ensamblador. Pasamos a describir cada uno de ellos:

2.3. Memoria
La memoria es uno de los principales recursos de las computadoras digitales. Ms adelante comprobaremos que la primera, segunda, cuarta y quinta capacidades bsicas de la computadora tienen que ver con la memoria. La memoria es un dispositivo electromagntico, que permite almacenar los datos tratantes que son las instrucciones y los datos tratados que son los datos propiamente dichos. Cuando se ejecuta un programa los datos tratantes interactan con los datos tratados para producir nuevos datos tratados, que son los que se devuelven al usuario del programa. Lo que se almacena en la memoria son 1s y 0s, y sabemos que cada una unidad de almacenamiento que almacenan estos 1s y 0s se llama bit. As la cadena 101111102, requiere 8 bits para almacenarse en memoria. El tamao de la memoria, que por ser un medio de almacenamiento fsico, tiene un tamao finito, es igual al nmero de bits que puede contener, es decir cuntos 1s y/o 0s puede almacenar. Como este nmero que da el tamao es muy grande, se recurre a utilizar unidades de almacenamiento ms grandes que el bit. Estas unidades son: 1 nibbel que tiene 4 bits 1 byte que tiene 8 bits 1 kbyte (kilo byte) que tiene 210 bytes = 1,024 bytes = 8,192 bits 20 1 Mbyte (mega byte) que tiene 2 bytes = 1,024 Kbytes = 1,048,576 bytes = 8,388,608 bits 1 Gbyte (giga byte) que tiene 230 bytes = 1,024 Mbytes = 1,048,576 Kbytes
31

= 1,073,741,824 bytes 1 Tbyte (tera byte) que tiene 1024 Gbytes = bytes 1,048,576 MBytes 1,099,511,627,776 bytes

240 = =

Recordemos que en el sistema mtrico 1 kilo, significa 1000 = 10 3, en cambio en informtica 1 kilo equivale a 1,024 = 210, aproximadamente 1000, pero no 1000. Supongamos que la memoria tiene 1 Mbyte =1,048,576 bytes =8,388,608 bits, esto es tiene aproximadamente 1 milln de bytes es decir 8 millones de bits. Es necesario entender que todos los bits tienen que estar interconectados, para poder guardar y recuperar ya sea el 1 o 0 que tenga almacenado; el hecho es que tenemos que poder dirigirnos a la direccin de memoria a nivel de bit. Para simplificar esto, se ha convenido en utilizar el byte como medida de direccionamiento, y cada byte se le asigna un nmero hexadecimal que es su direccin, que va desde el primer byte al que se le asigna la direccin que es el nmero hexadecimal 00000 16 hasta la direccin FFFFF16 que corresponde al ultimo byte 1,048,576.
2.3.1

Direccionamiento absoluto Direccionamiento segmento:desplazamiento

segementado. segmentado
representar una

Haciendo una abstraccin, podemos entonces memoria RAM de 1 Mbyte en la siguiente forma: Direccin 0000016 0000116 0000216 0000316 0000416 0000516 0000616 0000716 0000816 0000916 0000A16 0000B16 Byte No. 1 2 3 4 5 6 7 8 9 10 11 12

32

... 8D29816 8D29916 8D29A16 8D29B16 FFFFC16 FFFFD16 FFFFE16 FFFFF16

...

...

...
1

... 578,200 578,201 578,202 578,203

1,048,573 1,048,574 1,048,575 1,048,576

...

Esta forma de direccionar se llama direccionamiento absoluto. Vemos entonces que para direccionar a todos los bytes de una memoria RAM, de 1 Mbyte, requerimos nmeros hexadecimales de 5 dgitos. Como cada nmero hexadecimal tiene 4 bits, para direccionar a la memoria requerimos 4 x 5 = 20 bits. Pero como veremos ms adelante los registros del 8086 tienen 16 bits, entonces los diseadores del procesador Intel 8086, tuvieron que ingeniarse y recurrieron al direccionamiento segmentado. Para ello imaginaron la memoria dividida en segmentos de 64 Kbytes. A estos segmentos los numeraron desde 000016 hasta FFFF16, usando nmeros de 4 hexadecimales que requieren 16 bits = 2 bytes para designarlos, y estos 16 bits si se pueden almacenar en los registros de segmento. A los bytes de cada sector de 64 Kbytes, los numeraron desde 000016 hasta FFFF16; a esta direccin le llamaron offset en ingls (o desplazamiento en castellano). Al hacer esto para direccionar la memoria se requieren dos datos: el nmero del segmento y el desplazamiento u offset dentro de este segmento . En esta forma la direccin en memoria de cualquier byte la designaremos con dos valores: segmento:desplazamiento, a este tipo de direccionamiento lo llamaremos direccionamiento segmentado con relacin al direccionamiento absoluto, que solo requiere un solo dato numrico. Toda la programacin que hagamos en este libro de Ensamblador, la haremos utilizando el direccionamiento segmentado segmento:desplazamiento, el sistema operativo se encargar de convertir la direccin segmentada a direccin absoluta que es la real. Es fcil deducir la siguiente frmula, que convierte la direccin segmentada a direccin absoluta o real: Segmento16:desplazamiento16 desplazamiento16 (*) = segmento16 * 1016 +

Aunque parezca increble, esta forma de direccionamiento produce overlaps de segmentos (sobre posicionamiento en castellano). Por suerte el sistema operativo es el que maneja la distribucin de memoria cuidando que los overlaps no produzcan problemas de sobreposicionamiento de datos en la memoria. Pasamos a ver unos ejemplos y verificar esto utilizando el programa debug.exe
33

Ejemplo Convertir las direcciones segmentadas, que se dan a continuacin, a direcciones absolutas. Las direcciones estn dadas en base hexadecimal. ( 1 ) 0000:0010 ( 2 ) 0001:0000 ( 3 ) 0000:1050 ( 4 ) 0070:0950 ( 5 ) 0100:0050 ( 6 ) 0105:0000 Solucion: Aplicando la frmula (*) se tiene sin considerar los ceros a la izquierda de los datos numricos: ( 1 ) 0000:0010 = 016 * 1016 + 1016 = 10 = 0001016 ( 2 ) 0001:0000 = 116 * 1016 + 016 = 1016 + 0 16 = 0001016 ( 3 ) 0000:1050 = 016 * 1016 + 105016 = 016 + 1050 ( 4 ) 0070:0950 = 7016 * 1016 + 95016 =70016 + 950 ( 5 ) 0100:0050 = 10016 * 1016 + 5016 = 100016 + 50
16

= 0105016 = 0105016 = 0105016


16

16

16

( 6 ) 0105:0000 = 10516 * 1016 + 000016 = 105016 + 0000

= 0105016

Observamos que las direcciones segmentadas (1) y (2) a pesar que estn en diferentes segmentos, tienen la misma direccin absoluta 0001016, es decir la direccin real. Se afirma lo mismo con respecto a las direcciones segmentadas (3), (4) , (5) y (6), las cuatro apuntan a la misma direccin absoluta 0105016. Eso es lo que pasamos a probar:

34

Offset Direccin Absoluta


Segmento 0 0000 0001 0002 0003 0000 0001 00000 00001 00002

...
00010

Segmento 1

...

...

0010

1050 ... FFFF Segmento 70 0000 0001 0002 FFFE FFFF

0104F 01050 01051

...

...

0950 Segmento 100 0000 0001

...

0050 Segmento 105 0000 0001

...

...

...
FFFD FFFE FFFF

...
FFFFD FFFFE FFFFF

Prueba del overlap utilizando el debug.exe Con el debug.exe probaremos la sobreescritura (overlap) de las direcciones segmentadas 0070:0950 y 0100:0050. Para hacerlo proceda as:
PRIMER PASO

Pulsar el botn Start (Inicio) del Windows. En el men emergente elija la opcin Run (Ejecutar). En la ventana Open (Abrir) digitar

35

debug.exe y pulsar el botn OK (Aceptar). En forma inmediata el Windows muestra en pantalla un guin () como indicacin de que se ha cargado en memoria el programa debug.exe
SEGUNDO PASO

A la derecha del guin digite -D 70:950 <enter>. El debug volcar el contenido de la memoria a partir de la direccin segmentada, y podr observar que esa direccin de memoria contiene el valor 00 16. Procedamos a cambiar el valor 0016 por el valor CA16. Para hacerlo procedemos as: Digite el comando E 70:950 <enter> y luego CA <enter>. A continuacin digitando D 100:50 <enter>, podr verificar que en esta direccin est almacenado el dato CA16 Todo esto se puede apreciar en la siguiente figura:

2.4. Disposicin de la memoria Cada vez que se prende la computadora digital la memoria no contiene nada, por que debido al carcter electromagntico de los componentes de la computadora, todo se destruy cuando anteriormente se apag el sistema. Al comenzar a trabajar la computadora con la memoria vaca, mediante un pequeo programa que se encuentra en el disco duro de la mquina, llamado boot strap, el sistema operativo que administra la memoria, empieza colocando todos los componentes RAM y ROM del sistema operativo
36

en la memoria. Cuando se termina de cargar todos los componentes que necesita la computadora para operar, la memoria queda distribuida en la siguiente forma: Direccin real 00000 00001 interrupcin y DOS 00600 aplicacin 0FFFF 9FFFF operativo DOS A0000 ... exp. pant BFFFF pantalla C0000 CFFFF D0000 ... expandida DFFFF E0000 ... Tabla de serv. de interr. Area de programas transitorios Area de programas de usuario - Vectores de

- Area datos BIOS Programas de

- Manejadores Sistema - Memoria de Memoria de

128 Kbytes pantalla Area de ROM 64 Kbytes memoria expandida Areas del sistema 384 Kbytes

Memoria

FFFFE FFFFF Memoria extendida

- ROM red - ROM disco - Memoria de video - Bios ROM

2.5. Registros El procesador 8086 tiene 14 registros de 16 bits (pueden contener nmeros hexadecimales de hasta 2 digitos), que son un recurso muy importante e imprescindible para almacenar datos que no se encuentran en la memoria. Incluso se pueden hacer programas muy pequeos sin necesidad de recurrir a la memoria para almacenar los datos intermedios. Adems la programacin usando solo registros es
37

ms rpida que aquella similar usando memoria y registros. Prcticamente los registros sirven para llevar el control de todo lo que sucede dentro de la PC. Los registros pueden contener datos o direcciones de memoria. Dichos registros continuacin: se dividen en seis categoras como vemos a AX AH-AL BX BH-BL CX CH-CL contador de bucles SS

- De propsito general DX (datos y direcciones) DH-DL datos de oper. aritm. - De segmentos ES (direcciones) Extra Segment dir. extras - Punteros de pila (direcciones) - De indices (direcciones ) CS Code Segment dir. del cod.

acumulador base oper. aritm. Offset DS

Data Segment Stack Segment dir. de dat. BP Base Pointer DI Destination Index dir. de pila

SP Stack Pointer SI Source Index

- Puntero de instrucciones IP (direcciones) Instruction Pointer - Un registro de indicadores de estado (flags o banderas), sin nombre lgico Pasamos a describir estos registros con mayor detalle: ( 1 ) 4 registros de propsito general. Que contienen datos y/o direcciones: DX DH AX AH DL AL BH BX BL CH CX CL

Estos cuatro registros son duales , es decir, pueden manipularse como si fueran de 8 o 16 bits: En la modalidad de 16 bits son conocidos como AX, BX, CX y DX. En la modalidad de 8 bits se les reconoce como AH, AL, BH, BL, CH, CL, DH y DL. Siendo la parte alta

38

la que figura con la letra H (high en ingls) y la parte baja la que figura con la letra L (low en ingls). El registro AX, como iremos aprendiendo cuando empecemos a programar, tambin llamado acumulador, resulta indispensable para toda operacin de entrada/salida, trabajando en conjuncin con las interrupciones, y para algunas operaciones de cadenas. El registro BX, tambin conocido como registro base, se usa para calcular direcciones que accesan a la memoria. El registro CX o contador es usado para llevar la cuenta en operaciones repetitivas, o como contador en iteraciones que pueden involucrar o no operaciones sobre cadenas. Tambin sirve como contador en operaciones relacionadas con bits individuales. Finalmente se tiene el registro DX, tambin conocido como registro de datos, cuya finalidad es servir como depsito de las direcciones de los puertos. En combinacin con el registro AX, se utiliza para almacenar nmeros de 32 bits (DX:AX) en la multiplicacin y divisin. Otra aplicacin de este registro es con las operaciones de interrupciones, durante las cuales conserva el desplazamiento u offset del bloque de informacin que ser manejado. El registro DX, generalmente se usa en combinacin con el registro DS, como DS:DX. (2) Los registros de segmento

El procesador tiene cuatro registros de 16 bits llamados registros de segmentos. El CS (code segment) o registro del segmento de cdigo se encuentra asociado al cdigo del programa; apunta al segmento que contienen el cdigo o datos tratantes; es decir, controla el cdigo de los programas y tiene como socio al registro IP en el sentido que la combinacin CS:IP, es la direccin de la prxima instruccin a ejecutar. El DS (data segment) o registro del segmento de datos, contiene la direccin del segmento donde se guardan los datos propiamente dichos o datos tratados. El ES (extra segment) o registro de segmento extra generalmente tiene la funcin de servir de colchn para ampliar el segmento de datos. El SS (stack segment) o registro del segmento de pila tiene la funcin de controlar el rea de la memoria donde se crear la pila. Todo esto se puede apreciar en la siguiente figura: memoria 00000 00001 ... 0016F
39

direccin

CS = 0017

00170 00171 ... 1016F

64 kbytes de cdigo ...

DS = 1028

1027F 10280 10281 ... ? 31000 31001 .. ?

64 kbytes de datos

SS = 3100 pila

64 kbytes de datos de la

ES = 5000

50000 50001 ... 5FFFF FFFFE FFFFF

64 kbytes de datos extras

Los registros DS, CS, SS y ES, son primordiales para generar la direccin de 20 bits que se pondr en el bus de direcciones de la CPU. Cualquier operacin que accese la memoria usar forzosamente uno de estos registros. Cada registro selecciona un rea que puede ser contigua o no, de hasta FFFFh bytes de tamao o sea: FFFFh bytes=164 bytes=216 bytes=26x210 bytes =64x210 bytes=64 KBytes=65536 bytes Toda instruccin utiliza los registros de segmentos con algn desplazamiento interno para acceder a la informacin, como aprenderemos cuando empecemos a programar. No es necesario utilizar los cuatro registros de segmento; el que si es imprescindible es el segmento de cdigo. Si no est este segmento, sencillamente no hay programa. ( 3 ) Los registros de apuntadores de pila BP SP

40

Como su nombre lo indica, son registros que apuntan a alguna localidad de memoria en general, como se ve en la figura de ms arriba que apunta al segmento 310016. El BP (base pointer) o apuntador base es muy usado para manipular la informacin que se encuentra en la pila. Una de sus principales utilidades es proveer un mecanismo para poder pasar parmetros a rutinas. El SP (stack pointer) o apuntador de pila, sirve para apuntar al comienzo de la pila, y el BP da el desplazamiento u offset de la pila. ( 4 ) Los registros ndice SI DI

Estos registros generalmente se utilizan en operaciones con cadenas. Un uso muy comn de ellos es a travs de la instruccin MOVSB (move string byte), la cual copia bytes consecutivos a partir de la direccin especificada por SI (source index) o ndice fuente en la direccin especificada por DI (destination index ) o ndice destino. Tambin tiene uso en otro tipo de operaciones, como el clculo de direcciones o el pase de parmetros a otras rutinas. ( 5 ) El registro apuntador de instrucciones IP

El IP (intruction pointer) o apuntador de instrucciones, se usa en combinacin con el registro CS, para especificar el rea de memoria donde se encuentra la siguiente instruccin por ejecutar. Este registro cambia de contenido conforme al flujo de ejecucin del programa. Los programas no pueden manejar directamente a este registro, pero si lo pueden hacer de forma indirecta mediante instrucciones de bifurcacin (quinta capacidad bsica). ( 6 ) El registro de banderas Este registro no tiene nombre lgico como los otros registros CS, DS, etc., nombre que se podra utilizar en el programa fuente. Es un registro de 16 bits -de los cuales slo se utilizan 9-, que reporta el status o resultado de alguna operacin aritmtica o lgica. Hay nueve banderas: Seis banderas de estado Registran el estado del procesador, normalmente asociado a
41

una comparacin o una instruccin aritmtica. - Bandera de acarreo. Indica acarreo en las instrucciones aritmticas. OF (Overflow flag) Bandera de desbordamiento (aritmtico) ZF (Zero flag) Bandera de resultado cero o comparacin igual SF (Sign flag) - Bandera de resultado o comparacin negativa PF (Parity flag) - Bandera de paridad (nmero par de bits) AF (auxiliar flag) - Bandera auxiliar. Indica si hay necesidad de ajuste en las operaciones aritmticas con nmeros BCD (decimal codificado en binario) Tres banderas de control. Registran el modo de funcionamiento del procesador. DF (Direction flag) - Bandera de direccin. Controla la direccin (hacia delante o hacia atrs) en las operaciones con cadenas de caracteres incrementando o decrementando automticamente los registros ndices SI y DI. - Bandera de interrupciones. Indica si estn permitidas o no las interrupciones de los dispositivos externos. - Bandera de atrape. Controla la operacin modo de paso a paso (usada por el programa debug.exe) CF (Carry flag)

IF (Interrupt flag)

TF (Trap flag)

Las posiciones de las banderas dentro del registro son: 4 15 3 14 2 13 1 OF 12 0 11 TF 10 SF 9 ZF 8 AF 7 PF 6 5 CF

D IF

Cada bit del registro de banderas tiene dos condiciones: encendido o apagado. En otras palabras, puede ser igual a 1 (cuando est encendido) o igual a 0 (cuando est apagado).

42

A continuacin se describe el significado de cada bit del registro de banderas. Todas las banderas apagadas: NV UP DI PL NZ NA PO NC Todas las banderas prendidas: OV DN EI NG ZR AC PE CY Siendo el significado de los bits: Overflow

NV = no hay desbordamiento OV =si lo hay Direction UP = hacia adelante DN = hacia atrs Interrupts DI = desactivadas EI = activadas Sign PL = positivo NG = negativo Zero NZ = no es cero ZR = si es cero Auxiliary carry NA = no hay acarreo auxiliar AC = hay acarreo auxiliar Parity PO = paridad non PE = paridad par Carry NC = no hay acarreo CY = si hay acarreo

Segmentos y registros asociados En lenguaje de mquina o lenguaje Ensamblador, como la direccin segmentada se compone de registro:desplazamiento, en muchos casos, para simplificar el cdigo, cada segmento tiene asignados uno o ms registros asociados. Por ejemplo, en vez de escribir la instruccin mov ax,DS:[BX], se escribe solamente mov ax,[BX], instruccion en la que [BX], significa desplazamiento. Podemos hacer esto por que el registro DS, tiene al registro BX como uno de sus asociados en la siguiente relacin de registros asociados: ( 1 ) CS ( 3 ) SS IP SP, BP ( 2 ) DS ( 4 ) ES BX, SI, DI BX, SI, DI

2.6. Interrupciones Recordemos que la tercera capacidad bsica de una computadora digital es la capacidad de interface de entrada/salida y se ejecuta mediante instrucciones de entrada/salida. Las interrupciones son el medio que tiene el procesador para realizar
43

operaciones de entrada/salida. De alguna manera, la CPU tiene que estar consciente de lo que sucede a su alrededor. Esta conciencia la adquiere mediante las interrupciones. Cada vez que se oprime una tecla, el teclado interrumpe a la CPU y le dice Oye, tengo algo para ti!. La CPU detiene lo que est haciendo y pone atencin en el teclado y reacciona y ejecuta una predeterminada accin dependiendo de cul tecla ha presionado el usuario. Para cada tecla la CPU reacciona en forma diferente. Algo parecido sucede cuando se quiere escribir un carcter en la pantalla o en la impresora, se produce una interrupcin. Las interrupciones ocurren tan seguido que la CPU necesita un modo eficiente de manejarlas. Una manera de administrar las interrupciones, que se usa en el entorno MS-DOS, es mantener una tabla de vectores (entindase direcciones) en la memoria baja (esto lo explicaremos ms adelante en detalle cuando estudiemos programas residentes TSR). Estos vectores de interrupcin sealan otra localidad de la memoria donde la CPU empezar a ejecutar el cdigo que ah se encuentre. A esta tcnica se llama darle servicio a la interrupcin. Despus de ejecutar esta tarea se retorna a la siguiente instruccin que sigue a la interrupcin. En otras palabras, una interrupcin es una bifurcacin a cierta localidad de la memoria (RAM o ROM) donde la CPU iniciar la ejecucin de una serie de instrucciones, y al terminar regresar a la siguiente localidad de la instruccin que caus la interrupcin. Las interrupciones se dividen en: 1. Interrupciones de hardware (interrupciones externas e internas) Ejemplo el desperfecto de un perifrico o pulsar una tecla. 2. Interrupciones de software o internas Ocurren como resultado de la ejecucin de una instruccin int, o una operacin de divisin que cause desbordamiento, o ejecucin en modo paso a paso, con el debug.exe, con los comandos T o P, por ejemplo. Existen 256 interrupciones de software (numeradas desde el 00h hasta FFh) Las interrupciones de software se dividen a su vez en: ( a ) Interrupciones del BIOS (Basic Input / Output System), que maneja las interrupciones 00h hasta 1Fh. - Controlan los perifricos y a veces funciones de disco ( b ) Interrupciones del DOS (Disk Operating System), que maneja las interrupciones 20h hasta 3Fh. - Administran la memoria y el disco La Interrupciones de DOS generalmente se usan cargando el parmetro de la funcin deseada en el registro AH, invocando la

44

interrupcin 21h. A este proceso se le llama utilizar las funciones del DOS. En la prctica esta interrupcin resulta ser la ms usada. Una razn de ello es mantener la compatibilidad a travs de las futuras versiones del sistema operativo MS-DOS, que sigue siendo parte importante de los sistemas operativos Windows. En esta primera parte, que programaremos en lenguaje de mquina, utilizaremos dos interrupciones: la interrupcin INT 20h que no tiene funciones, y la interrupcin INT 21h, con algunas de sus funciones de AH para los valores 01h, 02h, 08h, 09h, 0Ah, 4Ch, que pasamos a describir: INT 21h AH 01h Funcin

Esperar para leer un carcter del teclado con eco (con chequeo de CTRL-BREAK). Salida: AL = Carcter ASCII, ledo de teclado Escribe en pantalla el carcter ASCII contenido en el registro DL Escribe en pantalla la cadena de memoria direccionada por DS:DX, que debe terminar en $ Lee una cadena caracteres del teclado y los en un rea de memoria. El primer byte del rea, previamente, debe ser distinto de cero e indica el mximo de caracteres a teclear (incluido el retorno de carro). El segundo byte del rea indica el nmero de caracteres tecleados ( sin incluir el retorno de carro). Los datos se almacenan a partir del tercer byte. Direccin de entrada DS:DX Retorno al DOS INT 20h Pasa el control al DOS, en programas COM

02h 09h 0Ah almacena grabado nmero

04Ch

2.7.

Instrucciones.

45

Ya hemos mencionado que a las computadoras digitales tambin se les llama computadoras de programa almacenado porque para ejecutar un programa tienen que cargarlo ntegramente en la memoria antes de correrlo. Aclaremos ms este concepto: Las computadoras o sistemas de proceso de datos se caracterizan por el proceso digital de la informacin, as como por la diferenciacin en instrucciones (programas) y datos de la informacin ambos representados digitalmente en la memoria principal. Un programa es una secuencia de instrucciones dadas por una persona (programador) a una maquina (computadora), indicandole a esta ultima con detalle y precision cmo tiene que actuar para obtener la solucion de un problema, cuyos datos van incluidos en el programa. Es decir se le indica a la maquina, exacta y totalmente que es lo que tiene que hacer, mediante una secuencia de instrucciones, que se supone, la maquina obedece ciegamente. La computadora digital no hace otra cosa que explorar secuencialmente la informacin almacenada en su memoria, que est en el programa, compuesto de un conjunto de instrucciones, y las procesa siguiendo el principio de Von Neumann: primero lee cada instruccin la decodifica e interpreta y segundo la ejecuta guardando los resultados en la memoria. Cada vez que se ejecuta una instruccin el IP automticamente aumenta en 1 o ms, dependiendo del tamao de la instruccin en bytes, y pasa a apuntar la siguiente instruccin. El juego bsico de las instrucciones del microprocesador 8086 y que son compatibles con todos los microprocesadores de la familia X86, est conformado con 92 instrucciones, agrupadas de la siguiente manera, y que estudiaremos, poco a poco, con el suficiente detalle ms adelante. Instrucciones Instrucciones Instrucciones Instrucciones Instrucciones de transferencia de datos ................ aritmticas........................................ de manejo de bits.............................. de transferencia de control................ de manejo de cadenas...................... 14 20 12 23

8 3 92

Instrucciones de interrupciones ............................ Instrucciones de control del procesador.................. instrucciones Total ................................................

12

Una instruccin en lenguaje de mquina esta compuesto por el nombre de la instruccin y de 0 a 2 operandos Ejemplo: mov ax,41

46

nombre operandos En lenguaje de mquina todas las constantes estn en base hexadecimal, as en el ejemplo anterior el 41 significa 41h es decir 4116. Tampoco est permitido el uso de variables, etiquetas o comentarios. La terminacin de un programa de mquina se tiene que hacer con la INT 20h. A continuacin pasamos a disear algunos programas simples en lenguaje de mquina. Usaremos el programa debug.exe y sus rdenes: E, A, U, D, G, P, T, Q, N, R, que ya hemos descrito anteriormente. Haremos algunos clculos aritmticos con nmeros hexadecimales y rastrearemos los programas escritos. Sabemos que en base a la equivalencia 24 = 16, se demuestra que la conversin de un nmero hexadecimal a binario y viceversa es inmediata recurriendo a la siguiente tabla de conversin, que se puede aprender de memoria en forma muy fcil, por que es muy til. Numero_binario 00002 00012 00102 00112 01002 01012 01102 01112 10002 10012 10102 10112 11002 11012 11102 11112 Nmero hexadecimal 016 116 216 316 416 516 616 716 816 916 A16 B16 C16 D16 E16 F16 de binario a

Con esta tabla podemos convertir un nmero hexadecimal o viceversa en forma inmediata: 101011111 1 5 F

Ejemplo 1

Este es un ejemplo ilustrativo. Es increble pero siguiente cadena de unos y ceros:

afirmamos que la

47

101110100000100100000001101101000000100111001101001000011100110 1001000000110 000101101100011001110110111101110010011010010111010001101101011 0111100100100 es un programa de computadora digital, que contiene tanto las instrucciones como los datos, y que escribe en la pantalla la palabra: algoritmo. En realidad todos: programas grandes y pequeos son cadenas de unos y ceros. Para trabajar con mejor facilidad, usando la tabla de equivalencias anterior, convertimos los nmeros binarios a hexadecimales y obtenemos esta otra cadena de nmeros hexadecimales: BA 09 01 B4 09 CD 21 CD 20 61 6C 67 6F 72 69 74 6D 6F 24 Para ingresar el programa, utilizamos el comando E (Enter), que podemos utilizar en dos formas diferentes: ( 1 ) Digitamos E 100 <enter> y a continuacin digitamos los nmeros hexadecimales, por pares; despus de ingresar cada par pulsamos la tecla espacio. Al terminar con los dos ltimos nmeros hexadecimales 2 y 4, pulsamos la tecla <enter> y aparece el guin que es el smbolo del debug.exe. Despus, para correr el programa usamos el comando G (go) y vemos que aparece la cadena algoritmo y en la siguiente lnea el mensaje: El programa ha terminado con normalidad. Todo esto lo podemos apreciar en la siguiente pantalla:

( 2 ) Digitamos E 100 BA 09 01 B4 09 CD 21 CD 20 61 6C 67 6F 72 69 74 6D 6F 24 <Enter> y para correrlo digitamos -G, y obtenemos:

48

Si pulsamos el comando u 100, vemos los siguientos datos:


DIRECCION DIRECCION RELATIVA ABSOLUTA DE LA MEMORIA DE LA MEMORIA IP=0100 IP=14BD0 00000 00001 ... 14AD:0100 14BD0 14AD:0101 14BD1 14AD:0102 14BD2 14AD:0103 14BD3 14AD:0104 14BD4 instrucciones 14AD:0105 14BD5 14AD:0106 14BD6 14AD:0107 14BD7 14AD:0108 14BD8 14AD:0109 14BD9 14AD:010A 14BDA 14AD:010B 14BDB 14AD:010C 14BDC 14AD:010D 14BDD 14AD:010E 14BDE 14AD:010F 14BDF 14AD:0110 14BC0 14AD:0111 14BC1 14AD:0112 14BC2 ... ... 14AD:FFFE 24ACE 14AD:FFFF 24ACF CONTENIDO LOS 1s y 0s DE LA INTERPRETADOS MEMORIA EN LENGUAJE DE MAQUINA 10111010 00001001 00000001 10110100 00001001 11001101 00100001 11001101 00100000 01100001 01101100 01100111 01101111 01110010 01101001 01110100 01101101 01101111 00100100 . . .

mov dx,109 mov ah,09 int 21 int 20 a l g o r i t m o $

datos

Se pide grabar este programa con el nombre Ejem01.com y duplicarlo a su notacin sierra: Ejem01CadenaBinariaComoPrograma.com.

49

A continuacin codificaremos en lenguaje de mquina los ejemplos dados al describir las capacidades bsicas 1, 2, 3, 5, 6 y 7 de la computadora, con excepcin de la capacidad 4, de programa almacenado, que acabamos de tratar ampliamente. (Grabar todos los programa como .com) Ejemplo 2. (Primera capacidad bsica: almacenar datos en memoria) Verifiquemos la forma como se puede almacenar un dato numrico, tal como el nmero hexadecimal 4116, en la memoria de la computadora. Tenemos que hacer algo similar a lo que en Ensamblador hara la instruccin de asignacin mov X, 41h. Primero hay que decidir en que segmento y desplazamiento tenemos que guardar el nmero 41h. Para esta eleccin, ingresamos al debug.exe en la forma ya conocida, y averigemos qu sector nos ha asignado el sistema operativo para trabajar. Para ello pulsamos el comando r sin parmetros y obtenemos la siguiente pantalla:

Observamos que a los cuatro registros de segmento: DS, ES, SS, CS, se les ha asignado el segmento 1533 en su mquina el DOS puede asignarle otro valor diferente. A nosotros slo nos interesa en particular el segmento de datos DS=1533. Podramos seguir con esta misma direccin 1533, pero elijamos una diferente, el segmento 14AC y el desplazamiento 0, en cuya direccin almacenaremos el numero hexadecimal 41h, cuya longitud es de 1 byte. Entonces la direccin elegida es la direccin segmentada 14AC:0000, que corresponde a la direccin absoluta o real: 14AC * 10 + 0 = 14AC0. A continuacin tenemos que escribir el cdigo en lenguaje de mquina que nos permita hacer esto. Recurrimos al comando A para digitar el siguiente cdigo: mov ax,14AC mov ds,ax mov byte ptr [0000],41 int 20 Antes de correr el programa averiguamos qu valor hexadecimal existe en esa direccin. Para eso utilizamos el comando d 14AC:0000
50

y observamos que en esa localidad de la memoria existe el valor 00h en su mquina puede encontrar otro valor diferente. Corremos el programa con la instruccin g, y acto seguido volvemos a volcar (dumpear) la memoria con el comando d y verificamos que en vez de 00h esta el hexadecimal 41h. La siguiente pantalla muestra el resultado de ejecutar los pasos indicados:

Expliquemos el cdigo escrito. Con las instrucciones: mov ax,14AC y mov ds,ax se le ha indicado al procesador que el registro DS, apunte al segmento 14AC. Se utilizan dos instrucciones por que el Ensamblador, no permite mover datos numricos directamente al segmento de datos DS. Para mover datos a uno de los cuatro segmento DS, CS, SS y ES, se requiere utilizar un registro auxiliar, que sirva de intermediario, en este caso hemos usado el AX. La siguiente instruccin: mov byte ptr [0000],41 le dice al procesador que mueva al desplazamiento 0000 del segmento de datos, el nmero 41h. Ntese que el Debug.exe, para hacernos recordar que es un desplazamiento el valor 0000 se coloca entre corchetes. Adems si no se colocan los corchetes se obtiene un mensaje de error. La palabra byte ptr (byte pointer) le est indicando al procesador que solamente tiene que almacenar un dato de tamao de 1 byte.

51

y finalmente la instruccin: int 20, sirve para terminar el programa. El programa se graba con el nombre Ejem02.com, y se le hace la copia: Ejem02Cap_Bas1MoverDatosAMemoria.com Ejemplo 3. (Segunda capacidad bsica: aritmtica simple) Primero verificamos la suma de 3 + 5 y la resta 8 - 3. Utilizando el comando a ingresamos el siguiente cdigo: mov al,3 add al,5 mov al,8 sub al,3 int 20 y procedemos a ejecutar el programa, paso a paso, usando el comando p (proceed) y verificamos que en el medio registro AL de AX, queda la suma 8, y despus, en este mismo registro queda el nmero 5 que es la diferencia de 8 3. La siguiente pantalla muestra los resultados obtenidos, paso a paso, con el comando -P del Debug.exe:

Para verificar la multiplicacin de 3 * 8 = 24 y la divisin 10 / 2 = 5, ingresamos el siguiente cdigo, recordando que el debug.exe solo trabaja con nmeros hexadecimales: mov al,3 mov bl,8 mul bl mov al,A mov bl,2 div bl int 20 Al ejecutar este cdigo, utilizando el comando p (proceed) ,

52

obtenemos el siguiente resultado de 18 16 en el medio registro al que es el producto de 316 * 816 = 1816 . En cambio la divisin de A16 (diez en decimal) entre 216 da 516 que tambin se guarda en al La siguiente pantalla muestra los resultados en la multiplicacin:

y esta otra pantalla muestra los resultados obtenidos en la divisin:

Se graban el programa y la copia con los nombres Ejem03.com y Ejem03Cap_Bas2AritmeticaSimple.com Ejemplo 4 (Tercera capacidad bsica: entrada/salida) El siguiente cdigo en Ensamblador lee un carcter de teclado, lo almacena en la variable x, luego salta de lnea y escribe el carcter leido y termina. mov ah, 1 teclado int 21h mov x,al variable x ; se prepara para leer un carcter de ; lo lee y guarda en AL ; almacena el carcter ledo en la

53

mov ah,2 ; se prepara para escribir un carcter en pantalla mov dl,0Ah ; en dl, el salto de lnea int 21h ; salta de lnea mov dl,x ; en dl la el carcter leido int 21h ; escribe el carcter leido en pantalla mov ah,4ch ; se prepara para terminar int 21h ; termina y pasa el control al DOS A continuacin escribimos el mismo cdigo, pero en lenguaje de mquina: 100 mov ah, 1 102 int 21 104 mov [115],al 107 mov ah,2 109 mov dl,A 10B int 21 10D mov dl,[115] 111 int 21 113 int 20 115 Ingresamos el cdigo con el comando A y cuando se ejecuta con el G el programa se queda esperando hasta que ingresemos cualquier carcter usando el teclado; si pulsamos la tecla M, obtenemos el siguiente resultado:

Si a continuacin procedemos a vaciar (dumpear) el contenido de memoria en el desplazamiento [115], con el comando d 115, verificamos que en memoria en el desplazamiento 115 aparece el hexadecimal 4Dh, que corresponde al carcter ASCII M:

54

Este programa se graba con los nombres Ejem04Cap_Bas3EntradaYSalida.com

Ejem04.com

Ejemplo 5 (Quinta capacidad bsica: tomar decisiones simples) Ya hemos mencionado que las computadoras tienen circuitos electrnicos que pueden tomar decisiones simples, que son instrucciones de comparacin para bifurcar a determinada direccin de memoria. Cuando estudiamos la quinta capacidad bsica siguiente programa en lenguaje Ensamblador: mov ah,2 mov ch,5 mov cl,3 cmp ch, cl jl salgo suministramos el

menor)

; jl significa jump if less (salta si es

mov dl,ch int 21h mov dl,0Ah ;se prepara para saltar de lnea int 21h ; salta de lnea salgo: mov dl,cl int 21h mov ah,4ch int 21h

Lo que hace este programa es verificar que cuando ch < cl sea verdad debe escribir en pantalla el valor que contiene cl, y en caso contrario debe escribir ambos: primero el valor de ch y en la siguiente lnea el valor de cl. Para ch=3 y cl=5, el programa debe escribir solamente el valor de cl, es decir 5, y en cambio si ch=5 y cl=3, debe escribir ptimero
55

5 y despues 3 en la siguiente lnea. Adaptemos el programa para este segundo caso y tenemos el siguiente cdigo en lenguaje de mquina. 100 102 104 106 108 10A 10C 10E 110 112 114 116 mov ah,2 mov ch,35 mov cl,33 cmp ch, cl jl 112 mov dl,ch int 21 mov dl,A int 21 mov dl,cl int 21 int 20

Debe notarse que no es lo mismo el nmero 5 cuya representacin hexadecimal en un byte es 0516 = 05h = 00000101 2 que el ASCII , 5, cuya representacin hexadecimal es 3516 =35h= 001101012 . El siguiente programa es el resultado de ejecutar este cdigo

El programa se graba con los nombres Ejem06.com Ejem05Cap_Bas5TomarDecisionesSimples.com. Ejemplo 6 (Sexta capacidad bsica: persistencia de datos)

Anteriormente hemos visto que para lograr la persistencia se utiliza un dispositivo de almacenamiento secundario llamado archivo y que no forma parte de la memoria. Cuando describimos esta capacidad suministramos el cdigo de dos programas en lenguaje Ensamblador: el primero para crear un archivo de nombre a:\DATOS;DAT que se
56

encuentra en un disquete-, y el segundo para grabar en este archivo el nmero 3 y como comprobacin desplegarlo en pantalla. A continuacin damos el cdigo de esos dos programas, adaptados en uno slo, pero en lenguaje de mquina. Si no entiende el cdigo, no se preocupe, ms adelante cuando estudiemos archivos, despejar todas sus dudas sobre como opera el programa. Por ahora se pide ingresar este cdigo con el comando A del debug.exe y correrlo con el comando G. Al terminar puede verificar si se ha creado el archivo a:\DATOS.DAT, utilizando el comando: edit a:\DATOS.DAT que utiliza el editor de consola de Windows de nombre edit.exe No debe olvidarse que antes de correr el programa debe tener un disquete en la unidad A: 100 mov ah,3c direccin dx) 102 xor cx,cx 104 lea dx,[156] 108 int 21 10A mov ah,3d 10C mov al,1 archivo 10E lea dx,[156] 112 int 21 114 mov [164],ax 164 117 mov ah,40 en bx 119 mov bx,[164] 11D mov cx,1 120 lea dx,[155] en arch 124 int 21 126 mov ah,3e en bx 128 mov bx,[164] 12C int 21 12E mov ah,3d bx=desplaz 164 130 mov al,00 132 lea dx,[156] 136 int 21 164 138 mov ah,3f bx 13A mov bx,[164] 13E mov cx,1 141 lea dx,[166] leido ;se prepara para crear un archivo con ; cx=0 ;carga en dx direccion de archivo a crear ;crea archivo cuya direccion es dx ;se prepara para abrir un archivo ;al=1 significa que va a escribir en el ;carga en dx la direccin del archivo ;abre archivo y guarda en ax=# (# handle) ;guarda #handle en memoria, desplaz. ;se prepara para escribir el archivo con handle ;recupera en bx=#handle ;le indica que escribira 1 byte ;en dx = direccin donde esta el 3 a escribir ;escribe el 3 en el archivo de direccion dx ;se prepara para cerrar archivo con handle ;recupera en bx = #handle ;cierra archivo de handle bx ;se prepara para abrir archivo de handle ;al=0 significa que leer el archivo ;en dx la direccin del archivo ;abre archivo de handle bx = apunta desplaz. ;se prepara para leer archivo de handle en ;bx = #handle del archivo a leer ;leer 1 byte ;dx = direcc. memoria para guardar el byte

57

145 int 21 ;lee de archivo 1 byte y lo guarda en memoria desplz. 166 147 mov dl,[166] ;dl = byte del desplaz 166 (byte leido desde el archivo) 14B mov ah,2 ;se prepara para escribir el ASCII que est en dl 14D int 21 ;escribe ASCII en pantalla 14F mov ah,1 ;se prepara para leer ASCII de teclado 151 int 21 ;lee <enter> y aguanta pantalla 153 int 20 ;termina y pasa el control al DOS 155 db 33 ;dato a grabar en el archivo 156 db a:\DATOS.DAT,00 ; nombre del archivo que se crea en el disquete A continuacin se da el resultado de correr este programa:

El programa se graba con los nombres: Ejem06Cap_Bas6PesistenciaDeDatos.com

Ejem07.com

Ejemplo 7 (Stima capacidad bsica: reutilizacin) Al describir esta capacidad bsica, presentaremos un programa modular, que utiliza una librera de programas objetos de nombre LIBASS.LIB. Por ese motivo este programa no puede codificarse en lenguaje de mquina; y lo nico que haremos ahora es utilizar el debug.exe para correr el programa Ejem7.exe, cuyo programa fuente est en lenguaje Ensamblador, desde el ambiente del DOS. Para ello digitamos lo siguiente: debug Ejem7.EXE y aparece la siguiente pantalla:

58

Digitamos u, para ver el cdigo fuente y luego corremos el programa con el comando G. Siguiendo las instrucciones del programa ingresamos el nmero flotante 2.00E00, que equivale a 2 x 100 = 2.00 y obtenemos la raz cuadrada 1.41421356237309x10 0. Si probamos con otro dato tienen que ingresarse en el formato flotante D.DD..DE[+/-]DD, en el que D significa un dgito decimal. Este programa, se explicar con mayor detalle, cuando se estudie aritmtica flotante. El cdigo del programa Ejem07.asm es el que se ha dado al describir la stima capacidad bsica en la seccin 1.4.7., y se graba con los nombres: Ejem07.asm y Ejem07Cap_Bas7Reutilizacin.asm. Tambien est disponible, el programa ejecutable Ejem07.exe.

1.5

Algo ms sobre el lenguaje de mquina. El lenguaje de mquina es til para apreciar como trabaja internamente el procesador. En este sentido es un auxiliar irremplazable, y puede usarse para depurar programas, de ah el nombre del programa de utilera: debug.exe. Antes de continuar con el tercer captulo en el que empezaremos a estudiar el lenguaje Ensamblador, vamos a disear algunos programas ms en lenguaje de mquina. Ejemplo 8 Se pide escribir un programa, en lenguaje de mquina, que lea una cadena de teclado de hasta 72 caracteres como mximo = (48h), la almacene en memoria y despus despliegue esta cadena en pantalla. Como 72 = 48h, en el programa figura 47h. Este es un programa que tiene que manejar la capacidad bsica de la computadora de entrada/salida, por tanto tenemos que utilizar la interrupcin 21h. Como se trata de leer de teclado una cadena, de acuerdo a la tabla de funciones de la int 21h, tenemos que utilizar la
59

funcin AH=0Ah, para leer la cadena y la funcin AH=9h, para escribir la cadena. Antes de utilizar la funcin AH=0Ah, tenemos que decidir dos cosas: primero de que tamao ser la cadena a leer, y segundo en que parte de la memoria vamos a almacenar la cadena leda. Acordemos que la longitud mxima de la cadena sea de 47h caracteres, y que almacenaremos la cadena al terminar el cdigo del programa en lenguaje de mquina. Adems acordamos desplegar dos mensajes, para solicitar que se ingrese la cadena y para mostrar la cadena leda. En esa forma el diseo de la pantalla es el siguiente: Ingrese una cadena : Estoy aprendiendo Ensamblador Cadena leda : Estoy aprendiendo Ensamblador Como primer paso vamos a ingresar tentativamente el cdigo de ms abajo. Las direcciones que aparecen en este cdigo que son el desplazamiento 0000, que corresponde a la direccin de donde se va almacenar el mensaje Ingrese la cadena: , el valor de desplazamiento 1111, que corresponde a la direccin de memoria donde guardaremos la cadena leda y el valor de desplazamiento 2222, que corresponde a la direccin de donde almacenaremos el mensaje cadena leida :, son tentativos, y sus valores reales los vamos a obtener despus de ingresar el siguiente cdigo en el que se han numerado las instrucciones, slo con el propsito de explicar qu hace cada instruccin en lenguaje de mquina; para ello utilizamos el comando A del debug.exe:
1. lea dx,[0000] (desplazamiento 0000 del mensaje 1)

2. mov ah,9 3. int 21 4. lea dx,[1111] cadena) 5. mov ah,A 6. int 21 7. mov ah,2 8. mov dl,A 9. int 21 10. lea dx,[2222] 11. mov ah,9 12. int 21 13. lea dx,[1111] 14. add dx,2 ledos) 15. mov ah,9 16. int 21 17. int 20

(desplazamiento 1111 para almacenar

(se prepara escribir carcter) ( A salto de lnea) (salta de lnea para escribir el segundo mensaje) (desplazamiento 2222 del mensaje 2) (desplazamiento 1111 de la cadena leda) (ms 2, para saltar el 50 y # de caracteres

60

18. db Ingrese una cadena que termina en $: $ (primer mensaje) 19. db Cadena leida : $ (segundo mensje) 20. db 48, 48 dup ($); 48h= 72 es decir se pueden leer hasta 72 incluido el <enter>

Descripcin: 1. Tentativamente suponemos que el primer mensaje que se declara en la instruccin 18 es 0000, pues no conocemos cul es su valor. La instruccin de mquina LEA dx, [0000], significa Load Efective Address, que se traduce al castellano por: carga en el registro dx, la direccin efectiva del desplazamiento 0000. 2 y 3. Escribe en pantalla la cadena que se encuentra en la direccin ds:dx. Como acabamos de leer en dx el desplazamiento del primer mensaje y DS=CS=SS=ES cuando se trata de cdigo de mquina, al ejecutarse estas dos instrucciones escriben en pantalla el primer mensaje. La cadena a desplegar debe terminar en $, caso contrario el programa no funcionar bien. 4, 5 y 6. Leen el desplazamiento dx de la cadena a ser leda y almacenada donde se encuentra la instruccin 20. Suponemos que este desplazamiento es 1111. Cuando se ejecutan estas instrucciones, la computadora lee de 0 hasta 50 caracteres y los almacena en la direccin que corresponde al desplazamiento 1111. 7, 8 y 9. Utilizan la funcin ah=2 que escribe en pantalla el carcter que se encuentra en dl. Como dl=A16 =salta de linea, cuando se ejecutan estas instrucciones el cursor salta de linea. 10, 11 y 12. Esta tres instrucciones primero leen el desplazamiento 2222 del segundo mensaje y despus lo escriben en pantalla: su funcin es similar a la que cumplen las instrucciones 1, 2 y 3. 13 Lee el desplazamiento de la direccin donde se almacen la cadena, cuando se ejecutaron las instrucciones 4, 5 y 6. 14 Al desplazamiento dx le suma 2 bytes, 1 para saltar el nmero 28h y el otro para saltar el nmero de caracteres ledos que se coloca a continuacin del nmero 28h. 15 y 16 Escriben en pantalla la cadena de caracteres leidos y almacenados en el desplazamiento 1111, sin incluir el nmero 28h y el nmero de caracteres ledos. 17 Termina el programa y pasa el control al DOS.
61

Declara una cadena de bytes, con el mensaje Ingrese una cadena, que tiene que terminar con el carcter $. Por eso se utiliza la directiva db que significa define bytes, que despus aprenderemos que no es una instruccin si no ms bien una directiva o seudo instruccin.
18

19 Declara una cadena de bytes con el Cadena ingresada

segundo mensaje

20 Separa 28h = 40 bytes de memoria, para almacenar la cadena que va a ser leida al ejecutar las instrucciones 4, 5 y 6. Como esta cadena va a ser desplegada con las instrucciones 15 y 16, se inicializa con 40 veces $. A continuacin tenemos la pantalla que muestra qu se ha hecho. Recurriendo al comando A se ingres todo el cdigo del programa de ms arriba. Al terminar podemos visualizar los valores de los desplazamientos de cada instruccin que nos servirn para reemplazar a los tres desplazamientos 0000, 1111 y 2222.

En esta pantalla vemos lo siguiente: que el desplazamiento del primer mensaje, es 012B, que reemplaza al valor 0000; que el desplazamiento del segundo mensaje, es 0140 que reemplaza al valor 2222; y que el desplazamiento de la direccin para cargar la cadena leda es 0155, que reemplaza al valor 1111. Por tanto el nuevo cdigo que resuelve el problema es: lea dx,[012B] mov ah,9 int 21

62

lea dx,[0155] mov ah,A int 21 mov ah,2 mov dl,A int 21 lea dx,[0140] mov ah,9 int 21 lea dx,[0155] add dx,2 mov ah,9 int 21 int 20 12B db Ingrese una cadena: $ 140 db Cadena leida : $ 155 db 28, 28 dup (24) El resultado de correr este cdigo es el siguiente:

El programa se graba con los Ejem08LeeYEscribeCadena.com. Ejemplo 9

nombres

Ejem08.com

Aprenderemos a multiplicar nmeros hexadecimales, utilizando el lenguaje de mquina. Si se tenemos dos nmeros decimales: a con n dgitos y b que tiene m dgitos; si calculamos el producto de a por b, es decir a x b, por matemticas sabemos que a x b tiene m+n-1 o m+n dgitos. As por ejemplo si multiplicamos los nmeros decimales 5409 x 1011 el producto debe tener 7 u 8 dgitos; en efecto 5409 x 1011 = 5468499 tiene 7 dgitos decimales. En el caso extremo tenemos que el producto 9999 x 9999 = 99980001 tiene 8 dgitos decimales.
63

Sucede algo parecido en el sistema hexadecimal. Hemos visto que para multiplicar dos nmeros, tenemos que utilizar dos registros que tienen 16 bits = 2 bytes, por tanto cada uno puede almacenar 4 hexadecimales como mximo, y el producto llegar a tener 7 u 8 hexadecimales, o sea necesitamos dos registros para almacenar el producto. Por este motivo el procesador utiliza el par de registros DX:AX para guardar el producto. Si tenemos dos nmeros a y b y queremos calcular su producto a x b, forzosamente debemos colocar uno de ellos en el registro AX, es decir hacemos mov AX,a. El otro nmero lo almacenamos en cualquier registro que no sea el AX o DX, por ejemplo el BX, y hacemos mov BX,b; la instruccin mul BX, calcula a x b y el resultado lo guarda en DX:AX, la parte ms significativa en DX y la parte menos significativa en AX. Si queremos calcular el producto FFFFh x FFFFh =FFFE0001h, el siguiente cdigo en lenguaje de mquina resuelve el problema: mov ax,FFFF mov si,FFFF mul si int 20 el producto se almacena en el par de registros DX:AX: que es igual a DX=FFFEh y AX=0001h, segn se puede apreciar si corremos este programa

Este programa se graba Ejem09Multipliacion.com Ejemplo 10

con

el

nombre

Ejem09.com

La divisin es la operacin inversa de la multiplicacin. Por tanto el dividendo puede tener entre 1 y 8 dgitos y requiere dos registros, el

64

par DX:AX, y el divisor puede ser cualquier otro registro que no sea el DX o AX, digamos el BX, entonces la divisin se efecta con la instruccin div BX. El cociente se almacena en AX y el resto en DX. As por ejemplo, si dividimos 8 entre 3, escribimos el siguiente cdigo mov dx,0 mov ax,8 mov si,3 div si int 20 si corremos el programa obtenemos en AX=2 y en DX =2, por que: 8 2 = 2 + , o sea el cociente es 2 y el resto 2 3 3 En base al ejemplo 9, el mximo valor que podemos colocar en el par de registros DX:AX es el nmero hexadecimal FFFE0001, en caso contrario recibiremos un mensaje de error. El siguiente cdigo en lenguaje de mquina: mov dx,FFFE mov ax,1 mov si,FFFF div si int 20 nos da un cociente en AX igual a FFFFh y un resto en DX igual a 0:

Este programa se graba Ejem10Division.com

con

el

nombre

Ejem10.com

65

Ejemplo 11 Vamos a empezar a disear ciclos de repeticin en nuestros programas y tenemos que utilizar nuevas instrucciones de mquina: Las instrucciones cmp, jl y nop Las instrucciones cmp (compare), jl (jump if less), permiten formar ciclos de repeticin. La instruccin nop (no operation), nos ayudar en la depuracin. Por ejemplo para calcular, y almacenar la suma 1+2+...+100, en el registro DX: DX = 1 + 2 + 3 + ... + 10010 = 505010 (=13BA16) escribiremos el siguiente cdigo en lenguaje de mquina (6416=10010), que repite 100 veces las instrucciones 3 a 6: 1. 2. 3. 106 4. 5. 6. 106h si 7. 8 mov si,0 (si=0) mov dx,0 (dx=0) add si,1 (si=si+1) add dx,si (dx=dx+si) cmp si, 64 (compara contenido de si con 6416 = 10010) jl 106 (jump to 106h if less than 64h) salta a la direccin es verdad que si < 64 nop (no operar) int 20 (termina y pasa el control al DOS)

Cuando este programa termine tendr almacenado en DX =13BA16 (=505010) y en SI=6416=10010 como se puede apreciar en la siguiente pantalla. El programa tiene que ejecutarse con el comando G 110, que le indica al debug.exe que ejecute el programa hasta la instruccin 110 nop, y as se puede verificar los valores en los registros DX y SI, que no sucede si usamos G.

66

Este programa se graba con los nombres Ejem11CalculaSumatoria1a100.com. Ejemplo 12 La instruccin LOOP

Ejem11.com

El par compuesto por el registro CX y la instruccin LOOP nombre_etiqueta, nos permiten repetir CX veces el conjunto de instrucciones que abarca desde nombre_etiqueta hasta la instruccin LOOP. Cada vez que se llega a la instruccin LOOP, el valor de CX disminuye en 1, en esta forma llega un momento en que CX vale 0, y termina el ciclo. As por ejemplo, en el siguiente cdigo de mquina, como CX contiene el valor 1Ah (=26), todas las instrucciones desde el desplazamiento 107 hasta el desplazamiento 10C se repiten 26 veces, por tanto el siguiente programa escribe las 26 letras del alfabeto ingls, empezando con la letra A: 100 mov ah,2 102 mov dl,41 104 mov cx,1A 107 int 21 109 add dl,1 10C loop 107 10E int 20 la prueba de correr este programa es la siguiente:

67

Este programa se graba como Ejem12EscribeLetrasAlfabetoIngles.com Ejemplo 13 Las instrucciones PUSH y POP

Ejem12.com

PUSH y POP, nos sirven para agregar y sacar datos de la PILA, que no debemos olvidar, tambin es una parte de la memoria. El almacenamiento de datos en la pila se hace en forma diferente a como se hace con la instruccin MOV. Ambas instrucciones PUSH y POP utilizan un solo operando que es el nombre de un registro. Ya sabemos que JL , significa jump if less (salta si es menor que). Por eso el siguiente programa escribe, en pantalla, los 10 nmeros decimales, desde el 9 al 0, uno al lado del otro con un blanco intermedio: 100 mov ax,0 103 push ax 104 add ax,1 107 cmp ax,A 10A jl 103 es menor) 10C mov ah,2 10E mov cx,A 111 pop dx 112 add dx,30 115 int 21 117 mov dl,20 119 int 21 11D loop 111 11F int 20

( jump to 103 if less , salta a 103 si

el primer ciclo de repeticin desde el desplazamiento 103 hasta el 10A, sirve para almacenar en la pila diez nmeros desde el 0 hasta el 9. Hagamos una abstraccin e imaginemos la pila como un arreglo, tal

68

como aparece en la siguiente figura. Al terminar el ciclo vemos que quedan uno encima del otro, igual a una pila de nmeros de ah el nombre-, en la que el ultimo nmero en entrar va a ser el primero en salir: 9h 8h 7h 6h 5h 4h 3h 2h 1h 0h El cero hexadecimal est en el fondo de la pila, pues fue el primer PUSH AX, el que se ejecut, cuando AX contena el valor 0h. El segundo ciclo dado por el par CX=A16=10 y LOOP 111, hace que las instrucciones 111 hasta 117, se repitan 10 veces; y sirve para sacar los elementos de la pila. Por cada POP DX, se saca un elemento de la pila en el registro DX. Se empieza por 9h que est al tope de la pila y se termina en 0h que es el que est al fondo. Si al hexadecimal sacado en DX, por ejemplo 0009h, se le suma 30h, se obtiene 0039h, es decir en DH queda el valor 00h y en DL queda 39h, o sea el ASCII 9, que es el carcter que se escribe en pantalla con la interrupcin 21h y la funcin ah=2. Esta funcin se prende antes de iniciar el segundo ciclo de repeticin en la instruccin 10C. El resultado final es que se escriben en pantalla los caracteres ASCII desde el 9 hasta el 0. La siguiente pantalla, muestra el resultado cuando se corre el cdigo de mquina de ms arriba:

69

Este programa se graba como Ejem13.com Ejem13ManejoDeLaPilaLeeYEscribeNumeros.com Ejemplo 14

Vamos a continuar aprendiendo a disear ciclos de repeticin, esto es, conseguir que un nmero de instrucciones que se encuentran en la memoria se repitan un nmero determinado de veces, lo que es necesario para convertir un nmero hexadecimal a binario. Primero debemos resolver manualmente el problema, para ver que pasos tenemos que repetir varias veces. Cuando dividimos un nmero entre 2, el resto solo puede ser 1 o 0. Si tenemos que convertir el nmero 29 (=1Dh) a binario, empezamos dividiendo el nmero 29 y despus los cocientes resultantes entre 2, hasta obtener un cociente 0. Conforme se avanza en este proceso se van almacenando los restos, tal como se muestra a continuacin: 29 2 1 14 2 0 7 1

2 3 2 1 1 1 0

El resultado es el nmero binario 11101, formado por los restos, pero escritos en orden reverso del que fueron obtenidos.

70

El siguiente programa en lenguaje de mquina resuelve el problema mov dx,0 (DX = 0) mov ax,1D (AX = 1Dh = numero a convertir a 00011101; el dividendo) mov bx,2 (el divisor en BX) mov cx,0 (CX servir como contador de las repeticiones) 10C div bx (divide DX:AX entre BX, cociente en AX, resto en DX) push dx (guarda el resto DX en la pila) add cx,1 (suma uno al contador CX) mov dx,0 (DX=0 para borrar el resto y volver a dividir) cmp ax,0 (es el cociente AX=0?) jg 10C (si es mayor que 0 salta a 10C, si no sigue) mov ah,2 (se prepara para escribir en pantalla DL) 11C pop dx (recupera resto en DX) add dx,30 (Le suma 30h para convertirlo a ASCII) int 21 (escribe en pantalla ASCII de DL) loop 11C (resta 1 a CX y bifurca a 11C si CX 0) int 20 (termina, pasa el control al DOS) Los valores de 10C y 11C se obtuvieron en forma parecida a como fue hecho en el ejemplo 8. El resultado de correr este programa es el siguiente:

Este programa se graba con el Ejem14EscribeNumeroBinario.com.

nombre

Ejem14.com

71

CAPITULO III

EL LENGUAJE ENSAMBLADOR

3.1 Introduccin En el captulo I, aprendimos cules son las capacidades bsicas de una computadora digital. En el captulo II aprendimos a disear programar pequeos en lenguaje de mquina; pero nos dimos cuenta que el debug.exe tiene muchas limitaciones; sin embargo utilizar el lenguaje de mquina, nos ha ayudado a tomar conceptos de muchas cosas que utilizaremos ahora que empezamos a programar en lenguaje Ensamblador, que representa un nivel ms alto de codificacin, en el que podremos utilizar directivas o seudo instrucciones, declarar variables, utilizar datos numricos constantes en el sistema binario, octal, decimal y hexadecimal, etc. La modularidad es un aspecto importante Y sobre todo por que el lenguaje Ensamblador nos permite aprovechar la tercera razn por la que se utiliza las computadoras para resolver problemas, ya mencionada en el capitulo I, por la cual

72

con su creatividad el hombre es capaz de descomponer un problema grande y de difcil solucin, en un conjunto de pequeos problemas de fcil solucin. Lo repetimos ahora por que esto es importante: Cuando el hombre enfrenta un problema de gran complejidad no lo resuelve directamente, sino por el contrario soluciona equivalentemente un conjunto de pequeos problemas -uno despus de otro-, con la aclaracin pertinente de que las soluciones a estos pequeos problemas pueden ser obtenidos usando las limitadas capacidades bsicas que poseen todas las computadoras. El lenguaje Ensamblador, nos permitir trabajar en forma modular, descomponiendo un programa muy grande, en un conjunto de procedimientos o mdulos, que tienen un nmero de instrucciones que no sea muy grande para que pueda ser manejable. La entrada y salida de datos, es un escollo. Sin embargo al programar en lenguaje Ensamblador tambin encontraremos que existen muchas limitaciones sobre todo con las instrucciones de entrada y salida. Ya hemos mencionado anteriormente que en la representacin de informacin siempre est implcita la lectura y escritura de datos, en un lenguaje que tiene esencia matemtica cuando se usa la computadora. La computadora digital no lee, no hace sino registrar datos. Transfiere datos de un medio magntico llamado disco o teclado a otro medio magntico llamado memoria (almacenamiento principal). La computadora no escribe, transfiere o duplica los datos de un soporte sobre otro, desde la memoria (almacenamiento principal) a el disco o a la pantalla. La filosofa del procesador consiste en que todo lo que se lee de teclado es cdigo ASCII y todo lo que se escribe en pantalla tambin son caracteres ASCII, pero se almacenan en memoria en el sistema binario, en correspondencia con la tabla de cdigos ASCII. Tambin los datos numricos internamente estn almacenados en memoria en el sistema binario, pero resulta que su representacin est muy lejos de los patrones binarios que se utilizan para los 256 caracteres de la tabla ASCII. Si se lee de teclado el ASCII 3 se almacena en un byte de la memoria, como 33h (en binario 00110011 2), que es muy diferente del nmero hexadecimal 3h (en binario 000000112). El mismo problema se presenta cuando se tiene en memoria el nmero 03h (000000112), si escribimos este valor en pantalla, tal como est almacenado, se escribir el carcter ASCII que corresponde a un nmero con dos dgitos hexadecimales, el nmero
73

03h, que segn la tabla de caracteres ASCII para comprobarlo ejecute el programa Ejem19.com, que despliega esta tabla en pantalla, es el smbolo , y no el 3 como hubiramos esperado. Para probar esto ejecute el siguiente programa en lenguaje de mquina, y comprobar que despliega en pantalla la figura . mov ah,2 mov dl,3 int 21 int 20 El resultado se aprecia en la siguiente pantalla:

Posteriormente daremos solucin al problema de salida, recurriendo a la reutilizacin, que es una de las capacidades bsicas de las computadoras; para este propsito construiremos, una la librera esttica de mdulos objeto, de nombre UPA.LIB, que contendr varios procedimientos objeto, para salida de datos numricos. Este tema ser tratado ms adelante. 3.2. Programa fuente Recordemos que cuando trabajamos con el debug.exe, para ingresar las instrucciones de mquina, utilizbamos el comando A, y luego para ejecutar el programa el comando G. Trabajando con el compilador del lenguaje Ensamblador, el ingreso y la ejecucin, forman parte de un conjunto de pasos que tienen que ejecutarse uno despus de otro, y que hay que seguir en forma rgida. Esto es asi, porqu el ambiente del lenguaje Ensamblador es ms logrado que el que se usa con el programa debug.exe. Los pasos que se siguen para llegar a construir un programa en lenguaje Ensamblador son: 10) edicin, 20) ensamble, 30) enlace y 40) ejecucin. Pasamos a describir cada uno de estos pasos. PRIMER PASO: Edicin. Las instrucciones y la definicin de los datos que se codifican respetando la sintaxis del lenguaje Ensamblador, se llaman

74

programa fuente. El programa que sirve para digitar estas instrucciones se llama editor. Existen varios editores que pueden utilizarse, por ejemplo el programa edit.exe, proporcionado por el Windows como un componente del DOS. La estructura de un programa fuente Ensamblador, contiene ms de un segmento: uno para cdigo (que es obligatorio), y como opcionales, un segmento para los datos, la pila y el segmento extra. En este sentido la estructura de un programa fuente en lenguaje Ensamblador es la siguiente: nombre1 segment Assume cs:nombre1, ds:nombre2, ss:nombre3, es:nombre4 s nombre5 proc e instruccin 1 g instruccin 2 m ... e Termina n nombre5 endp t nombre6 proc o instruccin 1 instruccin 2 d ... e ret nombre6 endp c ... o nombren proc d instruccin 1 i instruccin 2 g ... o ret nombren endp nombre1 ends
seg de datos nombre2 segment directiva 1 de definicin de datos directiva 2 de definicin de datos ... directiva n de definicin de datos nombre2 ends nombre3 segment stack directiva 1 de definicin de datos de la pila directiva 2 de definicin de datos de la pila ... directiva n de definicin de datos de la pila nombre3 ends

seg de pila

nombre4 segment

seg extra

nombre4 ends end nombre5 El siguiente es un ejemplo de un programa fuente en lenguaje


75

directiva 1 de definicin de datos del segmento extra directiva 2 de definicin de datos del segmento extra ... directiva n de definicin de datos del segmento extra

Ensamblador: Programa: Prueba.asm y PruebaProgramaConCuatroSegmentos.asm codigo segment directiva assume cs:codigo,ds:data,ss:pila,es:extra directiva principal proc directiva mov ax,data ; carga direccion del segmento de datos mov ds,ax ; ds apunta segmento de datos lea dx, mensaje1 ; carga direccion efectiva de mensaje1 mov ah,9 ; se prepara pra escribir cadena ds:dx int 21h ; lo hace mov ax,"A" ; mete en push ax ; la pila "A" mov ax,"B" ; mete en push ax ; la pila "B" mov ax,"C" ; mete en push ax ; la pila "C" mov ax,"D" ; mete en push ax ; la pila "D" mov ah,2 ; funcion para escribir caracter mov bp,sp ; bp=sp= comienzo de la pila en bp mov dl, byte ptr [bp+6] ; dl=primer caracter metido en la pila int 21h ; lo escribe en pantalla mov dl, byte ptr [bp+4] ; dl=segundo caracter metido en la pila int 21h ; lo escribe mov ah,2 ; se prepara para escribir caracter mov dl,0dh ; retorno de carro CR int 21h ; retorna mov dl,0ah ; salto de linea LF int 21h ; salta mov ax,extra ; lee direccion de segmento extra mov es,ax ; es apunta a segmento extra mov si,0 ; si=desplazamiento 0 mov cx,33 ; cx = 33 veces sigo:
76

mov dh,0 mov dl,es:otro_mensaje[si] ; dl=letra de otro mensaje en desplaz. si add si,1 ; aumenta el desplazamiento mov ah,2 ; se prepara para escribir caracter de dl int 21h ; lo escribe loop sigo ; repite loop cx = 33 veces mov bp,sp ; comienzo de la pila en bp mov dl, byte ptr [bp+2] ; dl=tercer caracter metido en la pila int 21h ; lo escribe mov dl, byte ptr [bp] ; dl=cuarto caracter metido en la pila int 21h ; lo escribe mov ah,4ch ; se perpara para salir int 21h ; sale principal endp directiva codigo ends directiva data segment mensaje1 db "Letras leidas segmento de datos: $" directivas data ends pila segment stack db 4 dup ("PILA") directivas pila ends extra segment otro_mensaje db "Letras leidas segmento extra directivas extra ends end principal

:"

Todo lo que no est sealado como directiva no es una instruccin. La edicin del programa anterior se puede hacer utilizando el Edit.exe. Previamente hay que adoptar un nombre para el programa fuente, que tiene que tener un nombre de 1 a 8 caracteres y una extensin .ASM. Para nuestro caso adoptemos el nombre Prueba.ASM, y procedemos a editarlo con el siguiente comando en el ambiente del DOS: Edit Prueba.asm

77

y acto seguido se digita el programa fuente tal como aparece ms arriba, como puede verse en la siguiente pantalla:

SEGUNDO PASO: Ensamble. Hemos identificado dos lenguajes de programacin de alto nivel y de bajo nivel. Los programadores que escriben en un lenguaje de alto nivel, como C o Object Pascal, codifican comandos poderosos, cada uno de los cuales puede generar muchas instrucciones en lenguaje de mquina. Por otro lado, los programadores que escriben en un lenguaje ensamblador de bajo nivel codifican instrucciones simblicas como las que aparecen en el programa fuente de ms arriba, cada una de las cuales genera una instruccin en lenguaje de mquina. Sin importar el lenguaje de programacin que utilice, de todos modos es un lenguaje simblico que tiene que traducirse a lenguaje de mquina. Un lenguaje de alto nivel utiliza un compilador para traducir el cdigo fuente a lenguaje de mquina no ejecutable (a veces llamado cdigo objeto). Un lenguaje de bajo nivel utiliza un ensamblador, para realizar la traduccin. Despus un programa de nombre Link.exe, para ambos niveles, alto y bajo, completa el proceso para convertir el cdigo objeto a lenguaje de mquina ejecutable El programa ensamblador de microsoft se llama MASM.EXE y el ensamblador de Borland es TASM.EXE. Para ensamblar los
78

programas de este libro se puede usar cualquiera de los dos ensambladores. Los comandos para ensamblar el programa fuente son los siguientes: MASM prueba.asm o este otro: TASM prueba tambin TASM prueba.asm

Si no existen errores en el programa fuente, el ensamblador genera el programa objeto de nombre prueba.OBJ. Si se requiere un listado del programa fuente en un archivo de nombre prueba.lst, se recurre a los siguientes comandos: MASM prueba,,prueba.lst,, esta otra TASM prueba,,prueba.lst Despus de generado prueba.lst, puede imprimirse o editarse con el editor del DOS edit.exe utilizando el comando: Edit prueba.lst TERCER PASO: Enlace Una vez que el programa Prueba.asm queda sin mensajes de error, el ensamblador genera el programa objeto prueba.obj. El siguiente paso es enlazar el mdulo objeto. Por qu se realiza el ensamble?. La respuesta es por que el programa enlazador Link.exe realiza las funciones siguientes: Si se pide combinar ms de un mdulo ensamblados de forma separada en un solo programa ejecutable. Incluso el programa Link.exe puede combinar mdulos objeto generados por compiladores como el C y/o el ensamblador. Genera un mdulo .EXE y lo inicializa con instrucciones especiales para facilitar su subsecuente carga y ejecucin.

El comando para el ensamble, en nuestro caso es: LINK prueba;

Y le recomendamos que no se olvide de digitar el punto y coma final, por que de lo contrario el LINK trabaja en modo interactivo y le va a solicitar ms datos, que aparentemente resultan ser obvios, y es el
79

punto y coma final,el que evita este dialogo con el programa enlazador Link.exe. CUARTO PASO: Ejecucin del programa .EXE Una vez que se han enlazado uno o ms mdulos .OBJ en un solo mdulo .EXE, puede ejecutar el programa.exe cualquier nmero de veces, digitando el siguiente comando: Prueba <entrada> Aunque al principio estos pasos no sean por completo claros, encontrar que con un poco de experiencia se vuelven automticos. El resultado de ejecutar el programa prueba.exe es el siguiente:

Diagrama conjunto de los pasos para editar, ensamblar , enlazar y crear el ejecutable de un programa pantalla teclado

editor

edit.exe

en memoria el

prueba.asm
80

programa.fuente

ensamblador

MASM.exe TASM.exe

en memoria el

Otros.obj

Prueba.obj

programa.objeto

enlazador

LINK.EXE

en memoria el

(ejecutable) Ejecucin del programa Disco ENTRADAS

Prueba.exe

programa,exe

disquete

pantalla/teclado

ejecutable

Nombre.exe

programa

SALIDAS pantalla Disco 3.3 Tipos de sentencias fuente disquete impresora

Hemos dicho que un programa de computadora est compuesto de instrucciones y datos; ambos son los principales componentes de lo que se llama programa fuente y por eso se les llama sentencias fuente; por tanto un programa fuente contiene dos tipos de sentencias:

81

1.

Las instrucciones, que son enunciados que comienzan con un verbo en forma imperativa, tal como ADD y MOV, que ocasionarn que el procesador haga algo. Despus veremos que las instrucciones generan cdigo, esto es por cada instruccin de lenguaje Ensamblador se origina una instruccin en lenguaje de mquina. Las directivas o seudo instrucciones, que sirven para definir los datos, indicar donde comienza y donde termina un programa, o indicar dnde empieza y termina el segmento de datos, la pila y muchas otras cosas ms. A diferencia de las instrucciones, las directivas no generan cdigo, esto es, solamente son utilizadas por el compilador, pero sirven para armar la estructura del programa. Las instrucciones se aplican en tiempo de ejecucin, en cambio las directivas se aplican en tiempo de ensamblaje.

2.

3.3.1. FORMATO DE UNA INSTRUCCIN ENSAMBLADOR El formato de una instruccin contiene cuatro campos: [ etiqueta[:] ] nombre_de_instruccin [operandos] [;comentarios] los corchetes [ ] significan que el campo correspondiente es opcional. Ejemplo: mover: mov AX,45h etiqueta operandos instruccin ; Asigna 45 a AX comentarios

3.3.1.1. Campo etiqueta - Puede tener hasta 31 caracteres - Tiene que terminar con el smbolo de dos puntos : 3.3.1.2. Campo nombre Es el nombre simblico de la instruccin. Puede tener de 2 a 6 letras. 3.3.1.3. Campo operandos Puede tener 0, 1 2 operandos 3.3.1.4. Campo comentario Debe empezar con un punto y coma ;. Todo lo que se escriba a la derecha del smbolo ; es ignorado por el compilador

3.3.2.

Identificadores

82

Un identificador es un nombre que se aplica a elementos del programa fuente. Los dos tipos de identificadores son: nombre o variable, que se refiere a la direccin de un elemento de dato, y etiqueta que se refiere a la direccin de una instruccin y que es el primer campo opcional de una instruccin. Un identificador puede utilizar los siguientes caracteres:

Letras del alfabeto: desde la A hasta la Z Dgitos: desde el 0 al 9 Caracteres especiales: signo de interrogacin (), subrayado (_), signo de dlar ($), arroba (@) y punto (.).

El primer carcter de un identificador debe ser una letra o uno de los caracteres especiales, excepto el punto. El Ensamblador trata las letras maysculas y minsculas como iguales; por esto hay veces que se suele decir que el Ensamblador es sensible slo a maysculas, por que el compilador convierte las minsculas a maysculas en la etapa de compilacin. Para el Ensamblador es lo mismo escribir MOV, mov, Mov, mOv, etc. Todas significan lo mismo MOV. La longitud mxima de un identificador es de 31 caracteres (247 desde el MASM 6.0) Ejemplos de declaracin de variables, es decir de identificadores de datos son las siguientes: 3.3.3. FORMATO DE DEFINICIN DE DATOS. Los datos se definen en el segmento de datos DS, y se emplea el siguiente formato general que contiene 3 campos, siendo el primero opcional: [nombre_de_dato] directiva expresin 3.3.3.1. Campo nombre de dato Es un campo opcional, y es el nombre de la variable. Su formacin esta definida por las reglas de los identificadores que se dan ms adelante. 3.3.3.2. Campo directiva Las directivas que definen los diferentes tipos de datos o tipos de variables son:

DB Define variables de tipo byte ( 1 byte) Es el nico tipo que admite definicin de cadenas de
83

caracteres que exceden a dos caracteres. DW Define variables tipo word (2 bytes) DD Define variables de tipo palabra doble (4 bytes) DQ Define variables de tipo palabra cudruple (8 bytes) DT Define variables de tipo diez bytes (10 bytes) 3.3.3.3. Campo expresin Una expresin puede contener varios valores constantes separados por comas y limitados solo por la longitud de la lnea. Ejemplos: X db 23h, 45, hola amigo, 101011b, 56o hexadecimal decimal cadena binario octal de bytes
Y dw 0ADE4h, -0FFEh, 324567 SUMAR dw 2345h _Y12 dd 234567h $A dt 2345678

FORMA ABREVIADA DE LOS PROGRAMAS FUENTES Cuando describimos el paso uno:edicin hicimos referencia al formato clsico. Los ensambladores de Microsofot y Borland proporcionan una forma abreviadas para definir segmentos, que ahorran cdigo y tiempo, por tanto pasamos a describirla: Un programa fuente tiene la siguiente estructura: tiny small .model medium compact large .stack tamao_de_la_pila (en bytes) .data directivas de datos .code .386 nombre_1 proc instruccin 1 instruccin 2 ... Termina nombre_1 endp nombre_2 proc instruccin 1 instruccin 2 ... ret

84

nombre_2 endp ... nombre_n proc instruccin 1 instruccin 2 ... ret nombre_n endp end nombre_1 Requisitos para cada modelo de memoria El modelo de memoria puede ser tiny, small, mdium, compact o large. Tambin existe el modelo huge, que requiere conocimientos avanzados para tratarlo, y que no estudiaremos en este libro. Los requisitos para cada modelo son: FORMATO ABREVIADO MODELO NUMERO DE SEGMENTOS NUMERO DE SEGMENTOS DE CODIGO DE DATOS TINY 1 (programas .COM: DS=CS=SS=ES) Small 1 1 Mdium ms de 1 1 Compact 1 ms de 1 Large ms de 1 ms de 1 A continuacin resolveremos un problema utilizando los dos formatos: Ejemplo 15 Escribir un programa en lenguaje Ensamblador que escriba en pantalla, un nmero decimal sin signo de 16 bits, esto es, un nmero cuyo valor est en el rango [0,65535] o en hexdecimal [0h,FFFFh] Solucin Antes de entrar a codificar, tenemos que resolver el problema manualmente. Ya conocemos las capacidades bsicas de una computadora y tenemos que resolver el problema solamente utilizando estas capacidades bsicas. Supongamos que tengamos el nmero 375, cmo podemos separar sus 3 dgitos?. La respuesta es recurriendo a la divisin entre 10, as tenemos: 375 = 37 y el resto es 5 10 37 = 3 y el resto es 7 10

85

3 = 0 y el resto es 3 10 Como vemos, dividendo el nmero dado 375 y los cocientes sucesivos entre 10, hasta que el cociente sea cero, los restos sucesivos obtenidos, que son 5, 7 y 3, resultan ser los dgitos del nmero, pero al revs. Entonces el problema ya est resuelto, hacemos varias divisiones sucesivas hasta que el cociente sea cero y guardamos los restos en memoria, utilizando la pila. Para repetir el procedimiento varias veces recurrimos a la capacidad bsica de hacer comparaciones simples. No olvidemos que para dividir dos nmeros, se tiene que guardar el dividendo en el par de registros DX:AX, y el divisor en un registro que no sea DX ni AX. En nuestro caso, como el nmero no puede ser mayor que FFFFh, hacemos DX=0 y movemos el valor del nmero a escribir en formato decimal al registro AX, y elegimos el registro SI, para almacenar el divisor cuyo valor es 10. Entonces el algoritmo seudocodigo es el siguiente: * Guardamos en la pila los restos de dividir entre 10 Cx=0 (contador) DX=0 AX=numero SI=10 Sigo: DIV SI Push DX CX=CX+1 ; cuento en cx los nmeros de la pila CMP AX,0 Salta a sigo si es mayor que cero * sacamos los restos de la pila y los escribimos en pantalla Muestro: pop dx Escribe dl en pantalla LOOP muestro Termina Ya tenemos los conocimientos necesarios para codificar este programa en lenguaje Ensamblador, que es lo que pasamos a hacer, primero en el formato clsico (Ejem15CL.ASM) y segundo en el formato abreviado (Ejem15AB.ASM); y aclaramos que solamente usaremos un solo segmento. de cdigo CS. Codificacin en formato clsico ; Programa Ejem15cl.asm Ejem15clEscribeNumeroDecimalFormatoClasico.asm
Codigo segment Assume cs:codigo main proc mov cx,0 mov dx,0

86

mov ax,9648 ; numero a escribir 9648 mov si,10 sigo: div si push dx add cx,1 mov dx,0 cmp ax,0 jg sigo ; jump if great salta a sigo si ax es mayor que 0 mov ah,2 muestro: pop dx add dl,30h int 21h loop muestro mov ah,4ch ; se prepara para terminar int 21h ; termina main endp codigo ends end main

Codificacin en formato abreviado ; Programa Ejem15ab.asm Ejem15ablEscribeNumeroDecimalFormatoAbreviado.asm .model small .code main proc mov cx,0 mov dx,0 mov ax,9648 ; nmero a escribir:9648 mov si,10 sigo: div si push dx add cx,1 mov dx,0 cmp ax,0 jg sigo ; jump if great salta a sigo si ax es mayor que 0 mov ah,2 muestro: pop dx add dl,30h int 21h loop muestro mov ah,4ch ; se prepara para terminar int 21h ; termina main endp end main La ejecucin de ambos programas se v a continuacin:

87

y en formato abreviado:

Ejemplo 16 Escribir un programa en lenguaje Ensamblador que escriba pantalla un nmero de 1 dgito hexadecimal. Solucin Utilizaremos solamente el formato abreviado, por ser ms funcional. La siguiente tabla es la de los caracteres ASCII, 0, 1, 2, . . . 8, 9, :, ;, <, =, >, ?, @, A, B, C, D, E, F. Carcter ASCII Hexadecimal 0 30 en

88

1 31 2 32 3 33 4 34 5 35 6 36 7 37 8 38 9 39 : 3A ; 3B < 3C = 3D 3E ? 3F @ 40 A 41 B 42 C 43 D 44 E 45 F 46 De acuerdo a esta tabla, si en DL tenemos almacenado cualquier nmero hexadecimal desde 0, 1, 2, ,9; y sumamos a DL el valor 30h, entonces obtenemos en DL el ASCII: 0, 1. 3, . . . , 9. Por ejemplo, para DL=8h = 10002, resulta DL=3h +30h = 38h, y si escribimos en pantalla el contenido de DL, obtendremos el carcter 8. Si en cambio tenemos en DL = Dh = 11012, si sumamos 30h, tenemos DL=Dh + 30h = 3Dh. Si escribimos en pantalla el valor DL obtenemos, de acuerdo a la tabla de ms arriba, el carcter =, que no es la respuesta correcta. Cmo resolvemos el problema?. Observemos que hay una franja de 7 datos que est entre 9 y A, y por tanto a DL hay que aadirle tambin 7. Esto es, si originalmente tenamos DL = Dh, si le sumamos ya no 30h, si no 37h, obtenemos DL = Dh + 37h = 44h. Ahora si escribimos el contenido de DL en pantalla obtenemos D, que es el resultado correcto.. En definitiva si en DL hay un nmero hexadecimal menor o igual que 9h se le suma 30h y si el nmero es mayor que 9, se le suma 37h. Entonces para escribir un nmero hexadecimal de 1 dgito, el algoritmo a aplicar es: escribe un nmero hexadecimal de 1 dgito mov dl,Numero ; dl=numero hexadecimal add dl,30h ; dl = dl + 30h
89

cmp dl,39h ; compara dl con 39h jle saltar ; dl 39 ir a saltar add dl,7 ; dl > 39, dl = dl + 7h saltar: escribe dl en pantalla El programa completo es el siguiente, que grabamos con el nombre ejem16.asm: ; Programa Ejem16.asm Ejem16EscribeNumeroHexadecimalDeUnDigito.asm .model small .code main proc mov dl,7 add dl,30h cmp dl,39h jle saltar add dl,7 saltar: mov ah,2 int 21h mov ah,4ch ; int 21h ; termina main endp end main Los resultados de ejecutar este programa primero con DL=7 y despus con DL=0Dh son los siguientes:

90

Ejemplo 17 Escribir un programa en lenguaje Ensamblador que escriba pantalla un nmero de 2 dgitos hexadecimales. en

91

Solucin Utilizando el programa Ejem16.asm disearemos un programa que escriba un nmero de 2 cifras hexadecimales. Ahora empezamos a nombre_de_procedimiento. usar la instruccin call

Supongamos que tenemos en DL= E7h =11100111 2 , y lo que pretendemos es que nuestro programa escriba en pantalla la cadena E7. Hacemos lo siguiente, utilizamos la instruccin SHR DL,CL(shift right), que produce un corrimiento de CL bits a la derecha, del contenido de DL, en la forma siguiente: DL = E7h 11100111 MOV CL,4 SHR DL,CL DL = 0Eh 00001110

y despus llamamos al procedimiento que escribe el valor 0Eh de DL. A continuacin utilizamos la instruccin AND para convertir en 0000 una parte de un registro. La tabla de AND, es el de la conjuncin, y est definida en la siguiente forma: AND 0 1 0 1 0 0 0 1

Entonces si DL = E7h = 111001112 DL = 111001112 0Fh = 000011112 AND DL,0Fh = 000001112 = 07h y nuevamente llamamos al procedimiento que escribe 1 hexadecimal es decir el nmero hexadecimal 7. El procedimiento main del programa ejem16.asm, tiene que adaptarse para que funcione como un procedimiento interno, que pueda ser activado desde otro procedimiento utilizando la instruccin call. Lo primero que tenemos que hacer es adoptar como nombre del procedimiento un identificador que nos recuerde en forma directa
92

cul es su funcin, es decir que el nombre suscintamente nos diga qu hace el procedimiento. En este caso, convenimos en llamar al procedimiento escribe_1_hexa, por que la tarea que va a ejecutar es justamente esa: escribir en pantalla un nmero de 1 dgito hexadecimal. El procedimiento main del programa ejem16.asm, ya convertido como procedimiento interno es el siguiente, y que puede ser utilizado por quin lo necesite (recurdese el concepto de reutilizacin): escribe_1_hexa proc push ax push dx add dl,30h cmp dl,39h jle saltar add dl,7 saltar: mov ah,2 int 21h pop dx pop ax ret escribe_1_decimal endp Adems del cambio de nombre, se suprime la instruccin mov dl,7 y se han aadido dos instrucciones push, y dos instrucciones pop; y al finalizar el procedimiento una instruccin ret (return). Las instrucciones push y pop tienen la funcin de retornar todos los registros que son utilizados dentro del procedimiento, tal como los recibi. Para el programador que llama (call) un procedimiento, este ltimo debe funcionar como una caja negra y por ningn motivo debe cambiar los valores de los registros. La instruccin ret (return en ingles -retorna en castellano-), permite retornar a la instruccin que sigue a la instruccin call. A continuacin damos todo el programa completo, el que se ha grabado con el nombre Ejem17.asm, y la pantalla con los resultados de correr este programa ; Programa Ejem17.asm Ejem17EscribeNumeroHexadecimalDeDosDigitos.asm
.model small .code principal proc mov dl,0E7h push dx mov cl,4 shr dl,cl call escribe_1_hexa pop dx and dl,0Fh

93

call escribe_1_hexa mov ah,4ch int 21h principal endp escribe_1_hexa proc push ax push dx add dl,30h

cmp dl,39h jle saltar add dl,7 saltar: mov ah,2 int 21h pop dx pop ax ret escribe_1_hexa endp

end principal

Ejemplo 18 Escribir un programa en lenguaje Ensamblador que escriba pantalla un nmero de 4 dgitos hexadecimales. Solucin en

94

Seguimos utilizando la stima capacidad bsica de las computadoras: la reutilizacin. Para escribir un nmero de 4 hexadecimales, llamaremos dos veces al procedimiento escribe_2_hexas, convenientemente adaptado. El siguiente es un programa con su respectivo segmento de datos, para declarar la variable de nombre numero de tamao 16 bits, es decir del tipo dw (define word) que describimos en el prrafo 3.2.3. formato de definicin de datos. Tambin en este programa aparece la directiva .386, que es valida para procesadores 80386 y posteriores, y que usamos porque permite usar las instrucciones pushA, -que equivale a las instrucciones push AX, push BX, . . . , push SI, push DI-, y la instruccin popA -que equivale a las instrucciones pop DI, pop SI, . . . , pop BX, pop AX-. El uso de estas instrucciones nos permite ahorrar cdigo. Tambin usamos la directiva ptr, que estudiaremos con ms detalle ms adelante, que permite mover un dato numrico al medio registro DL de 1 byte de tamao, desde la variable numero que es de 2 bytes. ; Programa Ejem18.asm Ejem18EscribeNumeroHexadecimalDeCuatroDigitos.asm .model small .data numero dw 0B5E4h ; dato a escribir en pantalla .code .386 main proc mov ax,@data mov ds,ax mov dl,byte ptr numero+1 ; dl = B5h call escribe_2_hexas mov dl,byte ptr numero ; dl = E4h call escribe_2_hexas mov ah,4ch int 21h main endp escribe_2_hexas proc; tiene como par metro a DL pushA push dx mov cl,4 shr dl,cl call escribe_1_hexa pop dx and dl,0Fh call escribe_1_hexa popA ret escribe_2_hexas endp escribe_1_hexa proc pushA
95

add dl,30h cmp dl,39h jle saltar add dl,7 saltar: mov ah,2 int 21h popA ret escribe_1_hexa endp end main El programa anterior se graba con el nombre Ejem18.asm y el resultado de su ensamble, enlace y ejecucin se pueden apreciar en la siguiente pantalla:

96

CAPITULO IV
4.1

PROGRAMAS .EXE vs PROGRAMAS .COM

Como ejecuta los programas el DOS

En el entorno MS-DOS existen tres tipos diferentes de programas ejecutables desde la lnea de comandos: los que tiene la extensin .COM (de COMmand), los que tiene la extensin .EXE (de EXEcutable), y los que tiene la extensin .BAT (de BATch). Este ltimo ya no se utiliza mucho, pero no deja de ser til. Ahora nos concentraremos en estudiar las diferencias entre programas .COM y :EXE y tambin las semejanzas. Si se tiene tres archivos con el mismo nombre prueba, pero diferentes extensiones .COM, .EXE y .BAT, el orden de prioridad en ejecucin es: prueba.COM prueba.EXE prueba.BAT es decir, si estn los tres y se digita, en la linea de comandos del DOS, la palabra prueba, se ejecuta el prueba.COM; si slo estn prueba:EXE y prueba.BAT se ejecuta el prueba.EXE; y si slo est el prueba.BAT, ste es el que se ejecuta; y si no est ninguno de los tres, el DOS escribe un mensaje de error, tal como este: comando o nombre de archivo no vlido. El prefijo del segmento de programa (PSP) El PSP (Program Segment Prefix) es una estructura usada para controlar ciertos aspectos del programa. Tiene una longitud de 256 bytes, y siempre est ubicado en los primeros 256 bytes del segmento donde se carga el programa. En esta estructura se almacena informacin importante, que es til para la programacin de sistemas y programacin de la computadora, que es un trabajo
97

muy diferente al de hacer programas de aplicacin. A continuacin se detalla la estructura del PSP. El PSP entre otros, como un ejemplo, contiene una tabla de manejadores de archivos, que se utiliza cuando se necesitan ms de 20 archivos abiertos al mismo tiempo. Programa cargador del sistema El Dos da soporte de carga a memoria, a dos tipos de programas ejecutables: .COM y .EXE. Un programa .COM consta de un solo segmento que contiene cdigo, datos y la pila. Si se necesita de un pequeo programa de utilera o un programa residente en memoria (un programa que es instalado permanentemente en y est disponible mientras otros programas estn ejecutndose), se escribe un programa .COM. Un programa .EXE consta de segmentos de cdigo, datos y de la pila separados y es el mtodo usado para la mayora de programas serios. 4.2. Programa tipo .COM Los programas .COM son una reminiscencia de la poca que predominaba el sistema operativo CP/M (el cual trabajaba con procesadores de 8 bits, que son los precursores del 8086 y dems familia). Este sistema operativo utilizaba la extensin COMmand para implicar que era un programa ejecutable (no existan los programa con extensin .EXE y slo se poda distinguir un programa ejecutable de los dems si tena la extensin .COM) Un tipo de programa .COM es almacenado en el disco exactamente como ser cargado en memoria para su ejecucin. Dicho de otra manera, el programa se almacena en el disco como una imagen exacta de lo que se cargar en la memoria y se ejecutar. El PSP de un programa .COM se carga en el desplazamiento 0 a FFh y el programa .COM empieza en el desplazamiento 100h. Todos los programas en lenguaje de mquina son .COM. La longitud de un programa .COM, est restringida a 64 Kbytes. Un programa .COM tiene un solo segmento fsico y cuatro segmentos lgicos el CS, DS, SS y ES, y todos tienen la misma direccin. Al final del segmento se usa una palabra (16 bits) como pila. Entonces, la longitud de un programa .COM es en realidad 65536 256 2 = 65278 bytes. Los 256 son los del PSP y los 2 son de la pila. Inicializacin de un programa .COM Cuando el DOS carga un programa .COM para ejecucin, inicializa de forma automtica todos los registros de segmentos con la direccin del PSP. Por tanto no se requiere programar su carga. Puesto que el direccionamiento comienza en un desplazamiento de 100H bytes desde el inicio del PSP, se necesita codificar una directiva ORG
98

como ORG 100h, inmediatamente despus de segment o el enunciado .CODE. La directiva ORG (Origin) le indica al emsamblador que empiece la generacin del cdigo objeto en un desplazamiento de 100h bytes pasando el inicio del PSP, en donde el programa .COM real comienza. La pila del .COM El registro SP que apunta a la cabeza de la pila se inicializa con el valor 0FFFEh, y el MS-DOS almacena un cero en la pila antes de pasarle el control al programa .COM. La pila inicializada con cero, es para que acte como desplazamiento para el IP, si se utiliza RET para terminar la ejecucin del programa. Si el programa .COM es grande, o si la memoria est limitada, se debe tener cuidado al enviar palabras a la pila. No debe olvidarse que la pila es una parte de la memoria. Adems diremos que existen dos formas de recuperar datos de la pila: en forma destructiva y en forma no destructiva que estuduaremos ms adelante. Conversin a formato .COM Si su programa ya est escrito en formato .EXE, puede utilizar un editor para convertir instrucciones a formato .COM. Los formatos de codificacin de MASM y TASM para programas .COM son idnticos, aunque sus mtodos de conversin difieren. Cuando la conversin .COM est completa, se puede borrar los archivos .OBJ y .EXE. Aqu estn los pasos para convertir un programa para Microsoft y Borland, suponiendo que ya fue creado con un editor el programa fuente de nombre Prueba.ASM MASM generado MASM Prueba Prueba.OBJ LINK Prueba; Prueba.COM Archivo generado Prueba.OBJ Prueba.EXE TASM Archivo

TASM Prueba TLINK /T Prueba

EXE2BIN Prueba Prueba.COM 4.3 Programas .EXE Por su parte los programas .EXE (contraccin de la palabra EXEcutable) pueden tener los cuatro tipos de segmento fsicos diferentes: CS, DS, SS y ES al mismo tiempo (Ver el programa PRUEBA.asm, del capitulo III).
99

Cuando el DOS carga un programa .EXE del disco a la memoria para su ejecucin construye un PSP de 256 bytes (100h) en un lmite de prrafo de memoria interna disponible y almacena el programa inmediatamente siguiendo al lmite. Despus el DOS hace lo siguiente: Carga la direccin del segmento de cdigo en el CS Carga la direccin de la pila en el SS; y Carga la direccin del PSP en los registros DS y ES

El cargador del DOS inicializa los registros CS:IP y SS:IP, pero no los registros DS y ES. Sin embargo, por lo comn su programa necesita la direccin del segmento de datos en el DS ( y con frecuencia tambin en el ES). Como consecuencia, tiene que inicializar el DS con la direccin del segmento de datos, con la instruccin mov. Vase el programa Prueba.asm en la seccin 3.2 Programa fuente. Los programas .EXE pueden ser tan grandes como lo permita la memoria instalada. Adems otra ventaja es que son reubicables; esto permite que ms de un programa sea cargado en memoria utilizando todo el espacio disponible. La desventaja de los archivos .EXE es el tamao de la cabecera aadida por el enlazador para hacer posible la reubicacin. En contraste, ya sabemos que un programa .COM tiene un solo segmento fsico. Cuando un programa en lenguaje ensamblador no es muy grande, un archivo .COM es ms que suficiente para incluir todo lo referente a datos, instrucciones y manipulaciones de pila. De forma distinta al archivo .EXE, el archivo .COM no es reubicable y debe comenzar en la direccin 100h. La ventaja de un archivo .COM sobre un archivo .EXE es que reducir significativamente el tamao del archivo ejecutable. EJEMPLO DE UN PROGRAMA .COM Ejemplo 19 Convertir a programa .COM el siguiente programa Ejem19EX.asm, que es un programa .EXE, y que tiene 3 segmentos fsicos (El segmento de la pila no se utiliza):

; Programa Ejem19EX.asm Ejem19EXProgramaEXEAConvertirSumaBinaria.asm ; Programa EXE

100

codigo segment assume cs:codigo, ds:datos, ss:pila main proc mov si,datos mov ds,si mov ah,9 lea dx,cuadro int 21h mov bx,x call binario lea dx,sigmas int 21h mov bx,y call binario lea dx,sigigual int 21h mov bx,x add bx,y call binario lea dx,saltos int 21h mov ah,4ch int 21h main endp binario proc push ax push bx push cx push dx mov cx,16 mov ah,2 sigo: rcl bx,1 mov dl,0 adc dl,30h int 21h loop sigo pop dx pop cx pop bx pop ax ret binario endp codigo ends datos segment x dw 13456 y dw 7685 cuadro db 12 dup (0ah) db 15 dup (20h),36 dup ("*"),0ah,0dh db 15 dup (20h),"* OPERACION DE SUMA BINARIA *",0ah,0dh db 15 dup (20h),36 dup ("*"),0ah,0ah,0ah,0dh, 5 dup (20h),"$" sigmas db " + $" sigigual db " = $" saltos db 9 dup (0ah),"$" datos ends pila segment stack db 10 dup ("PILA") pila ends end main

La conversin consiste en los siguientes pasos: 10) Suprimimos el segmento de pila, eliminando las siguientes instrucciones:
101

pila segment stack db 10 dup ('PILA') pila ends 20) Utilizamos la directiva GROUP, que sirve para agrupar dos o ms segmentos lgicos en un solo segmento fsico. La sintaxis de esta directiva es: nombre GROUP nombre_de_segmento1 [, nombre_de_segmento2...] En nuestro caso, como nombre utilizamos el identificador todos, que puede ser cualquier otro diferente, solo que tienen que empezar con una letra. La sigiente directiva tiene que colocarse antes de la directiva codigo segment: todos GROUP codigo,datos y esto nos obliga a modificar la directiva assume en la siguiente forma: assume: cs:todos, ds:todos 30) Antes de la directiva main proc, colocamos la directiva: org 100h, por que todo programa .COM comienza en el desplazamiento 100h. 40) Eliminamos las instrucciones: mov ax,datos mov ds,ax por que ya no son necesarias, dado que el programa .COM solamente tiene un solo segmento. 50) Eliminamos las instruccin mov ah,4ch e int 21h, y en su lugar colocamos la instruccin: int 20h que utilizan los programas .COM, para pasar el control al DOS Hechos estos cambios el programa .COM queda as:
; Programa Ejem19.asm Ejem19ProgramaCOMSumaBinaria.asm ; Programa COM group todo codigo,datos codigo segment assume cs:todo, ds:todo org 100h main proc mov ah,9 lea dx,cuadro

102

int 21h mov bx,x call binario (Continuacin) lea dx,sigmas int 21h mov bx,y call binario lea dx,sigigual int 21h mov bx,x add bx,y call binario lea dx,saltos int 21h int 20h main endp binario proc push ax push bx push cx push dx mov cx,16 mov ah,2 sigo: rcl bx,1 mov dl,0 adc dl,30h int 21h loop sigo pop dx pop cx pop bx pop ax ret binario endp codigo ends datos segment x dw 13456 y dw 7685 cuadro db 12 dup (0ah) db 15 dup (20h),36 dup ("*"),0ah,0dh db 15 dup (20h),"* OPERACION DE SUMA BINARIA *",0ah,0dh db 15 dup (20h),36 dup ("*"),0ah,0ah,0ah,0dh, 5 dup (20h),"$" sigmas db " + $" sigigual db " = $" saltos db 9 dup (0ah),"$" datos ends end main

ENSAMBLAJE, COMPILACION Y CONVERSION Los comandos para ensamblar, enlazar y conversin a .COM son los siguientes: TASM ejem19 <enter> LINK ejem19; <enter>

103

EXE2BIN ejem19 ejem19.com <enter> Para ejecutar el programa se digita el comando: Ejem19 <enter> El resultado de ejecutar este programa es el siguiente:

VERSION SIMPLIFICADA La version siguiente: en formato simplificado del programa .COM es el

; Programa .COM version simplificada ; Programa Ejem19VS.asm Ejem19VSProgramaCOMSumaBinaria.asm .model tiny .386 .data x dw 13456 y dw 7685 cuadro db 12 dup (0ah) db 15 dup (20h),36 dup ("*"),0ah,0dh db 15 dup (20h),"* OPERACION DE SUMA BINARIA *",0ah,0dh db 15 dup (20h),36 dup ("*"),0ah,0ah,0ah,0dh, 5 dup (20h),"$" sigmas db " + $" sigigual db " = $" saltos db 9 dup (0ah),"$" .code org 100h main proc mov ah,9 lea dx,cuadro int 21h mov bx,x call binario lea dx,sigmas int 21h mov bx,y call binario

104

lea dx,sigigual int 21h mov bx,x add bx,y call binario lea dx,saltos int 21h int 20h main endp (continuacin) binario proc pushA mov cx,16 mov ah,2 sigo: rcl bx,1 mov dl,0 adc dl,30h int 21h loop sigo popA ret binario endp end main

; termina el programa .COM

105

CAPITULO V

PROCEDIMIENTOS vs MACROS

5.1 Programacin modular La idea de programacin modular es producto del desarrollo de mtodos tericos para el diseo de programas. Bsicamente, la programacin modular consiste en dividir un programa en unidades ms pequeas, las cuales pueden ser probadas por separado para despus ser integradas en un programa que cumple con los objetivos de diseo originalmente propuestos. Esta definicin no dice nada con respecto al tamao de los mdulos, ni tampoco indica qu criterio debe emplearse para definirlo, ya sea en trminos abstractos o del nmero de lneas de cdigo. Afortunadamente se ha hecho un esfuerzo considerable para dar respuesta a estas cuestiones. Cada mdulo debe llevar a cabo una sola tarea que debe ser independiente de las que realizan los dems mdulos y contenida en su totalidad, con una sola entrada y una sola salida. En lenguaje ensamblador la programacin modular se realiza por procedimientos. Estos ltimos ya fueron estudiados en varios programas y, en muchos casos, constituyen una buena aproximacin para tareas pequeas o partes mayores de una tarea. 5.2 Procedimientos Hasta ahora los segmentos de cdigo han consistido slo en procedimientos near, codificados como: NOMBRE_PROCEDIMIENTO PROC ... ... RET NOMBRE_PROCEDIMIENTO ENDP En este caso la directiva PROC informa al sistema que la direccin indicada es el punto de entrada para la ejecucin del programa, mientras que la directiva ENDP define el final del procedimiento. Sin embargo, un segmento de cdigo puede tener cualquier nmero de procedimientos, todos distinguidos por PROC y ENDP. Un procedimiento (tambin subrutina o mdulo) activado por una instruccin CALL, es una seccin de cdigo que realiza una tarea definida y clara (tal como ubicar el cursor en una determinada posicin de la pantalla o bien obtener entrada del teclado)

106

La organizacin de un programa en procedimientos proporciona los beneficios siguientes: Reduce la cantidad de cdigo, ya que el procedimiento comn puede ser llamado varias veces y desde cualquier lugar en el segmento de cdigo Fortalece la mejor organizacin del programa. Facilita la depuracin del programa, ya que los errores pueden ser aislados con mayor claridad. Ayuda en el mantenimiento progresivo de programas, ya que los procedimientos son identificados de forma rpida para su modificacin.

La directiva PROC La directiva PROC (PROCedure o procedimiento en castellano) tiene el siguiente formato: Nombre_procedimiento PROC [atributo] Indica el comienzo del procedimiento nombre_procedimiento, que consiste en un bloque de instrucciones que sirven para realizar una tarea determinada y que puede invocarse desde varios puntos del programa. Un procedimiento puede ejecutarse por la instruccin CALL. El atributo puede ser NEAR que es el default, es decir si no se consigna el atributo- o FAR. Un procedimiento NEAR slo se puede llamar desde el segmento que est definido. Al llamar a un procedimiento NEAR, se guarda en la en la pila solo el desplazamiento (valor del IP) de la instruccin siguiente al CALL, que se recupera al retornar de un procedimiento con la instruccin RET . Un procedimiento FAR se puede llamar desde cualquier segmento. Al llamar a un procedimiento FAR, se guarda en la pila el segmento (valor de CS) y el desplazamiento (valor de IP), valores que se recuperan con la instruccin RET. Directiva PUBLIC Es posible desarrollar un programa que conste de un programa principal enlazado con uno o ms subprogramas ensamblados por separado. As, si queremos que el procedimiento o dato o etiqueta, sean accesibles desde uno o ms procedimientos PROC ensamblados por separado con el enlazador LINK.EXE, debe utilizarse la directiva PUBLIC, que tiene el siguiente formato: PUBLIC nombre [, . . . ] Donde nombre puede ser: El nombre de un procedimiento

107

El nombre de una variable Una etiqueta

( 1 ) Ejemplo si queremos que el procedimiento SUMAR sea accesible de otros mdulos separados, escribiremos: PUBLIC SUMAR SUMAR PROC [NEAR o FAR] ; Comienzo del procedimiento ... RET SUMAR ENDP ; Fin del procedimiento En este caso el mdulo activador debe declarar que el mdulo SUMAR es externo, utilizando la directiva EXTRN (EXTERN o externo en castellano), que identifica los elementos que fueron declarados pblicos en otro mdulo separado. EXTRN SUMAR:[NEAR o FAR] ( 2 ) Si queremos que una variable X, de tipo byte, sea accesible desde un mdulo separado, escribiremos: PUBLIC X X DB 34h,567 Que requiere la directiva EXTRN en el mdulo activador en la siguiente forma: EXTRN X:BYTE Para otros tipos de variable se utiliza: WORD para tipo DW ( 2 bytes), DWORD (4 bytes) para tipo DD. Las instrucciones CALL y RET La instruccin CALL transfiere el control a un procedimiento llamado, y la instruccin RET regresa del procedimiento llamado al procedimiento original que hizo la llamada. RET debe ser la ltima instruccin en un procedimiento llamado. Parmetros para pasar datos a un procedimiento PROC. Cuando se activa o se llama a un procedimiento es necesario pasarle datos y tambin el procedimiento debe retornar datos. Es un intercambio de informacin As como las personas pueden comunicarse e intercambiar informacin, podemos hacer que los programas se comuniquen e intercambien informacin. Un ejemplo practico de comunicacin es el que se presenta entre profesor y alumno, en el proceso de enseanza-aprendizaje. El profesor enva un mensaje al alumno, ste recibe el mensaje y debe enviar un mensaje de respuesta, es decir debe presentarse un ciclo cerrado de intercambio de informacin: profesor-alumno y alumnoprofesor; todo esto para que el proceso de enseanza-aprendizaje
108

sea exitoso. Esto se puede apreciar en la siguiente figura:

datos

profesor

alumno datos

En igual forma dos programas pueden intercambiar informacin. En vez del profesor podemos imaginar un programa activador que hace las veces de amo y en vez del alumno podemos imaginar otro programa activado que hace las veces de esclavo , ambos algoritmos intercambian datos. El proceso de intercambio de datos siempre lo inicia el algoritmo activador, por eso su condicin de amo. Convenimos en que al programa activado le llamaremos subprograma (o tambin rutina o mdulo).

DATOS programa activador (amo) DATOS programa activado (esclavo)

Pasemos a estudiar los subprogramas en detalle. En los lenguajes de programacin de alto nivel existen dos tipos de subprogramas. Ellos son llamados subprogramas procedimiento y subprogramas funcion. Hay ms similitudes que diferencias entre ambos tipos y los dos pueden hacer la misma tarea sin mayores cambios, y por lo tanto la eleccin depende mucho de las preferencias del programador. Podramos afirmar que cada programa

109

funcin tiene un programa procedimiento equivalente y viceversa. Pero hay situaciones en que un programa funcin se adapta mejor que su programa procedimiento equivalente, porque permite ahorrar lneas de cdigo. Algunos lenguajes trabajan con los dos tipos de subprogramas la mayora de lenguajes estn en esta categora otros en cambio como , el lenguaje C solo trabaja con subprogramas funcion y este marco filosfico de concepcin de la programacin le da a este lenguaje mucha potencia. En cambio el lenguaje Ensamblador solo trabaja con subprogramas procedimiento, que son los que hemos descrito SUBPROGRAMAS PROCEDIMIENTO Antes de dar otro ejemplo, sera apropiado resumir las ideas desarrolladas hasta aqu. Estas pueden ser ilustradas examinando la estructura del siguiente esquema:
pn=a
n

PROCEDIMIENTO NOMBRE(p 1,p2,p3,...,p r; pr+1,...,,p n)

* Programa principal p1=a1

p2=a2

...

p1pppp

retorna

CALL NOMBRE (a1, a2, a3,...,a n)

...

ar+1=pr+1, ar+2=pr+2, ... ,an=pn


,

Instruccin que sigue a la instruccin CALL En un lenguaje alto nivel cuando se ejecuta la instruccin Call (o su equivalente), la secuencia de eventos es como sigue:
1.

Los valores de los argumentos a1, a2, a3, ... ,an son asignados a los parmetros p1,p2,p3, ... ,pn.

2. El control se pasa a la primera instruccin ejecutable en el procedimiento. Cuando una instruccin retorna (RET en Ensamblador) es ejecutada (pueden haber varios RET), la secuencia de eventos es esta otra:
1.

Solamente los valores de los parmetros por referencia p r+1,pr+2, ... ,pn son asignados a los argumentos por referencia ar+1, ar+2, ... ,an ... El control se pasa la instruccin que sigue a la instruccin CALL

2.

Observaciones Naturalmente el nmero de argumentos debe ser el mismo en la lista de argumentos y en la lista de parmetros.
110

No slo eso, tambin deben ser del mismo tipo.

El lenguaje ensamblador para el paso de parmetros utiliza registros o variables de tipo public y/o tambin la pila. EJEMPLOS DE PROGRAMACION MODULAR. A continuacin disearemos procedimientos externos, esto es, que se encuentren en un archivo separado y que se enlazan usando el programa LINK:EXE. No debemos olvidar que el ensamblador (sea MASM.EXE o TASM.EXE) genera un programa objeto, que aunque est en lenguaje de mquina, todava no es ejecutable, por que le faltan otros componentes. Es el programa de utilidad LINK.EXE quien genera lo que se llama un programa reubicable, al aadir una cabecera adicional al archivo .OBJ ya generado por el ensamblador. Con esto el enlazador habilita al programa para que el sistema operativo lo pueda colocar en cualquier parte de memoria disponible. No slo esto, el programa LINK.EXE, permite ensamblar varias rutinas que han sido construidas en archivos separados, como pasamos a estudiar. 5.3 Generacin del programa PROCS.ASM con mdulos objeto Escribir dos procedimientos externos, (1) el primero de nombre clear, que blanquee la pantalla, y (2) el segundo gotoxy para posicionar el cursor en la pantalla. Estos dos procedimientos deben grabarse en el archivo PROCS.ASM De acuerdo al manual de interrupciones de los procesadores Intel de la familia X86, para limpiar pantalla o posicionar el cursor debemos utilizar la interrupcin del BIOS: int 10h, asociada a la pantalla. ( 1 ) Para limpiar la pantalla, usaremos la funcin AH=6, que desplaza (scroll) hacia arriba la pgina activa. Se requieren las siguientes entradas, es decir que se den antes de activar la interrupcin: AL = nmero de lneas. Las lneas de la parte inferior se borran. Si AL=0 se borra toda la ventana (pantalla). CH = Fila esquina superior izquierda CL = Columna esquina superior izquierda DH = Fila esquina inferior derecha DL = Columna esquina inferior derecha BH = Atributo a usar en los caracteres en la lnea en blanco Siendo el atributo 0 1 2 3 4 5 Negro Azul Verde Azul-Verde (cyan) Rojo Magenta

111

6 7

Marrn Blanco

De acuerdo a estos requerimientos el cdigo del procedimiento clear para blanquear la pantalla y que en ella se dibujen los caracteres en color blanco (atributo bh=7), en un fondo negro que es el color por default de la pantalla, es el siguiente: ; Procedimiento para limpiar pantalla, fondo blanco public clear clear proc near ; no requiere parmetros pushA mov al,0. mov cx,0 mov dh,24 entradas de la funcin AH=6 mov dl,79 mov bh,7 mov ah,6 ; solicitud de funcin de limpiado Int 10h ; procede a limpiar popA ret clear endp ( 2 ) Para posicionar el cursor utilizaremos la funcin AH=2, que requiere las siguientes entradas: DH = Fila (0 24) DL = Columna (0-79) BH = Nmero de pgina. La pantalla tiene cuatro pginas disponibles que se identifican con los nmeros 0,1,2 y 3, para el modo normal de 80 columnas. Por default se usa la pgina 0. En este caso requerimos dos parmetros el DH para la fila y el DL para la columna. El procedimiento resultante es: ; Procedimiento para posicionar el cursor public gotoxy gotoxy proc near ; Parmetros DH = fila DL=columna pushA mov bh,0 mov ah,2 ; solicitud para posicionar el cursor int 10h ; lo posiciona popA ret gotoxy endp Aunque estos procedimientos pueden guardarse en forma separada en sus propios archivos, por simplicidad de operacin, los

112

almacenaremos en un solo archivo, que llamaremos PROCS.ASM. Ms adelante a este archivo le agregaremos, uno por uno, nuevos procedimientos que tambin sern pblicos, y nos servir para construir una librera de mdulos objeto. Al juntarlos en un solo archivo de nombre PROCS.ASM, no importando en que orden se ubican, la disposicin en la que quedan es la siguiente es el siguiente: ; Programa PROCSProcedimientosClearGotoxy.asm
.model small .386 .code ; Procedimiento para limpiar pantalla, fondo blanco public clear clear proc near ; no requiere parmetros pushA mov al,0. mov cx,0 mov dh,24 mov dl,79 mov bh,7 mov ah,6 ; solicitud de funcin de limpiado Int 10h ; procede a limpiar popA ret clear endp ; Procedimiento para posicionar el cursor public gotoxy gotoxy proc near ; Parmetros DH = fila DL=columna pushA mov bh,0 mov ah,2 int 10h popA ret gotoxy endp end

PROCS.asm

Este programa solamente se ensambla, porque, solamente interesa generar el modulo objeto PROCS.OBJ, que ser suficiente para nuestros propsitos. Por ese motivo solamente se utiliza el comando: TASM PROCS <enter> El resultado de ensamblar el programa fuente PROCS.ASM, es el siguiente:

113

Ejemplo 20 Escribir el programa Ejem08.com, del ejemplo 8, que lee una cadena de teclado, la almacene en memoria y despus despliegue esta cadena en pantalla. El programa debe ser interactivo y tiene que utilizar las rutinas clear para borrar la pantalla y gotoxy para posicionar los mensajes. El diseo de pantalla es el siguiente: Ingrese una cadena Cadena leda : Estoy aprendiendo : Estoy aprendiendo

Ensamblador Ensamblador

Desea continuar (s/n)?: Como la lgica del programa, ya fue explicada ampliamente al disear el algoritmo del ejemplo 8, nos concentraremos en los cambios que deben hacerse para utilizar las rutinas clear y gotoxy, y para conseguir que el programa sea interactivo. Los cambios al programa original y las nuevas instrucciones se han escrito en letra negrita, para que se aprecien. ; Programa Ejem20.asm Ejem20LeeUnaCadenaYLaEscribeEnPantalla.asm .model small .data mensaje1 db Ingrese una cadena : $ mensaje2 db Cadena leida : $ mensaje3 db Desea continuar (s/n)?: $ cadena db 50,$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$$ .code extrn clear:near, gotoxy:near main proc mov ax,@data mov ds,ax
114

sigo: call clear mov dh,12 mov dl,14 call gotoxy lea dx,mensaje1 mov ah,9 int 21h lea dx,cadena mov ah,0Ah int 21h mov ah,2 mov dl,0Ah int 21h mov dh,13 mov dl,14 call gotoxy lea dx,mensaje2 mov ah,9 int 21h lea dx,cadena add dx,2 mov ah,9 int 21h mov dh,15 mov dl,14 call gotoxy lea dx,mensaje3 mov ah,9 int 21h mov ah,1 int 21h cmp al,s je sigo mov ah,4ch int 21h main endp end main Este programa se ensambla, enlaza y ejecuta, comandos: TASM ejem20 <enter> LINK ejem20 PROCS; <enter> Ejem20 <enter> El resultado de su ejecucin es el siguiente: con los siguientes

115

5.4 Una alternativa: las macros Lo mismo que se puede hacer con los procedimientos PROC, se puede lograr de otra manera muy distinta, utilizando la directiva macro. Una macro es un bloque de sentencias en lenguaje Ensamblador que utiliza una serie de parmetros. El formato de la directiva macro es el siguiente: nombre MACRO lista_de_parmetros ... instrucciones de lenguaje Ensamblador ... ENDM La primera directiva, que es la cabecera de la macro, comienza con un identificador que es el nombre de la macro y termina con una lista de parmetros que se separan por comas. El fin de la macro se indica mediante la directiva ENDM. Entre ambas directivas se incluyen las sentencias que constituyen el cuerpo de la macro. Los parmetros deben figurar en las instrucciones de la macro. La invocacin de una macro consiste en especificar el nombre de la macro, junto con los argumentos, que en la mayora de casos son iguales en nmero y en tipo que los parmetros de la macro, por que la macro es muy flexible en los casos que no cumple esta condicin: nombre_macro lista_de_argumentos Cada argumento se corresponde con cada parmetro y cuando se invoca la macro hace que se incluya en el bloque de sentencias que constituyen el cuerpo de la mquina, sustituyendo los parmetros de la macro por los argumentos. A este proceso se le llama expansin de la macro. En el listado del programa fuente ensamblado las lneas generadas se indican mediante el signo + en la columna 31. La columna 32 se deja en blanco. La columna 33 se corresponde con la 1
116

del mdulo fuente. Hacemos las siguientes observaciones: Pueden existir macros sin parmetros El nmero de argumentos en la invocacin de una macro no tiene por qu coincidir con el nmero de parmetros. Si hay ms argumentos que parmetros, se ignoran los argumentos que sobran. Si hay menos argumentos que parmetros, los parmetros que faltan se convierten en nulos.

Ejemplos: ( 1 ) Macro para calcular Z = X * Y PRODUCTO MACRO X,Y,Z1,Z2 mov ax,X mov si,Y mul si mov Z1,dx mov Z2,ax ENDM ; ax=X ; si=Y ; DX:AX=X * Y ; Z1=dx ; Z2=ax

Un programa de activacin para muliplicar 0FFFFh x =FFFFh es el siguiente .model small .data parte_alta dw ? parte_baja dw ? .code producto mecro X,Y,Z1,Z2 mov ax,X ; ax=X mov si,Y ; si=Y mul si ; DX:AX=X * Y mov Z1,dx ; Z1=dx mov Z2,ax ; Z2=ax endm main proc mov ax,@data mov ds,ax 0FFFFh,0FFFFh,parte_alta,parte_baja mov ah,4ch Int 21h main endp end La expansin resultante, de esta ltima instruccin es:

PRODUCTO

117

mov ax,0FFFFh mov si,0FFFFh mul si mov parte_alta,dx mov parte_baja,ax Si se corre el programa en parte_alta se almacena el valor FFFEh y en parte_ baja 0001h. ( 2 ) La siguiente es una macro que cuando se activa, escribe el carcter que se encuentra en el identificador uno tantas veces como indica el valor de dos lista macro uno,dos,tres mov dl,uno mov cx,dos mov ah,2 tres: int 21h add dl,1 loop tres endm por ejemplo si se corre el siguiente programa: ; Programa PruebaMC.asm PruebaMCPruebaUnaMacro.asm lista macro uno,dos,tres mov dl,uno mov cx,dos mov ah,2 tres: int 21h add dl,1 loop tres endm miguel segment assume cs:Miguel main proc lista 'A',10,sigo lista 'K',11,continuo mov ah,4ch int 21h main endp miguel ends end main

118

se producen dos expansiones, que son : mov dl,A mov cx,10 mov ah,2 sigo: int 21h add dl,1 loop sigo mov dl,K mov cx,11 mov ah,2 continuo: int 21h add dl,1 loop continuo Almacenemos el programa con el nombre PruebaMC.asm, y si se corre el programa escribe la cadena ABCDEFGHIJ seguida de la cadena KLMNOPQRSTU, como se puede apreciar en la siguiente pantalla

As como hemos empezado a construir un archivo de procedimientos PROCS.ASM, que despus convertiremos en una librera, se puede crear una biblioteca de macros. Para utilizar esta librera de macros se utiliza la directiva INCLUDE en la siguiente forma: INCLUDE C:\MACROS.LIB Siendo MACROS.LIB, el archivo que contiene las macros. Veamos un ejemplo: Ejemplo 21 El programa que se d ms abajo, de nombre PrPROCS.ASM, que lee un nmero como cadena y lo escribe al revs, utiliza los procedimientos clear y gotoxy. Se pide: ( 1 ) Escribir los procedimientos clear y gotoxy, como macros, utilizando los mismos nombres, y grabarlos en un archivo de nombre macros.lib ( 2 ) Modificar el programa PrPROCS.ASM, y ya modificado grabarlo con el nombre Ejem21.ASM, para que en vez de usar los procedimientos utilice la librera de macros.lib, creada en la
119

parte ( 1 ). ; Programa PrPROCS.asm PrPROCSPruebaProcedimientosClearGotoxy.asm .model small .386 .data titulo1 db "**************************************************************$" titulo2 db "* Archivo de Procs:PPROCS.ASM *$" titulo3 db "* Prueba de los modulos clear y gotoxy *$" titulo4 db "* Programa: PrPROCS.asm *$" titulo5 db "* Lee un numero como cadena y lo escribe al reves *$" titulo6 db "**************************************************************$" mensaje1 db "Ingrese un numero : $" mensaje2 db "Numero leido al reves : $" pregunta db "Desea continuar (s/n)? : $" numero db 255 .code extrn clear:near,gotoxy:near main proc mov ax,@data mov ds,ax mov es,ax sigo: mov dl,17h ; fondo_azul-letras_blancas call clear call titulo ;titulo es un procedimiento interno mov dh,17 mov dl,15 call gotoxy lea dx,mensaje1 mov ah,9 int 21h lea dx,numero mov ah,0ah int 21h mov di,1 mov cl,numero[di] mov dh,18 mov dl,15 call gotoxy lea dx,mensaje2 mov ah,9 int 21h
120

mov di,cx add di,2 repite: dec di mov dl,numero[di] mov ah,2 int 21h loop repite mov dh,20 mov dl,15 call gotoxy lea dx,pregunta mov ah,9 int 21h mov ah,1 int 21h cmp al,"s" je sigo mov ah,4ch int 21h main endp titulo proc pusha mov dh,8 mov dl,15 call gotoxy lea dx,titulo1 mov ah,9 int 21h mov dh,9 mov dl,15 call gotoxy lea dx,titulo2 mov ah,9 int 21h mov dh,10 mov dl,15 call gotoxy lea dx,titulo3 mov ah,9 int 21h mov dh,11 mov dl,15 call gotoxy lea dx,titulo4 mov ah,9 int 21h mov dh,12 mov dl,15 call gotoxy
121

lea dx,titulo5 mov ah,9 int 21h mov dh,13 mov dl,15 call gotoxy lea dx,titulo6 mov ah,9 int 21h popa ret titulo endp end main ( 1 ) Conversin a macros de los procedimientos clear y gotoxy La conversin es muy sencilla. La macro clear, no tendr parmetros y la macro gotoxy, tendra dos parmetros fil, para indicar la fila y col para indicar la columna. El archivo macros.lib contiene a las dos macros como apreciamos a continuacin: MacrosContieneLasMacrosClearGotoxy.LIB clear macro pushA mov al,0 mov cx,0 mov dh,24 mov dl,79 mov bh,7 mov ah,6 ; solicitud de funcion de limpiado Int 10h ; procede a limpiar popA endm gotoxy macro fil,col ; Parametros DH=fila DL=columna pushA mov dh,fil mov dl,col mov bh,0 mov ah,2 int 10h popA endm ;Macros.LIB

( 2 ) Conversin del programa PrPROCS.ASM y grabarlo como Ejem21.ASM, para usar las macros El siguiente es el programa ejem21.asm, que es el resultado de

122

convertir el programa original PrPROCS.ASM para que use las macros clear y gotoxy. ; Programa Ejem21.asm Ejem21LeeUnNumeroYLoEscribeAlRevesConMacros.asm .model small
.386 .data titulo1 db "****************************************************************$" titulo2 db "* Biblioteca MACROS.LIB *$" titulo3 db "* Prueba de las macros clear y gotoxy *$" titulo4 db "* Programa: Ejem21.asm *$" titulo5 db "* Lee un numero como cadena y lo escribe al reves *$" titulo6 db "****************************************************************$" mensaje1 db "Ingrese un numero : $" mensaje2 db "Numero leido al reves : $" pregunta db "Desea continuar (s/n)? : $" numero db 255 .code include macros.lib ; utiliza las macros main proc mov ax,@data mov ds,ax mov es,ax sigo: clear call titulo mov dh,17 mov dl,15 gotoxy 17,15 lea dx,mensaje1 mov ah,9 int 21h lea dx,numero mov ah,0ah int 21h mov di,1 mov cl,numero[di] mov dh,18 mov dl,15 gotoxy 18,15 lea dx,mensaje2 mov ah,9 int 21h mov di,cx add di,2 repite: dec di mov dl,numero[di] mov ah,2 int 21h loop repite gotoxy 20,15 lea dx,pregunta mov ah,9 int 21h

123

mov ah,1 int 21h cmp al,"s" je sigo mov ah,4ch int 21h main endp titulo proc pusha gotoxy 8,15 lea dx,titulo1 mov ah,9 int 21h gotoxy 9,15 lea dx,titulo2 mov ah,9 int 21h gotoxy 10,15 lea dx,titulo3 mov ah,9 int 21h gotoxy 11,15 lea dx,titulo4 mov ah,9 int 21h gotoxy 12,15 lea dx,titulo5 mov ah,9 int 21h gotoxy 13,15 lea dx,titulo6 mov ah,9 int 21h popa ret titulo endp end main

Primero es necesario ensamblar el archivo Macros.LIB, para verificar si no tiene errores de sintaxis, y obtenemos el siguiente resultado:

El error: Unexpected end of file encountered se genera porque el cdigo de las macros no tiene la instruccin End. Por tanto no le damos ninguna importancia.

124

El resultado de correr el programa Ejem21.asm, es es el siguiente:

125