Programcion hibrida

TECNOLOGICO DE ESTUDIOS SUPERIORES DE JOCOTITLAN INGENIERIA EN SISTEMAS COMPUTACIONALES ASIGNATURA:

SEMINARIO DE DESARROLLO DE PROYECTOS DE INVESTIGACION PROGRAMACION EN ENSAMBLADOR PARA PROCESADORES 80×86

DOCENTE: ISC. JUAN ALBERTO ANTONIO VELAZQUEZ

PRESENTA: ALVA HILARIO GUSTAVO BECERRIL LOPEZ NANCY CRUZ MATIAS DEISY GONZALEZ MALDONADO MARTHA YARELI ROMERO ORTEGA FRANCISCO JAVIER SANCHEZ CRUZ GUSTAVO

GRUPO:ISC-801 JOCOTITLAN MEXICO, 15 DE ABRIL DE 2008.

INDICE I. -CONCEPTOS BASICOS LENGUAJE MAQUINA Y ENSAMBLADOR INTERPRETES COMPILADORES Y ENSAMBLADORES PROCESO DE LIGA, RUTINAS RUN-TIME Y SERVICIOS DE S.

I. ARQUITECTURAS DE LOS MICROPROCESADORES SISTEMA OPERATIVO MS-DOS ENSAMBLADORES Y MACROENSAMBLADORES 6 6 7 7 8 16 17

II. -LENGUAJE ENSAMBLADOR IMPORTANCIA DEL LENGUAJE ENSAMBLADOR VENTAJAS Y DESVENTAJAS FORMATO DEL ENSAMBLADOR DIRECTIVAS CONJUNTO DE INSTRUCCIONES MACROS Y PROCEDIMIENTOS INTERRUPCIONES 18 18 18 20 21 23 26 28

III. -CREACION Y DEPURACION DE PROGRAMAS EN LENGUAJE ENSAMBLADOR EDICION ENSAMBLADO LINK EJECUCION DEPURACION UTILERIA EXE2BIN Y ARCHIVOS . EXE y . COM 28 28 29 30 30 31 31

IV. PROGRAMACION EN ENSAMBLADOR PROGRAMACION BASICA FORMATOS DE INSTRUCCIONES FORMATO DE UN PROGRAMA PROCESO DE ENSAMBLE Y LIGADO DE UN PROGRAMA INSTRUCCIONES DE TRANSFERENCIA DE DATOS INSTRUCCIONES ARITMETICAS INSTRUCCIONES PARA LA MANIPULACION DE BANDERAS INSTRUCCIONES DE SALTO INSTRUCCIONES PARA CICLOS INSTRUCCIONES LOGICAS INSTRUCCIONES DE ROTACION Y DESPLAZAMIENTO INSTRUCCIONES PARA LA PILA MANIPULACION DE

Lo sentimos, pero las muestras de ensayos completos están disponibles solo para usuarios registrados

Elija un plan de membresía
CADENAS INSTRUCCIONES PARA EL MANEJO DE STRINGS 32 32 32 33 33 34 36 39 41 44 45 46 48 49 50

PROGRAMACION DE ENTRADA Y SALIDA INERRUPCIONES DE SOFTWARE Y HARDWARE INTERRUPCIONES DEL BIOS INTERRUPCIONES DEL DOS MACROS PARAMETROS Y ETIQUETAS PROGRAMACION MODULAR PROCEDIMIENTOS PASO DE PARAMETROS PROGRAMACION HIBRIDA PASCAL Y ENSAMBLADOR 52 53 54 54 55 56 60 60 61 64 64

INTRODUCCION.

El presente trabajo, esta enfocado al lenguaje ensamblador de los procesadores 8088, 8086, 80186, 80188 y 80286, asi como todo lo necesario para programar en lenguaje ensamblador y todas las herramientas que nos proporciona este para realizar programas.

Este documento trata de abarcar, de la forma mas general, todo aquello que involucra el conocimiento y uso del lenguaje ensamblador. Ha sido organizado en CUATRO partes importantes que describen detalladamente aspectos relevantes a considerar para el uso de lenguaje ensamblador. La primera describe los conocimientos basicos que deben poseerse para una mejor comprension e interpretacion de lo que es el lenguaje ensamblador y como debe ser usado. La segunda parte presenta una breve descripcion de lo que es el lenguaje ensamblador, ventajas y desventajas de este, instrucciones generales, todo lo que nos proporciona el lenguaje ensamblador.

En el tercer apartado se mencionan los pasos para la creacion y depuracion ade un programa en lenguaje ensamblador. En la ultima parte se explican los tipos de programacion en lenguaje ensamblador asi como todas las instrucciones interrupciones, parametros, procedimientos en cada uno de ellos. . OBJETIVOS Proporcionar informacion a la comunidad estudiantil que les sirva de apoyo didactico en la elaboracion de investigaciones, realizacion de practicas y exposicion de proyectos en las distintas areas de conocimiento.

Presentar un proyecto de calidad en la materia de SEMINARIO DE DESARROLLO DE PROYECTOS DE INVESTIGACION EN EL TECNOLOGICO DE ESTUDIOS SUPERIORES DE JOCOTITLAN. I. -CONCEPTOS BASICOS. EL LENGUAJE DE MAQUINA Y EL LENGUAJE ENSAMBLADOR. Todo procesador, grande o pequeno, desde el de una calculadora hasta el de un supercomputador, ya sea de proposito general o especifico, posee un lenguaje unico que es capaz de reconocer y ejecutar. Por razones que resultan obvias, este lenguaje ha sido denominado Lenguaje de Maquina y mas que ser propio de un computador pertenece a su microprocesador.

El lenguaje de maquina esta compuesto por una serie de instrucciones, que son las unicas que pueden ser reconocidas y ejecutadas por el microprocesador. Este lenguaje es un conjunto de numeros que representan las operaciones que realiza el microprocesador a traves de su circuiteria interna. Estas instrucciones, por decirlo asi, estan grabadas o «alambradas» en el hardware y no pueden ser cambiadas. El nivel mas bajo al que podemos aspirar a llegar en el control de un microprocesador es precisamente el del lenguaje de maquina.

Ahora bien, siendo el lenguaje de maquina un conjunto de numeros, ? como es capaz el microprocesador de saber cuando un numero representa una instruccion y cuando un dato? El secreto de esto reside en la direccion de inicio de un programa y en el estado del microprocesador. La direccion de inicio nos indica en que localidad de memoria comienza un programa, y en consecuencia que datos deberemos considerar como instrucciones. El estado del microprocesador nos permite saber cuando este espera una instruccion y cuando este espera un dato.

Obviamente, el lenguaje de maquina de un microprocesador no puede ser ejecutado por otro microprocesador de arquitectura distinta, a menos que haya cierto tipo de compatibilidad prevista. Por ejemplo, un 80486 es capaz de ejecutar lenguaje de maquina propio y soporta el codigo generado para microprocesadores anteriores de la misma serie (desde un 8086 hasta un 80386). Por otra parte, un PowerPC es capaz de ejecutar instrucciones de los microprocesadores Motorola 68xxx y de los Intel 80xx/80×86.

En ambos casos, el diseno de los microprocesadores se hizo tratando de mantener cierto nivel de compatibilidad con los desarrollados anteriormente. En el segundo caso, este nivel de compatibilidad se extendio a los de otra marca. Sin embargo, un 8088 no puede ejecutar codigo de un 80186 o superiores, ya que los procesadores mas avanzados poseen juegos de instrucciones y registros nuevos no contenidos por un 8088. Un caso similar es la serie 68xxx, pero de ninguna manera podemos esperar que un Intel ejecute codigo de un Motorola y viceversa. Y esto no tiene nada que ver con la compania, ya que Intel desarrolla tros tipos de microprocesadores como el 80860 y el iWARP, los cuales no pueden compartir codigo ni entre ellos ni entre los 80xx/80xxx. Ahora bien, mientras que con el lenguaje de maquina, nosotros obtenemos un control total del microprocesador, la programacion en este lenguaje resulta muy dificil y facil para cometer errores. No tanto por el hecho de que las instrucciones son solo numeros, sino porque se debe calcular y trabajar con las direcciones de memoria de los datos, los saltos y las direcciones de llamadas a subrutinas, ademas de que para poder acer ejecutable un programa, se deben enlazar las rutinas de run-time y servicios del sistema operativo. Este proceso es al que se le denomina ensamblado de codigo. Para facilitar la elaboracion de programas a este nivel, se desarrollaron los Ensambladores y el Lenguaje Ensamblador. Existe una correspondencia 1 a 1 entre las instrucciones del lenguaje de maquina y las del lenguaje ensamblador. Cada uno de los valores numericos del lenguaje de maquina tiene una representacion simbolica de 3 a 5 letras como instruccion del lenguaje ensamblador.

Adicionalmente, este lenguaje proporciona un conjunto de pseudo-operaciones (tambien conocidas como directivas del ensamblador) que sirven para definir datos, rutinas y todo tipo de informacion para que el programa ejecutable sea creado de determinada forma y en determinado lugar.

INTERPRETES, COMPILADORES Y ENSAMBLADORES.

Aun cuando el lenguaje ensamblador fue disenado para hacer mas facil la programacion de bajo nivel, esta resulta todavia complicada y muy laboriosa.

Por tal motivo se desarrollaron los lenguajes de alto nivel, para facilitar la programacion de los computadores, minimizando la cantidad de instrucciones a especificar. Sin embargo, esto no quiere decir que el microprocesador ejecute dichos lenguajes. Cada una de las instrucciones de un lenguaje de alto nivel o de un nivel intermedio, equivalen a varias de lenguaje maquina o lenguaje ensamblador. La traduccion de las instrucciones de nivel superior a las de bajo nivel la realizan determinados programas. Por una parte tenemos los interpretes, como DBase, BASIC, APL, y Lisp.

En estos, cada vez que se encuentra una instruccion, se llama una determinada rutina de lenguaje de maquina que se encarga de realizar las operaciones asociadas, pero en ningun momento se genera un codigo objeto y mucho menos un codigo ejecutable. Por otra parte, tenemos los compiladores, como los desarrollados para Fortran, Clipper, COBOL, Pascal o C, que en vez de llamar y ejecutar una rutina en lenguaje de maquina, estos juntan esas rutinas para formar el codigo objeto que, despues de enlazar las rutinas de run-time y llamadas a otros programas y servicios del sistema operativo, se transformara en el programa ejecutable.

Finalmente, tenemos los ensambladores— como los descritos en este trabajo —que son como una version reducida y elemental de un compilador (pero que de ninguna manera deben considerarse como tales), ya que lo unico que tienen que hacer es cambiar toda referencia simbolica por la direccion correspondiente, calcular los saltos, resolver referencias y llamadas a otros programas, y realizar el proceso de enlace. Los ensambladores son programas destinados a realizar el ensamblado de un determinado codigo.

EL PROCESO DE LIGA, LAS RUTINAS DE RUN-TIME Y LOS SERVICIOS DEL SISTEMA OPERATIVO.

Para crear un programa ejecutable a partir de un codigo objeto se require que se resulevan las llamadas a otros programas y a los servicios del sistema operativo, y agregar las rutinas o informacion de run-time para que el programa pueda ser cargado a memoria y ejecutado. Este proceso es lo que se conoce como Link o proceso de liga, y se realiza a traves de un ligador o Linker que toma de entrada el codigo objeto y produce de salida el codigo ejecutable.

Las rutinas de run-time son necesarias, puesto que el sistema operativo requiere tener control sobre el programa en cualquier momento, ademas de que la asignacion de recursos y su acceso deben hacerse solamente a traves del sistema operativo. Para los computadores personales, esto no es tan complejo como para otros computadores y sistemas operativos, pero es requerido.

ARQUITECTURA DE LOS MICROPROCESADORES .

Sin importar de que microprocesador se trate, los microprocesadores del 8088 al 80486 usan el modelo de registros del 8086. Los microprocesadores matematicos 80287 al 80487 utilizan el modelo de registros expandidos del 8087.

Para mayor detalle ver los apendices A y B. Los microprocesadores matematicos estan disenados exclusivamente para efectuar operaciones aritmeticas de una manera mas rapida y precisa bajo el control de otro procesador razon por la cual se denominan coprocesadores. Estos tambien poseen un juego de instrucciones de lenguaje de maquina propio. La diferencia entre los diversos microprocesadores de uso general y los coprocesadores reside en el nuevo conjunto de instrucciones, registros y senalizadores agregados con cada nueva liberacion de un procesador superior.

Estas adiciones se hicieron con el fin de agregar un mayor poder de computo sin alterar la estructura basica, para asi mantener la compatibilidad con los desarollos anteriores, tanto de software como de hardware. La diferencia entre los 8086 y 8088 con los 80186 y 80188 no es muy grande, esta radica en un grupo de instrucciones que fueron agregadas al 80186 y al 80188. La diferencia entre el 8086 y el 8088, lo mismo que entre el 80186 y el 80188, es el modelo de memoria que usan ambos procesadores.

El 8088 y el 80188 estan disenados como microprocesadores de 8 bits por lo que el modo de acceso a la memoria es ligeramente distinto pero compatible con el 8086 y el 80186. Esto se vera con mas detalle en un tema posterior. Debido al tipo de microprocesador empleado, la memoria de la PC se encuentra dividida en una serie de blocks denominados segmentos, de 64KB cada uno. La memoria es accesada especificando el segmento y el desplazamiento dentro del segmento (segmento:desplazamiento, para mayor detalle ver el apendice C). Para las PC? la memoria se clasifica en tres tipos: – Convencional. Es la memoria de tipo basico y que abarca las direcciones de 0 a 640KB. En esta es donde se cargan los programas de usuario y el sistema operativo, y es la que esta disponible para equipo XT (8088,8086, 80186 y 80188). – Extendida. Esta memoria solo esta disponible para procesadores 80286 y mayores (equipo AT, 80386 y 80486). Muchos programas que usan la memoria convencional no pueden usar la memoria extendida porque las direcciones en memoria extendida estan mas alla de las que el programa puede reconocer.

Unicamente las direcciones dentro de los 640KB pueden ser reconocidas por todos los programas. Para reconocer la memoria extendida se requiere de un manejador de memoria extendida, como HIMEM. SYS que provee MS-DOS. – Expandida. Esta es la memoria que se agrega al computador a traves de una tarjeta de expansion, y que debe ser administrada por un programa especial, como el EMM386. EXE. A diferencia de la memoria convencional o extendida, la memoria expandida es dividida en bloques de 16K llamados paginas (pages) .

Cuando un programa solicita informacion de memoria expandida el manejador copia la pagina correspondiente en un area denominada page frame para poder ser accesada en la memoria extendida. Como podremos ver, el 8088, 8086, 80188 y 80186 son capaces de direccionar hasta 1 MB de memoria. Ya hemos indicado que la memoria convencional solo abarca 640KB, asi nos quedan 384KB libres. Esta parte de la memoria es denominada parte alta, y como no esta disponible para muchos programas generalmente se usa para cargar drivers del sistema perativo, programas residentes y datos de hardware (ROM y paginas de video). HISTORIA DE LOS PROCESADORES Con la aparicion de los circuitos integrados, la posibilidad de reducir el tamano de algunos dispositivos electronicos se vio enormemente favorecida. Los fabricantes de controladores integrados, calculadoras y algunos otros dispositivos comenzaron a solicitar sistemas integrados en una sola pastilla, esto dio origen a la aparicion de los microprocesadores.

Microprocesadores de 4 bits En 1971, una compania que se dedicaba a la fabricacion de memorias electronicas lanzo al mercado el primer microprocesador del mundo. Este microprocesador fue el resultado de un trabajo encargado por una empresa que se dedicaba a la fabricacion de calculadoras electronicas. El 4004 era un microprocesador de 4 bits capaz de direccionar 4096 localidades de memoria de 4 bits de ancho. Este microprocesador contaba con un conjunto de 45 instrucciones y fue ampliamente utilizado en los primeros videojuegos y sistemas de control.

Microprocesadores de 8 bits Con la aparicion de aplicaciones mas complejas para el microprocesador y el gran exito comercial del 4004, Intel decidio lanzar al mercado un nuevo microprocesador, el 8008, este fue el primer microprocesador de 8 bits. Las caracteristicas de este microprocesador fueron: Capacidad de direccionamiento de 16 Kb Memoria de 8 bits Conjunto de 48 instrucciones Este microprocesador tuvo tanto exito, que en cosa de dos anos su capacidad de proceso fue insuficiente para los ingenieros y desarrolladores, por lo cual en 1973 se libero el 8080.

Este microprocesador fue una version mejorada de su predecesor y las mejoras consistieron en un conjunto mas grande de instrucciones, mayor capacidad de direccionamiento y una mayor velocidad de procesamiento. Finalmente, en 1977, Intel anuncio la aparicion del 8085. Este era el ultimo microprocesador de 8 bits y basicamente identico al 8080. Su principal mejora fue la incorporacion del reloj temporizador dentro de la misma pastilla. Microprocesadores de 16 bits En 1978, Intel lanzo al mercado el 8086 y un poco mas tarde el 8088.

Estos dos microprocesadores contaban con registros internos de 16 bits, tenian un bus de datos externo de 16 y 8 bits respectivamente y ambos eran capaces de direccionar 1Mb de memoria por medio de un bus de direcciones de 20 lineas. Otra caracteristica importante fue que estos dos microprocesadores eran capaces de realizar la multiplicacion y la division por hardware, cosa que los anteriores no podian. Finalmente aparecio el 80286. Este era el ultimo microprocesador de 16 bits, el cual era una version mejorada del 8086.

El 286 incorporaba una unidad adicional para el manejo de memoria y era capaz de direccionar 16Mb en lugar de 1Mb del 8086. Microprocesadores de 32 bits El 80386 marco el inicio de la aparicion de los microprocesadores de 32 bits. Estos microprocesadores tenian grandes ventajas sobre sus predecesores, entre las cuales se pueden destacar: direccionamiento de hasta 4Gb de memoria, velocidades de operacion mas altas, conjuntos de instrucciones mas grandes y ademas contaban con memoria interna (cache) de 8Kb en las versiones mas basicas.

Del 386 surgieron diferentes versiones, las cuales se listan a continuacion. Modelo 80386DX 80386SL 80386SX 80486SX 80486DX Bus de Datos 32 16 16 32 32 Coprocesador matematico Si No No No Si Terminales del microprocesador En esta seccion se realizara una breve descripcion del conjunto de terminales del microprocesador mas representativo de la familia 80×86. El microprocesador 8086 puede trabajar en dos modos diferentes: el modo minimo y el modo maximo. En el modo maximo el microprocesador puede trabajar en forma conjunta con un microprocesador de datos numerico 8087 y algunos otros circuitos perifericos.

En el modo minimo el microprocesador trabaja de forma mas autonoma al no depender de circuitos auxiliares, pero esto a su vez le resta flexibilidad. En cualquiera de los dos modos, las terminales del microprocesador se pueden agrupar de la siguiente forma: Alimentacion Reloj Control y estado Direcciones Datos El 8086 cuenta con tres terminales de alimentacion: tierra (GND) en las terminales 1 y 20 y Vcc=5V en la terminal 40. En la terminal 19 se conecta la senal de reloj, la cual debe provenir de un generador de reloj externo al microprocesador.

El 8086 cuenta con 20 lineas de direcciones (al igual que el 8088). Estas lineas son llamadas A0 a A19 y proporcionan un rango de direccionamiento de 1MB. Para los datos, el 8086 comparte las 16 lineas mas bajas de sus lineas de direcciones, las cuales son llamadas AD0 a AD15. Esto se logra gracias a un canal de datos y direcciones multiplexado. En cuanto a las senales de control y estado tenemos las siguientes: La terminal MX/MN controla el cambio de modo del microprocesador. Las senales S0 a S7 son senales de estado, estas indican diferentes situaciones acerca del estado del microprocesador.

La senal RD en la terminal 32 indica una operacion de lectura. En la terminal 22 se encuentra la senal READY. Esta senal es utilizada por los diferentes dispositivos de E/S para indicarle al microprocesador si se encuentran listos para una transferencia. La senal RESET en la terminal 21 es utilizada para reinicializar el microprocesador. La senal NMI en la terminal 17 es una senal de interrupcion no enmascarable, lo cual significa que no puede ser manipulada por medio de software.

La senal INTR en la terminal 18 es tambien una senal de interrupcion, la diferencia radica en que esta senal si puede ser controlada por software. Las interrupciones se estudian mas adelante. La terminal TEST se utiliza para sincronizar al 8086 con otros microprocesadores en una configuracion en paralelo. Las terminales RQ/GT y LOCK se utilizan para controlar el trabajo en paralelo de dos o mas microprocesadores. La senal WR es utilizada por el microprocesador cuando este requiere realizar alguna operacion de escritura con la memoria o los dispositivos de E/S.

Las senales HOLD y HLDA son utilizadas para controlar el acceso al bus del sistema. DIAGRAMA DE COMPONENTES INTERNOS Descripcion de los componentes La figura 2 muestra la estructura interna del microprocesador 8086 con base en su modelo de programacion. El microprocesador se divide en dos bloques principales: la unidad de interfaz del bus y la unidad de ejecucion. Cada una de estas unidades opera de forma asincrona para maximizar el rendimiento general del microprocesador. Unidad de ejecucion Este elemento del microprocesador es el que se encarga de ejecutar las instrucciones.

La unidad de ejecucion comprende el conjunto de registros de proposito general, el registro de banderas y la unidad aritmetico-logica. Unidad de interfaz de bus Esta unidad, la cual se conoce como BIU (Bus Interface Unit), procesa todas las operaciones de lectura/escritura relacionadas con la memoria o con dispositivos de entrada/salida, provenientes de la unidad de ejecucion. Las instrucciones del programa que se esta ejecutando son leidas por anticipado por esta unidad y almacenadas en la cola de instrucciones, para despues ser transferidas a la unidad de ejecucion.

Unidad aritmetico-logica Conocida tambien como ALU, este componente del microprocesador es el que realmente realiza las operaciones aritmeticas (suma, resta, multiplicacion y division) y logicas (and, or, xor, etc. ) que se obtienen como instrucciones de los programas. Buses internos (datos y direcciones) Los buses internos son un conjunto de lineas paralelas (conductores) que interconectan las diferentes partes del microprocesador. Existen dos tipos principales: el bus de datos y el bus de direcciones.

El bus de datos es el encargado de transportar los datos entre las distintas partes del microprocesador; por otro lado, el bus de direcciones se encarga de transportar las direcciones para que los datos puedan ser introducidos o extraidos de la memoria o dispositivos de entrada y salida. Cola de instrucciones La cola de instrucciones es una pila de tipo FIFO (primero en entrar, primero en salir) donde las instrucciones son almacenadas antes de que la unidad de ejecucion las ejecute.

Registros de proposito general El microprocesador 8086 cuenta con cuatro registros de proposito general, los cuales pueden ser usados libremente por los programadores. Estos registros reciben los nombres siguientes: AX (Acumulador) Este registro es el encargado de almacenar el resultado de algunas operaciones aritmeticas y logicas. BX (Base) Este registro es utilizado para calcular direcciones relativas de datos en la memoria. CX (Contador) Su funcion principal es la de almacenar el numero de veces que un ciclo de instrucciones debe repetirse.

DX (Datos) Por lo general se utiliza para acceder a las variables almacenadas en la memoria. Registros apuntadores El 8086 tambien cuenta con dos registros apuntadores SP y BP. Estos registros reciben su nombre por que su funcion principal es la de apuntar a alguna direccion de memoria especifica. SP (Apuntador de pila) Se encarga de controlar el acceso de los datos a la pila de los programas. Todos los programas en lenguaje ensamblador utilizan una pila para almacenar datos en forma temporal. BP (Apuntador Base) Su funcion es la de proporcionar direcciones para la transferencia e intercambio de datos.

Registros indices Existen dos registros llamados SI y DI que estan estrechamente ligados con operaciones de cadenas de datos. SI (Indice Fuente) Proporciona la direccion inicial para que una cadena sea manipulada. DI (Indice Destino) Proporciona la direccion de destino donde por lo general una cadena sera almacenada despues de alguna operacion de transferencia. Registros de segmento El 8086 cuenta con cuatro registros especiales llamados registros de segmento. CS (Segmento de codigo) Contiene la direccion base del lugar donde inicia el programa almacenado en memoria.

DS (Segmento de datos) Contiene la direccion base del lugar del area de memoria donde fueron almacenadas las variables del programa. ES (Segmento extra) Este registro por lo general contiene la misma direccion que el registro DS. SS (Segmento de Pila) Contiene la direccion base del lugar donde inicia el area de memoria reservada para la pila. Registro apuntador de instrucciones IP (Apuntador de instrucciones) Este registro contiene la direccion de desplazamiento del lugar de memoria donde esta la siguiente instruccion que sera ejecutada por el microprocesador.

Registro de estado Conocido tambien como registro de banderas (Flags), tiene como funcion principal almacenar el estado individual de las diferentes condiciones que son manejadas por el microprocesador. Estas condiciones por lo general cambian de estado despues de cualquier operacion aritmetica o logica: CF (Acarreo) Esta bandera indica el acarreo o prestamo despues de una suma o resta. OF (Sobreflujo) Esta bandera indica cuando el resultado de una suma o resta de numeros con signo sobrepasa la capacidad de almacenamiento de los registros.

SF (Signo) Esta bandera indica si el resultado de una operacion es positivo o negativo. SF=0 es positivo, SF=1 es negativo. DF (Direccion) Indica el sentido en el que los datos seran transferidos en operaciones de manipulacion de cadenas. DF=1 es de derecha a izquierda y DF=0 es de izquierda a derecha. ZF (Cero) Indica si el resultado de una operacion aritmetica o logica fue cero o diferente de cero. ZF=0 es diferente y ZF=1 es cero. IF (interrupcion) Activa y desactiva la terminal INTR del microprocesador. PF (paridad) Indica la paridad de un numero.

Si PF=0 la paridad es impar y si PF=1 la paridad es par. AF (Acarreo auxiliar) Indica si despues de una operacion de suma o resta ha ocurrido un acarreo de los bits 3 al 4. TF (Trampa) Esta bandera controla la ejecucion paso por paso de un programa con fines de depuracion. Funcionamiento interno (ejecucion de un programa) Para que un microprocesador ejecute un programa es necesario que este haya sido ensamblado, enlazado y cargado en memoria. Una vez que el programa se encuentra en la memoria, el microprocesador ejecuta los siguientes pasos: 1. Extrae de la memoria la instruccion que va a ejecutar y la coloca en el registro interno de instrucciones. 2. – Cambia el registro apuntador de instrucciones (IP) de modo que senale a la siguiente instruccion del programa. 3. – Determina el tipo de instruccion que acaba de extraer. 4. – Verifica si la instruccion requiere datos de la memoria y, si es asi, determina donde estan situados. 5. – Extrae los datos, si los hay, y los carga en los registros internos del CPU. 6. – Ejecuta la instruccion. 7. – Almacena los resultados en el lugar apropiado. 8. – Regresa al paso 1 para ejecutar la instruccion siguiente.

Este procedimiento lo lleva a cabo el microprocesador millones de veces por segundo. Manejo de memoria Segmentacion El microprocesador 8086, como ya se menciono, cuenta externamente con 20 lineas de direcciones, con lo cual puede direccionar hasta 1 MB (00000h–FFFFFh) de localidades de memoria. En los dias en los que este microprocesador fue disenado, alcanzar 1MB de direcciones de memoria era algo extraordinario, solo que existia un problema: internamente todos los registros del microprocesador tienen una longitud de 16 bits, con lo cual solo se pueden direccionar 64 KB de localidades de memoria.

Resulta obvio que con este diseno se desperdicia una gran cantidad de espacio de almacenamiento; la solucion a este problema fue la segmentacion. La segmentacion consiste en dividir la memoria de la computadora en segmentos. Un segmento es un grupo de localidades con una longitud minima de 16 bytes y maxima de 64KB. La mayoria de los programas disenados en lenguaje ensamblador y en cualquier otro lenguaje definen cuatro segmentos. El segmento de codigo, el segmento de datos, el segmento extra y el segmento de pila. A cada no de estos segmentos se le asigna una direccion inicial y esta es almacenada en los registros de segmento correspondiente, CS para el codigo, DS para los datos, ES para el segmento extra y SS para la pila. Direccion fisica Para que el microprocesador pueda acceder a cualquier localidad de memoria dentro del rango de 1MB, debe colocar la direccion de dicha localidad en el formato de 20 bits. Para lograr esto, el microprocesador realiza una operacion conocida como calculo de direccion real o fisica. Esta operacion toma el contenido de dos registros de 16 bits y obtiene una direccion de 20 bits.

La formula que utiliza el microprocesador es la siguiente: Dir. Fisica = Dir. Segmento * 10h + Dir. Desplazamiento Por ejemplo: si el microprocesador quiere acceder a la variable X almacenada en memoria, necesita conocer su direccion desplazamiento. La direccion segmento para las variables es proporcionada por el registro DS. Para este caso, supongamos que X tiene el desplazamiento 0100h dentro del segmento de datos y que DS tiene la direccion segmento 1000h, la direccion fisica de la variable X dentro del espacio de 1Mb sera: Dir. Fisica = 1000h * 10h +0100h Dir. Fisica = 10000h + 0100h Dir.

Fisica = 10100h (direccion en formato de 20 bits). Direccion efectiva (desplazamiento) La direccion efectiva (desplazamiento) se refiere a la direccion de una localidad de memoria con respecto a la direccion inicial de un segmento. Las direcciones efectivas solo pueden tomar valores entre 0000h y FFFFh, esto es porque los segmentos estan limitados a un espacio de 64 Kb de memoria. En el ejemplo anterior, la direccion real de la variable X fue de 10100h, y su direccion efectiva o de desplazamiento fue de 100h con respecto al segmento de datos que comienza en la direccion 10000h.

Direccionamiento de los datos En la mayoria de las instrucciones en lenguaje ensamblador, se hace referencia a datos que se encuentran almacenados en diferentes medios, por ejemplo: registros, localidades de memoria, variables, etc. Para que el microprocesador ejecute correctamente las instrucciones y entregue los resultados esperados, es necesario que se indique la fuente o el origen de los datos con los que va a trabajar, a esto se le conoce como direccionamiento de datos. En los microprocesadores 80×86 existen cuatro formas de indicar el origen de los datos y se llaman modos de direccionamiento.

Para explicar estos cuatro modos, tomaremos como ejemplo la instruccion mas utilizada en los programas en ensamblador, la instruccion MOV. La instruccion MOV permite transferir (copiar) informacion entre dos operandos; estos operandos pueden ser registros, variables o datos directos colocados por el programador. El formato de la instruccion MOV es el siguiente: Mov Oper1,Oper2 Esta instruccion copia el contenido de Oper2 en Oper1. Direccionamiento directo Este modo se conoce como directo, debido a que en el segundo operando se indica la direccion de desplazamiento donde se encuentran los datos de origen.

Ejemplo: Mov AX,[1000h] ;Copia en AX lo que se encuentre almacenado en ; DS:1000h Direccionamiento inmediato En este modo, los datos son proporcionados directamente como parte de la instruccion. Ejemplo: Mov AX,34h Mov CX,10 ;Copia en AX el numero 34h hexadecimal ;Copia en CX el numero 10 en decimal Direccionamiento por registro En este modo de direccionamiento, el segundo operando es un registro, el cual contiene los datos con los que el microprocesador ejecutara la instruccion. Ejemplo: Mov AX,BX ;Copia en AX el contenido del reg

Direccionamiento indirecto por registro Finalmente, en el modo indirecto por registro, el segundo operando es un registro, el cual contiene la direccion desplazamiento correspondiente a los datos para la instruccion. Ejemplo: Mov AX,[BX] ; Copia en AX el dato que se encuentre en la localidad de ;memoria DS:[BX] Los parentesis cuadrados sirven para indicar al ensamblador que el numero no se refiere a un dato, si no que se refiere a la localidad de memoria. En los siguientes capitulos se muestran varios programas, en los cuales podra identificar los diferentes modos de direccionamiento de datos.

EL SISTEMA OPERATIVO MS-DOS. Junto con todo lo visto anteriormente, y como se menciono anteriomente, uno de los componentes que caracterizan los computadores personales es su sistema operativo. Una PC puede correr varios sistemas operativos: CP/M, CP/M-86, XENIX, Windows, PC-DOS, y MS-DOS. Lo que los define es la forma en que estan integrados sus servicios y la forma en que se accesa a ellos. Esto es precisamente lo que el linker debe enlazar y resolver. Aqui nos enfocaremos exclusivamente en el sistema operativo MS-DOS, y lo que se mencione aqui sera valido para las versiones 3. y superiores. Este sistema operativo esta organizado de la siguiente manera: Comandos Internos (reconocidos y ejecutados por el COMMAND. COM) Comandos Externos ( . EXEs y . COMs ) Utilerias y drivers (programas de administracion del sistema) Shell (Interfaz amigable, solo versiones 4. 0 o mayores) Servicios (Interrupciones) Los servicios, mas conocidos como interrupciones o vectores de interrupcion, es parte medular de lo que es MS-DOS, y no son mas que rutinas definidas por MS-DOS y el BIOS, ubicadas a partir de una localidad de memoria especifica.

La manera de accesar a estas rutinas y a los servicios que ofrecen es mediante una instruccion que permite ejecutar una interrupcion. MS-DOS proporciona dos modulos: IBMBIO. COM (provee una interfaz de bajo nivel para el BIOS) e IBMDOS. COM (contiene un manejador de archivos y servicios para manejo de registros). En equipos compatibles estos archivos tienen los nombres IO. SYS y MSDOS. SYS, respectivamente. El acceso a los servicios del computador se realiza de la siguiente manera: Programa DOS DOS ROM EXTERNO de usuario Alto nivel Bajo nivel peticion de — IBMDOS. COM — IBMBIO.

COM — BIOS — Dispositivo I/O ENSAMBLADORES Y MACROENSAMBLADORES. Existen varios ensambladores disponibles para ambiente MS-DOS: el IBM Macro Assembler, el Turbo Assembler de Borland, el Turbo Editassm de Speedware, por citar algunos. Una breve descripcion de cada uno se propociona a continuacion. Macro Ensamblador IBM. – Esta integrado por un ensamblador y un macroensamblador. En gran medida su funcionamiento y forma de invocarlo es sumamente similar al de Microsoft. Su forma de uso consiste en generar un archivo fuente en codigo ASCII, se procede a generar un programa objeto que es ligado y se genera un programa .

EXE. Opcionalmente puede recurirse a la utileria EXE2BIN de MS-DOS para transformarlo a . COM. Es capaz de generar un listado con informacion del proceso de ensamble y referencias cruzadas. Macro Ensamblador de Microsoft. – Dependiendo de la version, este ensamblador es capaz de soportar el juego de instrucciones de distintos tipos de microprocesadores Intel de la serie 80xx/80×86. En su version 4. 0 este soporta desde el 8086 al 80286 y los coprocesadores 8087 y 80287. Requiere 128KB de memoria y sistema operativo MS-DOS v2. 0 o superior.

Trabaja con un archivo de codigo fuente creado a partir de un editor y grabado en formato ASCII. Este archivo es usado para el proceso de ensamble y generacion de codigo objeto. Posteriormente, y con un ligador, es creado el codigo ejecutable en formato . EXE. Turbo Editassm. – Este es desarrollado por Speddware, Inc. , y consiste de un ambiente integrado que incluye un editor y utilerias para el proceso de ensamble y depuracion. Es capaz de realizar el ensamble linea a linea, conforme se introducen los mnemonicos, y permite revisar listas de referencias cruzadas y contenido de los registros.

Este ensamblador trabaja con tablas en memoria, por lo que la generacion del codigo ejecutable no implica la invocacion explicita del ligador por parte del programador. Adicionalmente permite la generacion de listados de mensajes e informacion de cada etapa del proceso y la capacidad de creacion de archivos de codigo objeto. Turbo Assembler. – De Borland Intl. , es muy superior al Turbo Editassm. Trabaja de la misma forma, pero proporciona una interfaz mucho mas facil de usar y un mayor conjunto de utilerias y servicios.

En lo que se refiere a las presentes notas, nos enfocaremos al Microsoft Macro Assembler v4. 0. Los programas ejemplo han sido desarrollados con este y esta garantizado su funcionamiento. Estos mismo programas posiblemente funcionen con otros ensambladores sin cambios o con cambios minimos cuando utilizan directivas o p s e u d o i n s t r u c c i o n e s . Realmente la diferencia entre los ensambladores radica en la forma de generar el codigo y en las directivas con que cuente, aunque estas diferencias son minimas.

El codigo ensamblador no cambia puesto que los microprocesadores con los que se va a trabajar son comunes. Asi, todos los programas que se creen con un ensamblador en particular podran ser ensamblados en otro, cambiando las pseudo-operaciones no reconocidas por el equivalente indicado en el manual de referencia del paquete empleado. Los programas que componen el Macro Ensamblador Microsoft v4. 0 son los siguientes: Programa Descripcion MASM. EXE Microsoft Macro Assembler LINK. EXE Microsoft 8086 object linker SYMDEB. EXE Microsoft Symbolic Debuger Utility MAPSYM. EXE

Microsoft Symbol File Generator CREF. EXE Microsoft Cross-Reference Utility LIB. EXE Microsoft Library Manager MAKE. EXE Microsoft Program Maintenance Utility EXEPACK. EXE Microsoft EXE File Compression Utility EXEMOD. EXE Microsoft EXE File Header Utility COUNT. ASM Sample source file for SYMDEB session README. DOC Updated information obtained after the manual was printed. El Microsoft Macro Assembler v4. 0 crea codigo ejecutable para procesadores 8086, 8088, 80186, 80188, 80286, 8087 y 80287. Ademas es capaz de aprovechar las instrucciones del 80286 en la creacion de codigo protegido y no protegido.

El termino macroensamblador es usado para indicar que el ensamblador en cuestion tiene la capacidad de poder ensamblar programas con facilidad de macro. Una macro es una pseudo-instruccion que define un conjunto de instrucciones asociadas a un nombre simbolico. Por cada ocurrencia en el codigo de esta macro, el ensamblador se encarga de substituir esa llamada por todas las instrucciones asociadas y, en caso de existir, se dejan los parametros con los que se estaba llamando la macro y no con los que habia sido definida.

Es importante senalar que no se deja una llamada, como a una subrutina o procedimiento, sino que se incorporan todas las instrucciones que definen a la macro. II. – EL LENGUAJE ENSAMBLADOR. Importancia del lenguaje ensamblador El lenguaje ensamblador es la forma mas basica de programar un microprocesador para que este sea capaz de realizar las tareas o los calculos que se le requieran. El lenguaje ensamblador es onocido como un lenguaje de bajo nivel, esto significa que nos permite controlar el 100 % de las funciones de un microprocesador, asi como los perifericos asociados a este. A diferencia de los lenguajes de alto nivel, por ejemplo “Pascal”, el lenguaje ensamblador no requiere de un compilador, esto es debido a que las instrucciones en lenguaje ensamblador son traducidas directamente a codigo binario y despues son colocadas en memoria para que el microprocesador las tome directamente.

Aprender a programar en lenguaje ensamblador no es facil, se requiere un cierto nivel de conocimiento de la arquitectura y organizacion de las computadoras, ademas del conocimiento de programacion en algun otro lenguaje. Ventajas del lenguaje ensamblador: Velocidad de ejecucion de los programas Mayor control sobre el hardware de la computadora Desventajas del lenguaje ensamblador: Repeticion constante de grupos de instrucciones No existe una sintaxis estandarizada Dificultad para encontrar errores en los programas (bugs) UN EJEMPLO

Para comenzar veamos un pequeno ejemplo que ilustra el formato del programa fuente. Este ejemplo esta completamente desarrollado en lenguaje ensamblador que usa servicios o funciones de MS-DOS (system calls) para imprimir el mensaje Hola mundo!! en pantalla. ; HOLA. ASM ; Programa clasico de ejemplo. Despliega una leyenda en pantalla. STACK SEGMENT STACK ; Segmento de pila DW 64 DUP (? ) ; Define espacio en la pila STACK ENDS DATA SEGMENT ; Segmento de datos SALUDO DB «Hola mundo!! «,13,10,»$» ; Cadena DATA ENDS CODE SEGMENT ; Segmento de Codigo

ASSUME CS:CODE, DS:DATA, SS:STACK INICIO: ; Punto de entrada al programa MOV AX,DATA ; Pone direccion en AX MOV DS,AX ; Pone la direccion en los registros MOV DX,OFFSET SALUDO ; Obtiene direccion del mensaje MOV AH,09H ; Funcion: Visualizar cadena INT 21H ; Servicio: Funciones alto nivel DOS MOV AH,4CH ; Funcion: Terminar INT 21H CODE ENDS END INICIO ; Marca fin y define INICIO La descripcion del programa es como sigue: 1. – Las declaraciones SEGMENT y ENDS definen los segmentos a usar. 2. – La variable SALUDO en el segmento DATA, define la cadena a ser desplegada.

El signo del dolar al final de la cadena (denominado centinela) es requerido por la funcion de visualizacion de la cadena de MS-DOS. La cadena incluye los codigos para carriage-return y line-feed. 3. – La etiqueta START en el segmento de codigo marca el inicio de las instrucciones del programa.

4. – La declaracion DW en el segmento de pila define el espacio para ser usado por el stack del programa.

5. – La declaracion ASSUME indica que registros de segmento se asociaran con las etiquetas declaradas en las definiciones de segmentos.

6. – Las primeras dos instrucciones cargan la direccion del segmento de datos en el registro DS. Estas instrucciones no son necesarias para los segmentos de codigo y stack puesto que la direccion del segmento de codigo siempre es cargado en el registro CS y la direccion de la declaracion del stack segment es automaticamente cargada en el registro SS.

7. – Las ultimas dos instrucciones del segmento CODE usa la funcion 4CH de MS-DOS para regresar el control al sistema operativo. Existen muchas otras formas de hacer esto, pero esta es la mas recomendada. 8. La directiva END indica el final del codigo fuente y especifica a START como punto de arranque.

EL FORMATO DEL ENSAMBLADOR.

De acuerdo a las convenciones y notacion seguidas en el manual del Microsoft Macro Assembler. Negritas Comandos, simbolos y parametros a ser usados como se muestra. Italicas Todo aquello que debe ser reemplazado por el usuario ? ? Indican un parametro opcional ,,, Denota un parametros que puede repetirse varias veces ¦ Separa dos valores mutuamente excluyentes letra chica Usada para ejemplos. Codigo y lo que aparece en pantalla.

Cada programa en lenguaje ensamblador es creado a partir de un archivo fuente de codigo ensamblador. Estos son archivos de texto que contienen todas las declaraciones de datos e instrucciones que componen al programa y que se agrupan en areas o secciones, cada una con un proposito especial. Las sentencias en ensamblador tienen la siguiente [nombre> mnemonico [operandos> [;comentarios> sintaxis: En cuanto a la estructura, todos los archivos fuente tienen la misma forma: cero o mas segmentos de programa seguidos por una directiva END.

No hay una regla sobre la estructura u orden que deben seguir las diversas secciones o areas en la creacion del codigo fuente de un programa en ensamblador. Sin embargo la mayoria de los programas tiene un segmento de datos, un segmento de codigo y un segmento de stack, los cuales pueden ser puestos en cualquier lugar. Para la definicion de datos y declaracion de instrucciones y operandos el MASM reconoce el conjunto de caracteres formado por letras mayusculas, letras minusculas (excluyendo caracteres acentuados, n, N), numeros, y los simbolos: ? @ _ $ : . > ( ) { } + – / *&%!? ~¦=# ;,»` La declaracion de numeros requiere tener presente ciertas consideraciones. En el MASM un entero se refiere a un numero entero: combinacion de digitos hexadecimales, octales, decimales o binarios, mas una raiz opcional. La raiz se especifica con B, Q u O, D, o H. El ensamblador usara siempre la raiz decimal por defecto, si se omite la especificacion de la raiz (la cual se puede cambiar con la directiva . RADIX). Asi nosotros podemos especificar un entero de la siguiente manera: digitos, digitosB, digitosQ o digitosO, digitosD, digitosH.

Si una D o B aparecen al final de un numero, estas siempre se consideraran un especificador de raiz, e. g. 11B sera tratado como 112 (210), mientras que si se trata del numero 11B16 debe introducirse como 11Bh. Para los numeros reales tenemos al designador R, que solo puede ser usado con numeros hexadecimales de 8, 16, o 20 digitos de la forma digitosR. Tambien puede usarse una de las directivas DD, DQ, y DT con el formato [+¦->digitos. digitos[E[+¦->digitos>. Las cadenas de caracter y constantes alfanumericas son formadas como ? caracteres? o «caracteres» . Para referencias simbolicas se utilizan cadenas especiales enominadas nombres. Los nombres son cadenas de caracteres que no se entrecomillan y que deben comenzar con una A.. Z ¦ a.. z ¦ _ ¦ $ ¦ @ los caracteres restantes pueden ser cualquiera de los permitidos, y solamente los 31 primeros caracteres son reconocidos.

DIRECTIVAS.

El MASM posee un conjunto de instrucciones que no pertenecen al lenguaje ensamblador propiamente sino que son instrucciones que unicamente son reconocidas por el ensambldor y que han sido agregadas para facilitar la tarea de ensablamblado, tanto para el programador como para el programa que lo lleva a cabo. Dichas instrucciones son denominadas directivas.

En general, las directivas son usadas para especificar la organizacion de memoria, realizar ensamblado condicional, definir macros, entrada, salida, control de archivos, listados, cross-reference, direcciones e informacion acerca de la estructura de un programa y las declaraciones de datos. * Conjunto de instrucciones. – Dentro de las directivas mas importantes, tenemos las que establecen el conjunto de instrucciones a soportar para un microprocesador en especial: . 8086(default). – Activa las instrucciones para el 8086 y 8088 e inhibe las del 80186 y 8 0 2 8 6 . 8087(default). – Activa instrucciones para el 8087 y desactiva las del 80287. 186. – Activa las instrucciones del 80186. . .286c. Activa instrucciones del 80286 en modo no protegido. .289p. – Activa instrucciones del 80286 en modo protegido y no protegido. .287. – Activa las instrucciones para el 80287. * Declaracion de segmentos. – En lo que respecta a la estructura del programa tenemos las directivas SEGMENT y ENDS que marcan el inicio y final de un segmento del programa. Un segmento de programa es una coleccion de instrucciones y/o datos cuyas direcciones son todas relativas para el mismo registro de segmento. Su sintaxis es: nombre SEGMENT [alineacion> [combinacion> [? lase? > nombre ENDS El nombre del segmento es dado por nombre, y debe ser unico. Segmentos con el mismo nombre se tratan como un mismo segmento. Las opciones alineacion, combinacion, y clase proporcionan informacion al LINK sobre como ajustar los segmentos. Para alineacion tenemos los siguientes valores: byte (usa cualquier byte de direccion), word (usa cualquier palabra de direccion, 2 bytes/word), para (usa direcciones de parrafos, 16 bytes/parrafo, deafult), y page (usa direcciones de pagina, 256 bytes/page). combinacion define como se combinaran los segmentos con el mismo nombre.

Puede asumir valores de: public (concatena todos los segmentos en uno solo), stack (igual al anterior, pero con direcciones relativas al registro SS, common (crea segmentos sobrepuestos colocando el inicio de todos en una misma direccion), memory (indica al LINK tratar los segmentos igual que MASM con public, at address (direccionamiento relativo a address). clase indica el tipo de segmento, senalados con cualquier nombre. Cabe senalar que en la definicion esta permitido el anidar segmentos, pero no se permite de ninguna manera el sobreponerlos. * Fin de codigo fuente. – Otra directiva importante es la ue indica el final de un modulo. Al alcanzarla el ensamblador ignorara cualquier otra declaracion que siga a esta. Su sintaxis es: END [expresion> la opcion expresion permite definir la direccion en la cual el programa iniciara. * Asignacion de segmentos. – La directiva ASSUME permite indicar cuales seran los valores por default que asimiran los registros de segmento. Existen dos formas de hacer esto: ASSUME registrosegmento:nombre,,, ASSUME NOTHING NOTHING cancela valores previos. * Etiquetas. – Las etiquetas son declaradas nombre: donde nombre constituye una cadena de caracteres. Declaracion de datos. – Estos se declaran segun el tipo, mediante la regla [nombre> directiva valor,,, donde directiva puede ser DB (bytes), DW (palabras), DD (palabra doble), DQ (palabra cuadruple), DT (diez bytes). Tambien pueden usarse las directivas LABEL (crea etiquetas de instrucciones o datos), EQU (crea simbolos de igualdad) , y el simbolo = ( asigna absolutos) para declarar simbolos. Estos tienen la siguiente sintaxis: nombre = expresion nombre EQU expresion nombre LABEL tipo donde tipo puede ser BYTE, WORD, DWORD, QWORD, TBYTE, NEAR, FAR. * Declaracion de estructuras. Para la declaracion de estructuras de datos se emplea la directiva STRUC. Su sintaxis es: nombre STRUC campos nombre ENDS CONJUNTO DE INSTRUCCIONES. El juego completo de instrucciones reconocidas por los procesadores intel 8086 a 80286, junto con los coprocesadores 8087 y 80287, se enlistan en el apendice E. Como puede verse en dicho apendice, la mayoria de las instrucciones requieren algunos operandos o expresiones para trabajar, y lo cual es valido tambien para las directivas. Los operandos representan valores, registros o localidades de memoria a ser accesadas de alguna manera.

Las expresiones combinan operandos y operadores aritmeticos y logicos para calcular en valor o la direccion a acceder. Los operandos permitidos se enlistan a continuacion: Constantes. – Pueden ser numeros, cadenas o expresiones que representan un valor fijo. Por ejemplo, para cargar un registro con valor constante usariamos la instruccion MOV indicando el registro y el valor que cargariamos dicho registro. mov ax,9 mov al,? c? mov bx,65535/3 mov cx,count count solo sera valido si este fue declarado con la directiva EQU. Directos. Aqui se debe especificar la direccion de memoria a accesar en la forma segmento:offset. mov ax,ss:0031h mov al,data:0 mov bx,DGROUP:block Relocalizables. – Por medio de un simbolo asociado a una direccion de memoria y que puede ser usado tambien para llamados. mov ax, value call main mov al,OFFSET dgroup:tabla mov bx, count count solo sera valido si fue declarado con la directiva DW. Contador de localizacion. – Usado para indicar la actual localizacion en el actual segmento durante el ensamblado. Representado con el simbolo $ y tambien conocido como centinela. help DB ? OPCIONES? 13,10 F1 DB ? F1 salva pantalla? ,13,10 . . . F10 DB ? F10 exit? ,13,10,? $ DISTANCIA = $-help Registros. – Cuando se hace referencia a cualquiera de los registros de proposito general, apuntadores, indices, o de segmento. Basados. – Un operador basado representa una direccion de memoria relativa a uno de los registros de base (BP o BX). Su sintaxis es: desplazamiento[BP> desplazamiento[BX> [desplazamiento>[BP> [BP+desplazamiento> [BP>. desplazamiento [BP>+desplazamiento en cada caso la direccion efectiva es la suma del desplazamiento y el contenido del registro. ov ax,[BP> mov al,[bx> mov bx,12[bx> mov bx,fred[bp> Indexado. – Un operador indexado representa una direccion de memoria relativa a uno de los registros indice (SI o DI). Su sintaxis es: desplazamiento[DI> desplazamiento[SI> [desplazamiento>[DI> [DI+desplazamiento> [DI>. desplazamiento [DI>+desplazamiento en cada caso la direccion efectiva es la suma del desplazamiento y el contenido del registro. mov ax,[si> mov al,[di> mov bx,12[di> mov bx,fred[si> Base-indexados. Un operador base-indexado representa una direccion de memoria relativa a la combinacion de los registros de base e indice. Su sintaxis es: desplazamiento[BP>[SI> desplazamiento[BX>[DI> desplazamiento[BX>[SI> desplazamiento[BP>[DI> [desplazamiento>[BP>[DI> [BP+DI+desplazamiento> [BP+DI>. desplazamiento [DI>+desplazamiento+[BP> en cada caso la direccion efectiva es la suma del desplazamiento y el contenido del registro. mov ax,[BP>[si> mov al,[bx+di> mov bx,12[bp+di> mov bx,fred[bx>[si> Estructuras. – Su sintaxis es variable. ampo. variable es el nombre con que se declaro la estructura, y campo es el nombre del campo dentro de la estructura. date STRUC mes DW ? dia DW ? aa DW ? date ENDS actual date ? ja? ,? 01? ,? 84? mov ax,actual. dia mov actual. aa, ? 85? Operadores y expresiones. – Se cuenta con los siguientes operadores: -aritmeticos expresion1 * expresion2 expresion1 / expresion2 expresion1 MOD expresion2 expresion1 + expresion2 expresion1 – expresion2 + expresion – expresion -de corrimiento expresion1 SHR contador expresion1 SHL contador -relacionales expresion1 EQ expresion2 xpresion1 NE expresion2 expresion1 LT expresion2 expresion1 LE expresion2 expresion1 GT expresion2 expresion1 GE expresion2 – de bit NOT expresion expresion1 AND expresion2 expresion1 OR expresion2 expresion1 XOR expresion2 -de indice [expresion1> [expresion2> ejemplos: mov al, string[3> mov string[last>,al mov cx,dgroup:[1> ; igual a mov cx,dgroup:1 -de apuntador tipo PTR expresion tipo puede ser BYTE o 1, WORD o 2, DWORD o 4, QWORD o 8, TBYTE o 10, NEAR o 0FFFFh, FAR o 0FFFEh.

Ejemplos: call FAR PTR subrout3 mov BYTE ptr [array>, 1 add al, BYTE ptr [full_word> -de nombre de campo estructura. campo ejemplos: inc month. day mov time. min,0 mov [bx>. dest -de proposito especial. OFFSET expresion. – Regresa el desplazamiento del operando mov bx, OFFSET dgroup:array mov bx, offset subrout3 SHORT etiqueta. – Para un salto de menos de 128 bytes jmp SHORT loop LENGTH variable. – Regresa el numero de elementos de variable segun su tipo mov cx,length array SIZE variable. – Regresa el tamano en ytes alojados para variable mov cx,size array SEG expresion. – Regresa el valor del segmento para expresion mov ax, SEG saludo MACROS Y PROCEDIMIENTOS. La manera mas facil de modularizar un programa es dividirlo en dos o mas partes. Para esto, es necesario que datos, simbolos, y demas valores de un modulo sean reconocidos por el otro u otros modulos. Para este tipo de declaraciones globales existen dos directivas: PUBLIC nombre,,, que hace la variable, etiqueta o simbolo absoluto disponible para todos los programas.

EXTRN nombre:tipo,,, que especifica una variable, etiqueta o simbolo externos identificados por nombre y tipo (que puede ser BYTE, WORD, DWORD, QWORD, TBYTE, NEAR, FAR, o ABS, este ultimo para numeros absolutos). El siguiente ejemplo ilustra el uso de las directivas. El primer listado corresponde al modulo principal, mientras que el segundo al modulo que contiene una rutina. Ambos modulos son archivos que se editan por separado, se ensamblan por separado, pero se ligan juntos. MODULO PRINCIPAL: MAIN. ASM NAME main PUBLIC exit EXTRN print:near stack SEGMENT word stack ‘STACK’ DW 64 DUP(? stack ENDS data SEGMENT word public ‘DATA’ data ENDS code SEGMENT byte public ‘CODE’ ASSUME cs:code, ds:data start: mov ax,data ; carga localizacion del segmento mov ds,ax ; en el registro DS jmp print ; va a PRINT en el otro modulo exit: mov ah,4ch int 21h code ENDS END start SUBMODULO: TASK. ASM NAME task PUBLIC print EXTRN exit:near data SEGMENT word public ‘DATA’ entrada DB «Entrando a un submodulo…. «,13,10,»$» salida DB «……. saliendo del submodulo. «,01,07,13,10,»$» data ENDS code SEGMENT byte public ‘CODE’ ASSUME cs:code, ds:data print: mov ah,06h ; Funcion para borrar pantalla mov al,0 ; todas las lineas ov cx,0 ; de 0,0 mov dh,24d mov dl,79d mov bh,0 ; atributo en lineas vacias int 10h ; Servicio de e/s video mov dx, OFFSET entrada mov ah,09h int 21h mov dx, OFFSET salida int 21h jmp exit ; Regresa al otro modulo code ENDS END La declaracion de macros se hace a traves de las directivas MACRO y ENDM. Su sintaxis es: nombre MACRO [parametros,,,> declaraciones ENDM parametros son los valores que se substituiran en la macro cada vez que se haga referencia a esta. Para la definicion de procedimientos se emplean las directivas PROC y ENDP.

Su sintaxis es: nombre PROC [distancia> sentencias nombre ENDP distancia, que puede ser NEAR (default) o FAR permiten indicar el tipo de acciones a realizar en brincos y llamados a subrutinas. nombre se puede usar como direccion en llamados o brincos. INTERRUPCIONES. Como se menciono anteriormente la PC esta constituida logicamente por su BIOS y sistema operativo. La mayoria de las rutinas que controlan al computador estan grabadas en el ROM del BIOS, aunque muchas rutinas son establecidas por el sistema operativo y se cargan en RAM al momento de encender al computador.

Estas rutinas son denominadas interrupciones y son activadas mediante la instruccion: INT numero. Una interrupcion es una operacion que invoca la ejecucion de una rutina especifica que suspende la ejecucion del programa que la llamo, de tal manera que el sistema toma control del computador colocando en el stack el contenido de los registros CS e IP. El programa suspendido vuelve a activarse cuando termina la ejecucion de la interrupcion y son restablecidos los registros salvados.

Existen dos razones para ejecutar una interrupcion: (1) intencionalmente como peticion para la entrada o salida de datos de un dispositivo, y (2) un error serio y no intencional, como sobreflujo o division por cero. El operando de una interrupcion indica cual es la rutina a activar. La direccion de la rutina es localizada por medio de una tabla que el sistema mantiene a partir de la direccion 0000:0000h. Existen 256 entradas de 4 bytes de longitud, y cada interrupcion proporciona varias funciones. Las interrupciones de 00h a 1Fh correponden al BIOS y de 20h a FFh son del DOS y BASIC.

El apendice F proporciona una lista de las interrupciones para equipo XT. III.

CREACION Y DEPURACION DE PROGRAMAS EN LENGUAJE ENSAMBLADOR EDICION.

Los archivos fuente de codigo ensamblador deben estar en formato ASCII standard. Para esto puede usarse cualquier editor que permita crear archivos sin formato, e. g. Edlin, Edit, Write, El editor del Turbo Pascal, Works, Word, WordStar, etcetera. Las declaraciones pueden ser introducidas en mayusculas y/o minusculas. Una buena practica de programacion es poner todas las palabras reservadas (directivas e instrucciones) en mayusculas y todo lo del usuario en minusculas para fines de facilidad e lectura del c o d i g o . Las sentencias pueden comenzar en cualquier columna, no pueden tener mas de 128 caracteres, no se permiten lineas multiples ni codigos de control, y cada linea debe ser terminada con una combinacion de line-feed y carriage-return. Los comentarios se declaran con ; y terminan al final de la linea. ENSAMBLADO. El ensamblado se lleva a cabo invocando al MASM. Este puese ser invocado, usando una linea de comando, de la siguiente manera: MASM archivo [,[objeto>[,[listado>[,[cross>>>>>[opciones>[;> donde: archivo. – Corresponde al programa fuente.

Por default se toma la extension . ASM. objeto. – Es el nombre para el archivo objeto. listado. – Nombre del archivo de listado de ensamblado. cross. – Es un archivo de referencias cruzadas. opciones. – Pueden ser: /A escribe los segmentos en orden alfabetico /S escribe los segmentos en orden del fuente /Bnum fija buffer de tamano num /C especifica un archivo de referencias cruzadas /L especifica un listado de ensamble /D crea listado del paso 1 /Dsym define un simbolo que puede usarse en el ensamble /Ipath fija path para buscar archivos a incluir /ML mantiene sensitividad de letras (mayus. minus) en nombres /MX mantiene sensitividad en nombre publicos y externos /MU convierte nombres a mayusculas /N suprime tablas en listados /P checa por codigo impuro /R crea codigo para instrucciones de punto flotante /E crea codigo para emular instrucciones de punto flotante /T suprime mensajes de ensable exitoso /V despliega estadisticas adicionales en pantalla /X incluir condicionales falsos en pantalla /Z despliega lineas de error en pantalla si el ; al final se omite es necesario poner todas las comas que se indican. Si no se quiere poner algun valor basta con dejar la coma. tra forma de invocar al ensamblador es solo tecleando MASM y respondiendo a la informacion que se solicita. Para omitir algun valor solo basta teclear ENTER si dar ningun valor. L I N K . De la misma forma que el ensamblado, la fase de liga se lleva a cabo con el LINK. Este puede ser invocado de la misma forma que el MASM. Los parametros que este requiere son: LINK objeto [,[ejecutable>[,[mapa>[,[libreria>>>>>[opciones>[;> donde: objeto. – Es el nombre para el archivo . OBJ ejecutable. – Nombre del archivo . EXE mapa. – Nombre del archivo mapa libreria. – Nombre del archivo biblioteca de rutinas opciones. Pueden ser: /HELP muestra lista de opciones /PAUSE pausa en el proceso /EXEPACK empaca archivo ejecutable /MAP crea mapa se simbolos publicos /LINENUMBERS copia numero de lineas al mapa /NOIGNORECASE mantiene sensitividad en nombres /NODEFAULTLIBRARYSEARCH no usa bibliotecas por default /STACK:size fija el tamano del stack a usar /CPARMAXALLOC:numero fija alojacion maxima de espacio /HIGH fija la direccion de carga mas alta /DSALLOCATE aloja grupo de datos /NOGROUPASSOCIATION ignora asociaciones para direcciones /OVERLAYINTERRUPT:numero asigan nuevo numero a la INT 03Fh /SEGMENTS:numero procesa un numero de segmentos /DOSSEG sigue la convencion de orden de DOS EJECUCION. Para la ejecucion del programa simplemente basta teclear su nombre en el prompt de MS-DOS y teclear ENTER.

Con esto el programa sera cargado en memoria y el sistema procedera a ejecutarlo. Lo que se veria en pantalla seria lo siguiente: C:DATAPROGRAMSASM>masm main Microsoft (R) Macro Assembler Version 4. 00 Copyright (C) Microsoft Corp 1981, 1983, 1984, 1985. All rights reserved. Object filename [main. OBJ>: Source listing [NUL. LST>: Cross-reference [NUL. CRF>: 50966 Bytes symbol space free 0 Warning Errors 0 Severe Errors C:DATAPROGRAMSASM>masm task Microsoft (R) Macro Assembler Version 4. 00 Copyright (C) Microsoft Corp 1981, 1983, 1984, 1985. All rights reserved. Object filename [task. OBJ>: Source listing [NUL. LST>: Cross-reference [NUL. CRF>: 51034 Bytes symbol space free 0 Warning Errors 0 Severe Errors C:DATAPROGRAMSASM>link main+task Microsoft (R) 8086 Object Linker Version 3. 05 Copyright (C) Microsoft Corp 1983, 1984, 1985. All rights reserved. Run File [MAIN. EXE>: List File [NUL. MAP>: Libraries [. LIB>: C:DATAPROGRAMSASM>main Entrando a un submodulo…. ……. saliendo del submodulo. C:DATAPROGRAMSASM> DEPURACION. Para la depuracion de un programa en ensamblador tenemos disponibles dos herramientas. Por un lado tenemos el debuger que nos proporciona MS-DOS (DEBUG. EXE) y por otro lado tenemos el que nos proporciona Microsoft (SYMDEB. EXE). Este ultimo trabaja igual que el de MS-DOS pero nos proporciona muchas ventajas mas. Una de ellas es a facilidad de desplegar el codigo fuente correspondiente a la instruccion que se esta ejecutando (si el programa ejecutable fue ensamblado o compilado con un ensamblador o compilador compatible), nos permite ejecutar comandos del S. O. y nos permite obtener informacion de las interrupciones de manera simbolica. LA UTILERIA EXE2BIN Y LOS ARCHIVOS . EXE Y . COM . Para MS-DOS solo existen dos tipo de archivos ejecutables los . COM y . EXE. Ambos archivos difieren en algunas cosas. Primero, las ventajas de los . EXE son dobles, nos permiten tener archivos reubicables y el uso de hasta cuatro segmentos (STACK, DATA, EXTRA y CODE) de hasta 64KB cada uno. Un archivo.

COM solo puede tener un segmento de 64KB, en el que se tiene tanto codigo como pila, y datos. La desventaja de los . EXE es que agregan 512 bytes como cabecera con informacion para la reubicacion del codigo. Un . COM no es reubicable, siempre inicia en la direccion 0100H. Si nuestro programa no es muy grande 64KB son mas que suficientes. Por lo que conviene crearlo como . COM, para esto se cuenta con la utileria EXE2BIN. EXE que nos proporciona el sistema operativo. y que nos permite crear . COM a partir de . EXE . Las restricciones para esto son las suguientes: el archivo a convertir no debe estar empacado, no debe tener segmento de stack, debe tener solo segmento de codigo y su tamano debe ser menor a 64KB. III. PROGRAMACION EN ENSAMBLADOR PROGRAMACION BASICA Para comenzar con la programacion en lenguaje ensamblador, es necesario contar con un conjunto de herramientas de programacion. Este conjunto de herramientas consta de un editor de texto capaz de producir archivos en codigo ASCII, un ensamblador y un enlazador. Para propositos de este trabajo, se utilizaran los siguientes programas: El ensamblador PASS32.