UNIVERSIDAD NACIONAL DE INGENIERIA RECINTO UNIVERSITARIO SIMON BOLIVAR Facultad de Electrotecnia y Computación Departamento de Arquitectura y Sistemas Folleto Complementario de Arquitectura de Máquinas Computadoras II Programación en Lenguaje Ensamblador Elaborado por: Ing. José Díaz Chow Managua, Octubre de 2013 INDICE DE CONTENIDO 4. PROGRAMACION EN ENSAMBLADOR ..................................................................................... 1 4.1 4.2 4.2.1 4.3 4.4 4.4.1 4.4.2 4.4.3 4.5 4.5.1 4.5.2 4.5.3 EL LENGUAJE ENSAMBLADOR. .................................................................................................... 1 ALGORITMIZACIÓN Y PSEUDOCÓDIGO. ........................................................................................ 1 Implementación de las estructuras de control de flujo ........................................................... 2 ENSAMBLADORES Y HERRAMIENTAS DE PROGRAMACIÓN. .......................................................... 3 LA ARQUITECTURA DE LA FAMILIA IX86 ..................................................................................... 4 Introducción............................................................................................................................ 4 Organización .......................................................................................................................... 4 Modelo de Memoria................................................................................................................ 5 EL LENGUAJE ENSAMBLADOR DE LA FAMILIA IX86 ..................................................................... 7 Formato de una sentencia en ensamblador. ........................................................................... 7 Palabras Reservadas .............................................................................................................. 8 Expresiones Constantes u Operandos inmediatos: ................................................................. 9 4.5.3.1 4.5.4 4.5.5 4.5.5.1 4.5.5.2 4.5.6 4.5.7 Constantes Enteras Simbólicas................................................................................................... 10 Operadores ............................................................................................................................10 Tipos de datos ........................................................................................................................11 Variables de Memoria ................................................................................................................ 11 Tipos de datos compuestos......................................................................................................... 11 Modos de direccionamiento ...................................................................................................12 El Conjunto de Instrucciones.................................................................................................13 4.5.7.1 4.5.7.2 4.5.7.3 4.5.7.4 4.5.7.5 Instrucciones de Copiado de datos ............................................................................................. 13 Adición y sustracción de enteros ................................................................................................ 16 Instrucciones de Multiplicación y División:............................................................................... 17 Instrucciones de Operaciones a nivel de BITS: .......................................................................... 19 Instrucciones de Lógica y control de programa.......................................................................... 21 4.6 LA COMPUTADORA PERSONAL BASADA EN CPUS IX86. .............................................................25 4.6.1 El video de la PC ...................................................................................................................25 4.6.1.1 4.6.1.2 4.6.2 La pantalla.................................................................................................................................. 25 Procesamiento básico de pantalla ............................................................................................... 25 La entrada estándar de la PC ................................................................................................27 4.6.2.1 Procesamiento básico de teclado ................................................................................................ 27 ANEXO A: LISTA DE PALABRAS RESERVADAS. .........................................................................................30 ANEXO B: EL CONJUNTO DE INSTRUCCIONES. ...........................................................................................32 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I 1. PROGRAMACION EN ENSAMBLADOR 1.1 El Lenguaje Ensamblador. Hoy día, estamos acostumbrados a programar en lenguajes de alto nivel, como C, Pascal, Java, C# o Visual Basic, que son similares al lenguaje natural humano, pero muy diferentes al lenguaje nativo del procesador. En los lenguajes de alto nivel, empleamos el paradigma de programación estructurada, donde tenemos estructuras de control de programa similares a las estructuras lógicas del pensamiento humano, que facilitan la programación (condicionales como el if-then-else e iterativas como el while, for y repeat), el procesador, en cambio solo nos permite una ejecución secuencial de instrucciones, e instrucciones de salto cuando sea requerido modificar la dirección del flujo de programa. El único vocabulario que el procesador puede entender es su conjunto de instrucciones. Para comunicarse efectivamente con él, un programador debe escribir su código fuente empleando sentencias formadas por instrucciones de este conjunto, con sus operandos. Sabemos que el CPU sólo es capaz de interpretar estas instrucciones cuando están expresadas en binario, que es lo que llamamos lenguaje de máquina. Sin embargo, para un ser humano, esto implicaría conocer cada código de operación y formato de cada instrucción además de codificar cada operando correctamente, lo cual sería bastante dificultoso además de tedioso y tardado. Para facilitar un poco el proceso de la programación a bajo nivel, se implementó el lenguaje ensamblador, que provee nombres mnemotécnicos para cada operación, que es más fácil de recordar para el programador. Así, luego, un programa denominado “ensamblador”, puede convertir estos mnemónicos y operandos en formato binario según el formato de cada instrucción. Para programar en lenguaje ensamblador es necesario realizar un cambio de pensamiento en nuestra forma de programar, implementando las estructuras de control de programa en base a las instrucciones de control de flujo que nos provee el procesador. 1.2 Algoritmización y Pseudocódigo. Para desarrollar un programa de computadora que resuelva un problema del mundo real, es conveniente primero representar ese problema en un modelo computacional que permita validar nuestra idea de solución, y luego, a partir del modelo, codificamos nuestro programa con mayor confianza que funcionará bien para los propósitos definidos. Se denomina algoritmo a tal modelo de solución de un problema. Podemos definirlo como la serie de pasos secuenciales, no ambiguos y finitos requeridos para resolver un problema. Elaborado por: José Díaz Chow Página 1 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Existen diversas formas de describir un algoritmo. Por ejemplo, mediante un diagrama de flujo, esquemas de bloque Nassi-Scheiderman o pseudocódigo. Como hemos anotado, el lenguaje ensamblador carece de las estructuras de control de flujo y, en este momento, es extraño para nosotros. Por tanto, es de gran importancia especificar un modelo computacional de la solución del problema, que nos guíe eficazmente, antes de comenzar a implementarla. Por la misma falta de estructura del ensamblador, la forma más idónea para representar tal algoritmo es mediante pseudocódigo. 1.2.1 Implementación de las estructuras de control de flujo El conjunto de instrucciones de la arquitectura x86 brinda instrucciones de salto o bifurcación que permiten implementar las estructuras de control de flujo que ofrece un lenguaje de alto nivel, pero de una forma más trabajosa. Estas instrucciones permiten implementar saltos incondicionales, saltos condicionales, llamadas a subrutinas y llamadas a interrupciones o servicios del sistema. Por ejemplo, para implementar un If-Then-Else, se verifica la condición, normalmente con la instrucción de comparación CMP y luego se salta a la parte then o a la parte else en función de los resultados. If: Cmp a, b Je Then Jmp Else Then: ; Cuerpo del Then Jmp End_If Else: ; Cuerpo del Else End_If: Un ciclo se implementa de forma similar. Considermos el caso de un while – End While. Primero se verifica la condición. Si no se cumple, saltar al fin del ciclo. Un repeat es muy similar con la salvedad que la condición se verifica al final del cuerpo del repeat. Un for requiere además un contador, aunque la familia ix86 provee la instrucción LOOP que lo implementa explícitamente. While: Cmp a, b Jne End_While ; Cuerpo del While Jmp While End_While: Página 2 Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I 1.3 Ensambladores y Herramientas de Programación. Como hemos mencionado anteriormente, un ensamblador es un programa que traduce los mnemónicos del lenguaje ensamblador a lenguaje de máquina (código objeto) que el procesador puede ejecutar directamente. No obstante, no basta ensamblar un programa para que éste sea ejecutable por parte del sistema operativo. Un segundo programa denominado enlazador (linker) convierte el código objeto en un programa ejecutable que puede ser de tipo ejecutable estándar: exe o de tipo comando: com (programa pequeño de menos de 640k de tamaño). Para la programación de nuestros ejemplos usaremos primordialmente Microsoft Macro Assembler (MASM). También experimentaremos un poco con las herramientas de Borland: Tasm y Tlink. Para los estudiosos, se dispone de una serie de ensambladores gratuitos para la arquitectura de 32 bits. Finalmente, sus programas pueden llamar librerías de terceros a fin de no reinventar la rueda. Estas librerías son anexadas a su ejecutable en tiempo de enlace. Para ensamblar y enlazar un programa con las herramientas de Microsoft, basta usar el programa ML que ensambla y enlaza de un solo paso (este en realidad invoca a ambos módulos). Para hacerlo con las herramientas de Borland, ensamblamos con Tasm y enlazamos con tlink. Por ejemplo, para poder ejecutar el programa Hola.asm del laboratorio 3, con herramientas de Microsoft basta: Prompt> ml Hola.asm Prompt> Hola Para hacerlo con las herramientas de Borland: Prompt> Tasm –z Hola.asm Prompt> TLink Hola Prompt> Hola Elaborado por: José Díaz Chow Página 3 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . 1.4 La Arquitectura de la Familia ix86 Podemos decir que la familia de arquitecturas de Intel x86, tiene dos generaciones bien diferenciadas: la arquitectura de 16 bits que es la generadora de la familia y la arquitectura de 32 bits, más moderna y versátil. En este curso, nos enfocaremos en los principios y características básicas de la arquitectura de 16 bits. 1.4.1 Introducción La familia 80x86 nace con el lanzamiento del microprocesador 8086 y su primo 8088. Ambos idénticos en su arquitectura de 16 bits pero diferentes en su interfaz de bus. (el 8088 tenía una ruta de 8 bits para guardar compatibilidad con su predecesor 8080). Sorprendentemente, esta familia de procesadores que dan soporte a la IBM PC y compatibles desde su introducción en 1981 hasta hoy día, guardan compatibilidad en arquitectura hacia atrás. La tabla a continuación muestra la evolución de estos CPUs en cuanto a tamaño de registros, Memoria que es capaz de direccionar y velocidad de cómputo. Procesador Tamaño Registros [bits] 8088 80188 8086 80186 80286 80386 80486 Pentium, PRO, mmx Pentium II Pentium III Pentium IV 1.4.2 16 16 16 16 16 32 32 32 32 32 32 Ancho bus [bits] Memoria que direcciona 8 8 16 16 16 32 32 64 64 64 64 1 MB 1 MB 1 MB 1 MB 16 MB 4 GB 4 GB 4 GB 4 GB 4 GB 4 GB Velocidad [MHz] 4.71 6 4.71 6 4.7, 8, 12 25, 33 33, 66, 100 75 … 233 266 … 450 450 … 1,300 1,300 … 3,600 Organización Intel organiza el Datapath de estos microprocesadores en dos unidades lógicas: La unidad de ejecución (EU) y la Unidad de Interfaz de Bus (BIU). La EU contiene a la ALU, los registros de propósito general y punteros así como el de banderas. Algunos autores defienden que también contiene a la unidad de control. La BIU contiene los registros de control de programa (PC) y direccionamiento segmentado, la lógica de acceso al bus y una cola de instrucciones (de 2 a 8 instrucciones según CPU). Página 4 Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I Figura 1. Organización básica del 8086 1.4.3 Modelo de Memoria La memoria principal a que acceden estos procesadores se compone en parte de RAM de lectura/escritura y ROM que contiene el software del sistema (Programa de configuración del sistema y la BIOS). El esquema básico de direccionamiento del 8086 original es de 1MB define. La figura 2 muestra el mapa de memoria definido para la PC, computadora basada en este procesador, que integra 640KB de memoria principal para ejecución de programas de usuario, denominada Memoria Convencional. El resto del 1MB, es denominada memoria alta o superior, aloja la ROM con un espacio de 64 KB básicos para setup (configuración de parámetros) y 192 KB para extensión y el BIOS. Elaborado por: José Díaz Chow Página 5 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Figura 2. Mapa de la memoria 8086. Un aspecto importante a considerar del sistema de memoria que manejan los 80x86 es el ordenamiento de bytes. Intel emplea para estos little endian, es decir que el byte menos significativo se almacena en la posición más baja, al inverso de cómo se ordenan a lo interno de los registros. (Big endian es al contrario: más significativo en posición más baja). La arquitectura de 16 bits de la famila x86 implementa un modelo de memoria denominado segmentado, donde cada programa de usuario, reside en segmentos de memoria. Cada programa puede tener uno o más segmentos para datos, uno o más segmentos para código, otro para la pila y un extra segmento. En el modelo de programación segmentado, el cálculo de direcciones es desplazado, para lo cual emplea registros de base de segmento, lo cual permite que sean re-localizables en memoria. Se definen cuatro tipos de segmentos básicos: Data (Datos), Code (Código), Stack (Pila) y Extra (Extra para extender código o datos). Los registros base para éstos son: DS, CS, SS y ES respectivamente (Ver figura 1). Los segmentos deben tener un tamaño múltiplo de 16 bytes. En modo real (monotarea) puede ser de hasta 64KB. Las direcciones físicas de memoria de 1MB (20 bits) se obtienen mediante un modo de direccionamiento desplazado, donde el registro base del segmento se desplaza 4 posiciones a la derecha (se multiplica por 10H) y luego se suma al valor del desplazamiento para obtener la dirección física de 20 bits. Por ejemplo, suponga que el DS tiene 045FH y el desplazamiento para el dato X es 32H, entonces, DS se desplaza 4 posiciones volviéndose su contenido 045F0H a lo que se suma el 32H para obtener 04622H. Es importante recordar que el modelo de programación del 8086 es segmentado y que el modo [dirección] que podríamos considerar como “absoluto” (porque definimos Página 6 Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I directamente la dirección de memoria a la que queremos acceder) se refiere a una dirección que implícitamente está desplazada. Por ejemplo, basándonos en el caso del párrafo anterior, la instrucción MOVE AX, [0032] carga en el registro AX el valor de M(DS:32). La arquitectura x86 de 16 bits de Intel evolucionó a una arquitectura de 32 bits cuando apareció el procesador Intel 80386 en el año 1985, denominada inicialmente i386 o x8632 y finalmente IA-32. En la arquitectura de 32 bits, los registros se extienden a 32 bits (Por ejemplo EAX, cuyos 16 bits menos significativos corresponden a AX, y así todos los registros de propósito general). Asimismo, la arquitectura de 32 bits, dado que permite acceder a 4GB de direcciones lineales de memoria, emplea un modelo de memoria denominada FLAT, en el cual el direccionamiento ya no es segmentado. Posteriormente (de 1999 a 2003) AMD amplió la arquitectura de 32 bits de Intel a una de 64 bits y la llamó, inicialmente x86-64, y finalmente AMD64. Intel adoptó estas extensiones bajo el nombre de IA-32e, EM64T o Intel x64. La arquitectura de 64 bits puede trabajar en dos modos: el compatible y el nativo o puro. Un procesador en modo compatible puede ejecutar instrucciones en ensamblador x86 mediante traducción, pero si está en modo nativo no. 1.5 El Lenguaje Ensamblador de la Familia ix86 Un programa en lenguaje ensamblador está compuesto por una secuencia de sentencias. Estas sentencias representan tanto instrucciones del procesador como directivas o comandos al ensamblador. 1.5.1 Formato de una sentencia en ensamblador. Una sentencia en ensamblador se estructura de la siguiente forma: [[nombre:]] [[operacion]] [[operandos]] [[;comentario]] Donde nombre: es un identificador de etiqueta de código, que es una referencia simbólica a la dirección de la instrucción y a la instrucción misma. El componente opcional operacion representa una instrucción del procesador o una directiva o comando del ensamblador. Los operandos representan los operandos de las instrucciones o parámetros de las directivas y finalmente, un comentario es una facilidad para documentar la sentencia e inicia con un punto y coma (;) y termina al final de la línea. Identificadores Elaborado por: José Díaz Chow Página 7 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Un identificador es un nombre que se asigna a una definición a fin de poder referirse a ella de forma única. Usamos identificadores para nombrar constantes, variables, procedimientos, segmentos, tipos de datos definidos por el usuario y etiquetas de código (que representan la dirección de una instrucción). Los identificadores pueden tener una longitud máxima de 247 caracteres. Algunas restricciones a observar en la definición de nombres son: Los identificadores pueden usar caracteres alfanuméricos (A–Z), dígitos (0–9) o los caracteres especiales: @ _ $ ? Un identificador no puede comenzar con un dígito. Se recomienda evitar usar @ también para iniciar los identificadores porque MASM ha definido este carácter como inicio de símbolos predeterminados que son palabras reservadas. El lenguaje ensamblador es normalmente case insensitive, es decir, que no hace diferencias entre mayúsculas y minúsculas. Por ejemplo, en ensamblador, los identificadores MES y Mes son nombres idénticos y se refieren, por tanto al mismo objeto. 1.5.2 Palabras Reservadas Son aquellas palabras que tienen un significado especial en el lenguaje ensamblador o en el programa ensamblador y que por tanto no deben emplearse como nombres o identificadores en los programas. La mayoría de ensambladores generan error si se usa una palabra reservada como identificador. Comúnmente se tienen como palabras reservadas las siguientes: Instrucciones: nombres de las operaciones que puede ejecutar el CPU. Directivas: Comandos para el ensamblador. Atributos: Valores específicos empleados en directivas. Operadores: Empleados en expresiones. Símbolos Predefinidos: Que definen cierta información dentro del programa. En el MASM, la OPTION NOKEYWORD PalabraReservada permite deshabilitar el estado de palabra reservada a PalabraReservada. Por ejemplo, para eliminar el estatus de palabra reservada de la instrucción STR, el operador MASK y la directive NAME, podemos usar la sentencia siguiente: OPTION NOKEYWORD:<STR MASK NAME> El Anexo A provee una lista completa de todas las palabras reservadas del MASM. Página 8 Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I Operación Las operaciones representan instrucciones del procesador como add (suma), mov (copia valores) o int (interrupción). También pueden representar directivas del ensamblador como SEGMENT, DB o EQU. Posteriormente estudiaremos las instrucciones y las directivas del ensamblador en detalle. Operandos Los operandos en ensamblador pueden estar expresados en diferentes modos de direccionamiento. Un modo de direccionamiento indica cómo obtener el valor del operando. Estos operandos pueden estar expresados en diferentes tipos de datos. En términos generales, éstos son números enteros. A continuación mostramos diferentes tipos de direccionamiento de los operandos: 1.5.3 Expresiones Constantes u Operandos inmediatos: Una constante entera se compone de una secuencia de números que pueden estar tener además un sufijo que indica la base en que está expresado el número. Por ejemplo, en las sentencias siguientes: mov mov ax, 25 bx, 0B3h Los números 25 and 0B3h son constantes enteras. La h al final de 0B3 es un sufijo de base que indica que está expresado en hexadecimal. Los números en hexadecimal se prefijan además con 0 si el primer dígito es no numérico (0-9). Los sufijos de base o Radix son: y o b para binary (Nótese que si la base por defecto es Hex, no puede usarse b) o o q para octal t o d para decimal (Nótese que si la base por defecto es Hex, no puede usarse d) h para hexadecimal Nuevamente, los sufijos pueden estar en mayúsculas o minúsculas. Si no se especifica la base del número, el ensamblador asume que está expresado en la base predeterminada, que por defecto es decimal. Se puede cambiar la base por defecto con la directiva .RADIX. Las expresiones enteras pueden contener además de constantes enteras, operadores de desplazamiento, aritméticos y lógicos. El ensamblador evalúa y reemplaza el valor en tiempo de ensamble. Elaborado por: José Díaz Chow Página 9 A R Q U I T E C T U R A 1.5.3.1 D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Constantes Enteras Simbólicas Se pueden definir constantes simbólicas enteras mediante la directiva EQU o el signo de igual (=). Estas directivas asignan el valor durante tiempo de ensamble realizando sustitución en el código generado. Se pueden usar para facilitar la legibilidad y el mantenimiento de los programas al evitar tener números mágicos en código. Por ejemplo, para tener identificadores simbólicos para ciertos códigos de exploración del teclado: SCAN_A SCAN_B SCAN_ESC EQU EQU EQU 30 48 1 Las directivas EQU e = tienen diferentes propósitos. EQU define una constante cuyo valor no se puede modificar posteriormente en el programa, en tanto, el valor definido con el = sí. La sintaxis de EQU es: ConstanteSimbolica EQU expression Donde ConstanteSimbolica es un nombre único de su elección (excepto palabras reservadas) y expresion puede ser una constante entera, una expresión entera, una cadena de caracteres o una expresión que evalúa a una dirección de memoria. El ejemplo siguiente ilustra el uso de EQU: column row screen EQU EQU EQU 80 25 column * row line EQU row 1.5.4 ; ; ; ; ; Constante. Define 80 caracteres por columna Constante. Define 25 líneas por pantalla Constante. Define tamaño en caracteres de la Pantalla. Evalúa en 2000 Constante. Line equivale a 25 Operadores Los operadores son usados en expresiones constantes. El valor de la expresión se determina en tiempo de ensamble y no cambia en tiempo de ejecución. Es importante notar la diferencia entre las operaciones del procesador y los operadores. Por ejemplo, la palabra reservada ADD es una instrucción y el signo + es el operador de suma. Las reglas que rigen lo operación de expresiones son: Las operaciones en paréntesis se ejecutan antes que las adyacentes. Las operaciones Binarias de mayor precedencia se ejecutan primero. Operaciones de igual precedencia se ejecutan de izquierda a derecha. Las operaciones Unarias de igual precedencia se ejecutan de derecha a izquierda. Página 10 Prof. José Díaz Chow A R Q U I T E C T U R A 1.5.5 D E M Á Q U I N A S C O M P U T A D O R A S I I Tipos de datos Un tipo de datos describe un conjunto de valores, principalmente Enteros. Una variable de un tipo dado puede tener cualquier valor dentro del rango especificado para ese tipo. Un dato entero de un byte, suele usarse también como un carácter, mediante el código ASCII. Hoy día algunos ensambladores soportan otros códigos de dos bytes por carácter. El ensamblador de la familia x86 define algunos tipos de datos intrínsecos que algunos ensambladores han extendido. En función de si se usa o no signo, una misma cantidad de bits puede fungir como dos tipos de datos diferentes. Por defecto estos tipos son: BYTE (8 bits), WORD (16 bits), DWORD (32 bits), QWORD (64 bits) y TBYTE (80 bits). 1.5.5.1 Variables de Memoria La directiva Dx define una variable un tipo de datos definido x, donde x es la inicial de los tipos, según fueron listados arriba. Por ejemplo DB define una variable tipo byte: Mem8 Mem16 Mem32 DB DW DD 01H 0123H 01234567H Una forma equivalente es: Mem8 Mem16 Mem32 1.5.5.2 BYTE WORD DWORD 01H 0123H 01234567H Tipos de datos compuestos Se puede tratar secuencias de unidades de datos del mismo tipo como arreglos. Por ejemplo, se pueden tratar secuencias de bytes como cadenas. Los tipos de datos pueden tener atributos como el tipo de lenguaje compatible langtype y la distancia distance (NEAR o FAR). Un dato FAR, está almacenado en un segmento de datos diferente. El programador puede crear tipos compuestos de datos de diferentes tipos en ensambladores avanzados como MASM, mediante directivas como STRUCT, UNION y RECORD (contiene bits) y definir sus propios tipos con la directiva TYPEDEF que asigna a un tipo cualificado un nombre. Por ejemplo: Elaborado por: José Díaz Chow Página 11 A R Q U I T E C T U R A CHAR D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . TYPEDEF BYTE El tipo cualificado es cualquier tipo o un puntero a tipo, de la forma: [[distancia]] PTR [[tipo]] Donde distancia es NEAR, FAR y tipo es cualquier tipo definido previamente. Ejemplo: CHAR TYPEDEF BYTE PCHAR TYPEDEF PTR CHAR 1.5.6 Modos de direccionamiento En ensamblador de la familia 80x86, tenemos los modos básicos de direccionamiento inmediato, directo de registro y directo de memoria. En este último modo es necesario especificar que dado el modelo segmentado del 8086, las variables deben ser relocalizables en cualquier segmento de memoria en que se carguen, por tanto, el directo de memoria con que trata el programador normalmente es en realidad una modo desplazado relativo al segmento de datos activo en el momento. Por ejemplo, mem8 .data db 25 .code . . . move al, mem8 En este caso, mem8 representa una variable de memoria relocalizable. Suponga que mem8 inicia a partir del byte 18 del segmento de datos, entonces mem8 equivaldría a escribir [18] y su dirección absoluta sería en realidad CS:18, es decir: CS << 4 + 18. Usted puede especificar una dirección efectivamente absoluta, si es preciso, especificando el registro de segmento a considerar de la forma Registro de Segmento: Desplazamiento, como se muestra: Move ax, ES:bx Existe también una serie de modos complejos muy poderosos. Tenemos el modo indirecto de registro: Move ax, [bx], muy utilizado. En este caso nótese que los Página 12 Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I corchetes en ensamblador ix86 se denominan especificadores de índice y representan una referencia a memoria o indirección. Tenemos también una serie de modos desplazados: base-desplazamiento, indizados, baseíndice y los base-índice con escalación. Normalmente los registros BP, BX se llaman registros base y SI y DI registros de índice. Un modo base, parte de un registro base + un desplazamiento inmediato. Un modo indizado, parte de una dirección base + un registro de índice opcional + un desplazamiento inmediato opcional. El modo base-índice parte de una dirección base + un registro de índice + un desplazamiento inmediato opcional y el modo con escalación, que está disponible solo en arquitectura de 32 bits, permite una dirección generada a partir de un registro base o general + un registro de índice que puede estar escalado, es decir multiplicado por un factor (0, 1, 2, 4 u 8) + un desplazamiento opcional. Ejemplos: 1.5.7 base: Indice: b-i: escalado: [bx+4], BX[4] TABLA [2], [TABLA+2], TABLA[DI] Tabla[bx][di] [BX+DI*4+2] El Conjunto de Instrucciones Podemos agrupar las instrucciones que conforman el repertorio de la familia ix86 ya sea en función de la operación que realizan o del CPU con que se introdujo. A fin de no ser extensivos con este acápite, nos enfocaremos en el estudio de las instrucciones más utilizadas. En el anexo B, añadiremos la lista completa de las instrucciones del 8086. 1.5.7.1 Instrucciones de Copiado de datos Las principales instrucciones para copiado de datos son MOV (Move o mueve), XCHG (Exchange o intercambio), CWD (Convert Word to Double, convierte una palabra en doble), y CBW (Convert Byte to Word, convierte un byte en palabra). La instrucción MOV, copia el segundo operando (fuente) al primero (destino). Es importante notar que solo uno de los operandos puede residir en memoria. Veamos unos ejemplos: ; Copia de valores inmediatos mov ax, 7 ; Valor Inmediato a Registro mov mem, 7 ; Valor Inmediato a memoria mov mem[bx], 7 ; Valor Inmediato a memoria de forma indirecta ; Copia de Valores en Registros mov mem, ax ; De mov mem[bx], ax ; De mov ax, bx ; De mov ds, ax ; De Elaborado por: José Díaz Chow Registro Registro Registro Registro a a a a memoria memoria de forma indirecta Registro Registro de Segmento Página 13 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . ; Copia de Valores en memoria mov ax, mem ; De memoria a Registro mov ds, mem ; De memoria a Registro de Segmento ; Copia de Valores en memoria de forma indirecta mov ax, mem[bx] ; De memoria indirecta a Registro mov ds, mem[bx] ; De memoria indirecta a Registro de Segmento ; Copia de Valores en Registros de Segmento mov mem, ds ; De Registro de Segmento a memoria mov mem[bx], ds ; De Registro de Segmento a memoria indirecta mov ax, ds ; De Registro de Segmento a Registro general Existen algunas operaciones de copiado que no pueden hacerse en una sola operación y requieren dos instrucciones, por ejemplo: ; Copia un Operando Inmediato a Registro de Segmento mov ax, DGROUP ; Carga AX con el valor inmediato mov ds, ax ; Copia AX al Registro de Segmento ; Copia de memoria a memoria mov ax, mem1 ; Carga AX con un valor desde memoria mov mem2, ax ; Copia AX a otra localidad de memoria ; Copiar valor de un Registro de segmento a otro mov ax, ds ; Carga AX con un Registro de Segmento mov es, ax ; Copia AX a otro Registro de Segmento Los movimientos de un inmediato de menor tamaño a un registro de mayor tamaño son automáticamente extendidos. Los movimientos entre registros deben ser del mismo tamaño. Como los registros pueden expresarse en diferentes tamaños, y mover valores a registros desde fuente de tamaños más pequeños puede dejar inconsistente un registro de mayor tamaño (por ejemplo, un movimiento a AL puede dejar inconsistente el valor de AX), es importante hacer extensión de signo de enteros para convertir datos a un tamaño mayor. En este cometido, son muy útiles las instrucciones de conversión: Instruccion Extensión de Signo en registro: CBW (convierte byte a word) AL to AX CWD (convierte word a doubleword) AX to DX:AX CWDE (convierte word a doubleword extended)* AX to EAX CDQ (convierte doubleword a quadword)* EAX to EDX:EAX *Usa registros de 32 bits. Es importante notar que en arquitectura de 16 bits, una palabra doble se almacena en un par de registros de 16 bits (DX:AX) en tanto que en la arquitectura de 32 bits o “extendida” la palabra doble extendida se almacena en un registro de 32 bits (EAX) lo cual justifica la existencia de dos instrucciones CWD y CWDE. Veamos unos ejemplos: .DATA mem8 mem16 mem32 Página 14 SWORD SBYTE SDWORD -5 +5 -5 Prof. José Díaz Chow A R Q U I T E C T U R A .CODE . . . mov cbw mov cwd mov cwde mov cdq al, D E M Á Q U I N A S C O M P U T A D O R A S I I mem8 ; Carga -5 en precision de 8 bits(FBh) ; Convierte a -5 en 16 bits (FFFBh) en AX ax, mem16 ; Carga +5 en precision de 16 bits ; Convierte a +5 en 32 bits (0000:0005h) en DX:AX ax, mem16 ; Carga +5 en precision de 16 bits ; Convierte a +5 en 32 bits (00000005h) en EAX eax, mem32 ; Carga -5 en precision de 8 bits (FFFFFFFBh) ; Convert to 64-bit -5 ; (FFFFFFFF:FFFFFFFBh) in EDX:EAX Dado que la aritmética del procesador es por defecto con signo, el programador debe garantizar una correcta extensión de cero cuando trabaja sin signo con tamaños parciales de los registros, lo cual no se puede lograr con las instrucciones de conversión, por ejemplo : mem8 .DATA BYTE .CODE . . . mov sub 251 al, ah, ah mem8 ; Carga 251 (FBh) en 8 bits sin signo ; Pone en 0 la parte alta del registro (AH) ; AX = 251 (00FBh ). Con cbw sería -5 (FFFBh) desde memoria Las instrucciones MOVSX y MOVZX, disponibles solo en los CPUs de 32 bits, permiten hacer copia con extensión de signo y extensión de cero respectivamente, de forma directa. El equivalente de nuestro ejemplo anterior sería: ; movzx Ejemplo ax, mem8 de extension sin ; Carga en ax O0FBh (16 bits) desde FBH(8 bits)en mem signo La instrucción XCHG intercambia los valores de sus operandos. Se puede intercambiar valores entre registros, memoria y registros, pero no de memoria a memoria. xchg xchg ax, bx memory, ax ; ; Pone el contenido de AX en BX y el de BX en AX ; Intercambia el contenido de AX con el de la celda memory xchg mem1, mem2 ; Ilegal! Además de datos, es importante poder mover direcciones a los registros que nos permitan utilizarlos como punteros a memoria. Para tales efectos tenemos la instrucción LEA y el operador OFFSET que nos permiten copiar la dirección relativa al DS de una variable de memoria: Elaborado por: José Díaz Chow Página 15 A R Q U I T E C T U R A mem .DATA BYTE .CODE D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . 20 DUP(?) lea bx, mem ; Carga en bx la dirección del arreglo mem mov ah, [bx] ; copia en ah el primer byte en mem Una operación equivalente a LEA del ejemplo, con el operador OFFSET es: mov 1.5.7.2 bx, offset mem ; Carga en bx la dirección (offset) de mem Adición y sustracción de enteros Las instrucciones ADD, ADC, INC, SUB, SBB, y DEC permiten sumar, incrementar, restar y decrementar valores enteros respectivamente. Estas instrucciones tienen dos restricciones: 1. Si hay dos operandos, solo uno puede residir en memoria. 2. Si hay dos operandos, ambos deben ser del mismo tamaño. Para lograr el Segundo requisito, es factible usar el operador PTR para forzar a un operando al tamaño requerido. Por ejemplo, si Buffer es un arreglo de bytes y BX apunta a un elemento del mismo, puedes sumar una palabra desde Buffer con: add ax, WORD PTR Buffer[bx] ; Suma una palabra desde un arreglo de bytes. El siguiente ejemplo muestra diferentes sumas y restas en 8 y 16 bits: .DATA mem8 BYTE 39 .CODE ; Addition mov ; ; ; ; ; ; al, mem8 ; ; ah, al ; add al, ah mov inc add add Página 16 al, 26 al al, 76 Start with register Increment Add immediate Add memory Copy to AH ; Add register ; ; signed unsigned 26 26 1 1 76 + 76 ------103 103 39 + 39 -------114 142 +overflow 142 ---28+carry Prof. José Díaz Chow A R Q U I T E C T U R A ; Subtraction mov dec sub sub mov sub 1.5.7.3 ; ; ; ; ; ; al, mem8 ; ; ; al, 95 al al, 23 ah, 119 al, ah D E M Á Q U I N A S Load register Decrement Subtract immediate Subtract memory ; Load register ; and subtract ; ; signed 95 -1 -23 ---71 -122 ----51 C O M P U T A D O R A S I I unsigned 95 -1 -23 ---71 -122 ---205+sign 119 -51 ---86+overflow Instrucciones de Multiplicación y División: Para la multiplicación y división de enteros tenemos MUL, IMUL, DIV e IDIV. MUL e DIV realizan multiplicación y división sin signo en tanto que IMUL e IDIV la hacen con signo. La instrucción MUL multiplica sin signo: Mul usa por defecto un operando predefinido e implícito: el acumulador: AH, AX y EAX. ; acumulador acumulador * OP MUL OP La multiplicación de dos operandos de 8 bits da por resultado un producto de16 bits en AX, Multiplicación de dos operandos de 16 bits resulta en un producto de 32 bits en DX:AX. Dos operandos de 32 bits dan un producto de 64 bits en EDX:EAX. .DATA SWORD -30000 .CODE . . . ; 8-bit unsigned multiply mov al, 23 mov bl, 24 mul bl mem16 ; 16-bit signed multiply mov ax, 50 imul mem16 Elaborado por: José Díaz Chow ; ; ; ; ; Load AL 23 Load BL * 24 Multiply BL ----Product in AX 552 overflow and carry set ; Load AX 50 ; -30000 ; Multiply memory ----; Product in DX:AX -1500000 ; overflow and carry set Página 17 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . La instrucción IMUL multiplica con signo. Varias formas: IMUL Reg16, Inmediato IMUL Reg16, { Memoria16| Reg16}, Inmediato IMUL R, {Reg | Memoria} (CPUs de 32 bits) En general: IMUL d, f, [f2] d d * f | d f * f2 imul imul dx, 456 ax, [bx],6 ; Multiply DX times 456 on 80186-80486 ; Multiply the value pointed to by BX ; by 6 and put the result in AX imul imul dx, ax ax, [bx] ; Multiply DX times AX on 80386 ; Multiply AX by the value pointed to ; by BX on 80386 La instrucción DIV divide sin signo e IDIV con signo. Tiene un dividendo implícito (AH, DX:AX o EDX:EAX). El divisor puede ser un operando de memoria o Registro, excepto aquellos deparados para Cociente y Residuo. Puede ser necesario hacer extensión de signo o de zero a fin de lograr o ajustar el dividendo a la cantidad explícita de bits. Tamaño del dividendo Cociente Residuo 16 bits AX 8 bits AL AH 32 bits DX:AX 16 bits AX DX 64 bits EDX:EAX 32 bits EAX EDX .DATA SWORD SDWORD .CODE . . . ; Divide 16-bit mov mov div mem16 mem32 Tamaño del divisor Dividendo -2000 500000 unsigned by 8-bit ax, 700 bl, 36 bl ; ; ; ; ; Load dividend 700 Load divisor DIV 36 Divide BL -----Quotient in AL 19 Remainder in AH 16 ; Divide 32-bit signed by 16-bit Página 18 Prof. José Díaz Chow A R Q U I T E C T U R A mov mov idiv M Á Q U I N A S ax, WORD PTR mem32[0] ; dx, WORD PTR mem32[2] ; mem16 ; ; ; ; ; Divide 16-bit mov cwd mov idiv 1.5.7.4 D E signed by 16-bit ax, WORD PTR mem16 bx,-421 bx ; ; ; ; ; ; C O M P U T A D O R A S I I Load into DX:AX 500000 DIV -2000 Divide memory -----Quotient in AX -250 Remainder in DX Load into AX -2000 Extend to DX:AX DIV -421 Divide by BX ----Quotient in AX 4 Remainder in DX 0 -316 Instrucciones de Operaciones a nivel de BITS: Operaciones lógicas: AND, OR, XOR hacen operaciones lógicas bit a bit en dos operandos. Dejando el resultado en el primero. NOT complementa (niega) el operando. Note que además de la operación en sí misma, existe gran utilidad en estas operaciones para el testeo y establecimiento de valores de bits en posiciones específicas. Un OR con 1 establece en 1 el bit correspondiente y un AND con 0 limpia en 0 el valor del bit correspondiente. mov and ax, 035h ax, 0FBh or ax, 016h xor ax, 0ADh not ax ; ; ; ; ; ; ; ; ; ; ; Load value Clear bit 2 Value is now 31h Set bits 4,2,1 Value is now 37h Toggle bits 7,5,3,2,0 Value is now 9Ah Value is now 65h 00110101 AND 11111011 -------00110001 OR 00010110 -------00110111 XOR 10101101 -------10011010 01100101 ;AND example - converts characters to uppercase mov ah, 7 ; Get character without echo int 21h and al, 11011111y ; Convert to uppercase by clearing bit 5 cmp al, 'Y' ; Is it Y? je yes ; If so, do Yes actions . ; Else do No actions . yes: . ;OR example - compares operand to 0 or bx, bx ; Compare to 0 jg positive ; BX is positive jl negative ; BX is negative ; else BX is zero ;XOR example - sets a register to 0 xor cx, cx ; 2 bytes, 3 clocks on 8088 sub cx, cx ; 2 bytes, 3 clocks on 8088 mov cx, 0 ; 3 bytes, 4 clocks on 8088 Elaborado por: José Díaz Chow Página 19 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Operaciones de desplazamiento de bits. Las operaciones SHL y SHR hacen desplazamiento lógico a izquierda y derecha respectivamente. SAL y SAR hacen desplazamiento aritmético a izquierda y deredcha. ROL y ROR hacen rotaciones a izquierda y derecha. Cabe mencionar que estas instrucciones se expresan con la forma: OP d, f . Estas realizan los desplazamientos correspondientes en d en la cantidad de f bits. El bit desplazado se copia a C como referencia, en cada caso excepto en las rotaciones. Existen dos instrucciones más, RCL y RCR, que hacen las rotaciones a izquierda y derecha involucrando (pasando a través) de C. El 8086 solo admitía f=1 inmediato o el registro CL. Actualmente se puede usar cualquier I de 8 bits. SHL y SAL multiplican d por 2f. SHR y SAR dividen d entre 2f. SAR es una división con Signo. La división con SAR redondea negativos hacia abajo (al contrario de IDIV!). shr bx, 4 -- Con 8086 : mov cl, 4 shr bx, cl ; 9 clocks, 3 bytes on 80286 ; 2 clocks, 3 bytes on 80286 ; 9 clocks, 2 bytes on 80286 ; 11 clocks, 5 bytes total --- Otro ejemplo: masker .DATA BYTE .CODE . . . mov mov rol or rol or 00000010y ; Mask that may change at run time cl, 2 bl, 57h masker, cl bl, masker ; ; ; ; ; ; ; ; masker, cl bl, masker Rotate two at a time Load value to be changed Rotate two to left Turn on masked values New value is 05Fh Rotate two more Turn on masked values New value is 07Fh 01010111y 00001000y --------01011111y 00100000y --------01111111y ---Multiplicaciones mul_10 Página 20 MACRO mov shl mov shl shl add ENDM factor ax, factor ax, 1 bx, ax ax, 1 ax, 1 ax, bx ; ; ; ; ; ; ; ; Factor must be unsigned Load into AX AX = factor * 2 Save copy in BX AX = factor * 4 AX = factor * 8 AX = (factor * 8) + (factor * 2) AX = factor * 10 Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I -- Divisiones div_512 MACRO mov shr xchg dividend ax, dividend ax, 1 al, ah cbw ENDM 1.5.7.5 ; ; ; ; ; ; ; Dividend must be unsigned Load into AX AX = dividend / 2 (unsigned) XCHG is like rotate right 8 AL = (dividend / 2) / 256 Clear upper byte AX = (dividend / 512) Instrucciones de Lógica y control de programa. La instrucción JMP es un salto incondicional. La forma básica de usar JMP es con etiquetas de código. JMP d ; IP IP + d ( con d short y near ) A20: ... Jmp A20 La instrucción LOOP es un salto con contador. Loop implementa un for – Next. La cantidad de ciclos o iteraciones del loop se define en CX. En cada ciclo, loop decrementa CX automáticamente y detiene el ciclo cuando CX =0. Mov cx, 10 A20: ... Loop A20 La instrucción CMP compara dos valores. Es la base para saltos condicionales. CMP realiza una comparación mediante una resta que no afecta al operando destino. CMP establece las banderas C, O, S, Z, P, AC cmp jz bx, 0 B50 ; Compara Bx=0 ; Si Bx = 0 salta a la dirección de etiqueta B50: Las instrucciones de salto condicional. Existen una serie de instrucciones en ensamblador que permiten cambiar el flujo actual del programa en función del resultado de una expresión lógica o más explícitamente del estado de configuración de ciertas banderas. Normalmente, estas banderas son las que establece la instrucción CMP. Elaborado por: José Díaz Chow Página 21 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Las instrucciones de salto condicional guardan la forma JX donde J significa “salta si” y X representa la comparación realizada o banderas consultadas. Por ejemplo JE salta si el resultado de una comparación previa con CMP es que ambos operandos son iguales (E de Equal), así mismo, JZ, salta si la bandera Z (cero) está establecida. Ambas instrucciones son idénticas pues hacen el mismo trabajo, sin embargo, es posible que alguna de ellas sea más legible en algún contexto de programación. Es importante notar las diferencias en la comparaciones entre aritmética con signo y sin signo. Por ejemplo, en precisión de 8 bits el número FBH representa -5 en aritmética con signo y 251 en aritmética sin signo. Es obvio que son dos cantidades muy diferentes en cada contexto, por eso la arquitectura de la familia ix86 define instrucciones de salto condicional para cada tipo de aritmética. En aritmética con signo, decimos que dos operandos son iguales o que uno es mayor o menor que el otro (E de equal, G de greater than y L de less than), En cambio, en aritmética sin signo, decimos que son iguales, o que uno está por encima o por debajo del otro, respectivamente (E de equal, A de above y B de below). Instrucciones de llamadas a procedimientos Hasta el momento hemos experimentado con programas en ensamblador con un solo procedimiento (programa principal), sin embargo, al igual que en los programas en lenguaje de alto nivel, el ensamblador soporta la definición e invocación de procedimientos. Un procedimiento se declara en el segmento de código mediante la estructura: nombreProc PROC distancia … nombreProc ENDP El operador Distancia, indica si el procedimiento es cercano (NEAR) porque está definido en el mismo segmento de código o es lejano (FAR) cuando está definido en otro segmento de código. La instrucción CALL permite invocar a un procedimiento desde un programa en ensamblador. Todo procedimiento debe tener una instrucción RET al final, que retorna el control al programa que lo invocó. El paso de parámetros y de resultados se realiza mediante la pila. Es importante, por tanto tener en cuenta que CALL mete el IP en la pila (2 bytes) al momento de recuperar los parámetros. El IP que guarda CALL, lo restaura RET, por tanto, el programador de procedimientos, debe tener cuidado de dejar el SP en el mismo punto donde lo encontró. Ejemplo: Página 22 Prof. José Díaz Chow A R Q U I T E C T U R A Title Begin Begin Proc1 Proc1 Proc2 Proc2 D E M Á Q U I N A S C O M P U T A D O R A S I I Llamadas .model small .stack 64 .data .code Proc Far Call Proc1 ; … mov ax, 4c00h int 21h EndP Proc Call ; … Ret EndP Near Proc2 Proc ; … Ret EndP Near End Begin ; Fin del porgrama La instrucción INT: Interrumpe el programa que se ejecuta actualmente para realizar una llamada a una función del sistema operativo o de las rutinas de la ROM BIOS. Los servicios de la ROM BIOS Uno de los recursos más valiosos que asiste al programador de ensamblador de la PC son los servicios de la ROM BIOS. Estos servicios se refieren a una serie de rutinas de entrada salida (Basic Input Output Services) que se encuentran almacenadas en la memoria ROM del sistema. Estas rutinas permiten acceder y programar el hardware básico de la PC. Todos los servicios de la BIOS se invocan mediante interrupciones. Estos servicios pueden agruparse en cinco temas de acuerdo al objetivo. Cada tema contiene una serie de servicios organizados en torno a la estructura hardware o función que soportan, empleando una interrupción diferente para cada grupo de servicios, según muestra la tabla: Interrupción Hex Dec 10H 13H 14H 15H 16H 17H 16 19 20 21 22 23 Elaborado por: José Díaz Chow Uso Servicios de dispositivos periféricos Servicios de video Servicios de disco Servicios de comunicaciones seriales Servicios del sistema Servicios del teclado Servicios de impresión Página 23 A R Q U I T E C T U R A 11H 12H 17 18 1AH 26 5H 5 18H 19H 24 25 D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Servicios de estado del equipo Listado de equipamiento del sistema Tamaño de memoria Servicios de fecha y tiempo Servicios de hora y fecha Servicio de impresión de pantalla Impresión de la pantalla Servicios especiales Activar la ROM Basic Activar rutina de arranque Llamadas al sistema operativo DOS: INT 21H Aunque el DOS reserva para su uso muchas interrupciones (desde la 20H hasta la 3FH), normalmente los servicios del sistema los proporciona a través de solo cinco de ellas: 20H, 21H, 25H, 26H y 27H. Interrupción Hex Dec 20H 32 21H 33 25H 37 26H 38 27H 39 Descripción Terminación de programa Servicios generales del DOS Lectura absoluta de disco Escritura absoluta en disco Terminar y quedar residente Para efectos de este curso nos centraremos en los servicios generales o interrupción 21H. La interrupción 21h, provee una serie de funciones. Para invocar a un servicio del DOS mediante la interrupción 21H, se establece el número de función en AH y el parámetro en AL. Por ejemplo: Mov Mov Int ah, 4CH ; Función regresar al DOS al, 0 ; Valor de retorno = 0, normal. 21H ; Llama al DOS. Equivale a: Mov Int Página 24 ax, 4C00H 21H ; Función regresar al DOS normalmente. ; Llama al DOS. Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I 1.6 La Computadora Personal basada en CPUs ix86. 1.6.1 El video de la PC El video en la PC se obtiene gracias a un adaptador gráfico que genera las señales de video y un monitor que las presenta en una pantalla. Existen básicamente dos modos generales de video en la PC: el Modo carácter o texto y el modo gráfico. En el contexto de este curso, solamente consideraremos el modo texto, a las funciones más básicas y simples de video. 1.6.1.1 La pantalla La pantalla de la PC en modo texto representa una matriz de caracteres organizados en filas y columnas. El modo de video de texto más conocido es el de 25 filas por 80 columnas. El primer carácter en la esquina superior izquierda de la pantalla tiene la posición fila 0, columna 0 (0,0). El carácter en la esquina inferior izquierda tiene la posición (24,0). El de la esquina superior derecha (0,79) y el de la inferior derecha es la (24, 79). La pantalla del monitor puede presentar los datos que se escriben en un buffer de video que es un área de memoria a la que tiene acceso el programador. Esta área de memoria de video está organizada en páginas, de la cual solo una se muestra a la vez. Esto que permite escribir varias pantallas de video directamente en memoria y luego intercambiar entre ellas para hacer cambios rápidos de contenido en la pantalla. Cada carácter pintado en la pantalla se representa por dos bytes en la memoria. Uno almacena los atributos de visualización y el otro el código ASCII del carácter. Los atributos pueden ser: Color de frente, color de fondo, intensidad y parpadeo. 1.6.1.2 Procesamiento básico de pantalla En este curso abordaremos brevemente las funciones más básicas de procesamiento en pantalla proporcionadas por algunas funciones de la interrupción 10H de la BIOS: Limpiar la pantalla, posicionar el cursor, pintar un carácter con y sin atributo. Finalmente estudiaremos como escribir una cadena completa mediante el servico 09H de la interrupción de servicios del sistema del DOS, int 21H. En términos generales, la Int 10H espera que la función a ejecutar se escriba en el registro AH y en AL los parámetros básicos. Si la cantidad de parámetros crece, emplea los otros Elaborado por: José Díaz Chow Página 25 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . registros generales para completarlos. Por ejemplo, BH y BL sirven regularmente para definir ya sea atributo en modo texto o el número de la página de video a afectar. CX y DX para coordenadas de la ventana (CH, CL: Fila, Columna de la esquina superior izquierda; DH, DL: Fila, Columna de la esquina inferior derecha). Borrar la pantalla La función 6H de la int 10H permite definir una ventana rectangular y deslizar su contenido. Esto puede emplearse para borrar la pantalla. El siguiente código limpia la pantalla completa: Mov Mov Mov Mov Mov Int ah, al, bh, cx, dx, 10H 06h 00h 07h 0000h 184fh ;Selecciona función ; Limpiar toda la ventana seleccionada ; Blanco sobre negro. ; Esquina Sup. Izq: (0,0) ; Esquina Inf. Der: (24,79) Posicionar el cursor La función 02h de la Int 10H del BIOS permite posicionar el cursor en la pantalla. Según lo acostumbrado de escribe en AH la función (Ah2h). En BH se escribe el número de página (por defecto 0), y en DH, DL, la Fila, Columna de la posición a establecer para el cursor. Mov Mov Mov Mov Int ah, bh, dh, dl, 10H 02h 00h 05 12 ; Selecciona función ; Página por defecto. ; Posiciona el cursor en ; la posición (5,12) Escribir un carácter en la posición actual del cursor La función 09h de la Int 10H del BIOS permite escribir (y repetir) un carácter con un atributo determinado en la posicionar actual del cursor en la pantalla. La función 0Ah hace lo mismo pero sin considerar atributo (el carácter se escribe con el atributo actual). Como siempre, en AH se escribe la función (Ah09h | 0Ah). En Al se pone el carácter a escribir. En BL se escribe el atributo de video y en CX, la cantidad de veces a escribir el carácter en pantalla. Mov Mov Mov Mov Int Página 26 ah, al, bl, cx, 10H 09h ‘A’ 14h 01 ; ; ; ; Selecciona función escribe con atributo Escribir una A Atributo de color rojo sobre azul. Solo pintarla 1 vez Prof. José Díaz Chow A R Q U I T E C T U R A Mov Mov Mov Int ah, 0ah al, ‘A’ cx, 01 10H D E M Á Q U I N A S C O M P U T A D O R A S I I ; Selecciona función escribe sin atributo ; Escribir una A ; Solo pintarla 1 vez Despliegue de cadenas en pantalla con función del DOS La función 09h de la Int 21H del DOS permite desplegar una cadena completa. Esta cadena debe estar delimitada por el “guardián” del DOS, el carácter ´$´. Similar a las interrupciones del BIOS, la Int 21H requiere recibir la función en AH. La dirección de la cadena a desplegar se requiere en DX: .data Saludo db “Hola amigos,”, 01H, ‘$’ .code . . . Mov lea Int 1.6.2 ah, 09h dx, Saludo 21H ; Selecciona función de despliegue del DOS ; Dirección de inicio de la cadena La entrada estándar de la PC En la IBM PC y compatibles, se ha definido el teclado como el dispositivo de entrada estándar. El teclado es un dispositivo que presenta un conjunto de teclas en una disposición estándar. Cuando el usuario presiona una tecla, en realidad cierra un circuito al unir el contacto en la intersección de la fila y columna correspondiente a la tecla. Estas señales alimentan un codificador que genera un código de exploración del teclado en función de la posición de la tecla en la matriz. Por ejemplo, la tecla ESC que se encuentra en la esquina superior izquierda del teclado corresponde al código de exploración 1, F1 que le sigue es 2, y así en lo sucesivo. Además de generarse el código de exploración, el controlador del teclado, genera una interrupción de hardware. La BIOS trata esta interrupción llevando al Buffer del teclado el carácter correspondiente a la tecla pulsada pero ya en código ASCII. Por ejemplo, el ESC sería un 27. 1.6.2.1 Procesamiento básico de teclado En el contexto de este curso, exploraremos algunas de las funciones más básicas de teclado, empleando la interrupción 16H de la BIOS y el servicio 0AH del DOS. Elaborado por: José Díaz Chow Página 27 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Leer el siguiente carácter del teclado La función 00H de la Int 16H del BIOS, permiten esperar y leer el próximo carácter desde el teclado. Si no hay un carácter en el buffer, la función se queda esperando indefinidamente por la pulsación de un carácter. El carácter leído queda en AL. Cabe mencionar que si se pulsó un carácter especial, como las teclas de función, se generan dos bytes, el primero es un 0 y el segundo es la definición de la tecla. El siguiente código lee el próximo carácter del teclado: Mov Int ah, 00h 16H ; Selecciona función de lectura al, 27 ; Se tecleó ESC? . . . Cmp Comprobar si existe un carácter en el buffer del teclado Frecuentemente, no queremos esperar a que presionen un carácter sino, que queremos monitorear si se hizo de forma transparente. Esto nos lo permite la función 01h de la Int 16H del BIOS. Si se encontraba un carácter en el buffer, la función establece la bandera Z a 1 y retorna en AL el carácter en el buffer, pero no lo retira de allí. Habría que invocar la función 00h para hacerlo. El siguiente código muestra el uso de la función: leerCar: Mov Int jz Jmp HayCaracter : Mov Int ah, 01h 16H HayCaracter leerCar ; Selecciona función verificar ; Invoca a función ; Página por defecto. ah, 00h 16H ; Selecciona función leer ; lee el carácter en AL Leer una cadena completa desde el teclado El DOS nos provee una importante función o servicio que permite leer toda una cadena desde el teclado, poniendo a disposición nuestra todas las teclas de edición además (BackSpace, Delete, etc). Requiere la definición de un espacio de memoria en el área de datos donde especificar parámetros de la función y guardar la cadena leída. El ejemplo a continuación lee una cadena de un máximo de 20 caracteres desde el teclado. .data ; Definición de la lista de parámetros ParLeer Label Página 28 Byte Prof. José Díaz Chow A R Q U I T E C T U R A MaxLon db LonReal db Cadena db 20 ? 20 D E M Á Q U I N A S C O M P U T A D O R A S I I dup(‘ ‘) .code mov ah, 0ah lea dx, ParLeer int 21h Elaborado por: José Díaz Chow ; Solicita función de lectura ; provee la dirección de la lista de par ; invoca al DOS Página 29 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Anexo A: Lista de Palabras Reservadas. Podemos identificar cuatro categorías de Palabras reservadas en el ensamblador de la familia ix86: Nombres de registros, como AX y AH. Instrucciones simbólicas, como ADD y MOV. Directivas (instrucciones para el ensamblador), como PROC y END. Operadores, como DUP y SEG. No se deben emplear estas palabras para definir datos, pues estas pueden confundir al ensamblador o causar un error al ensamblar. Nombres de registros: AH, AL, AX, EAX BH, BL, BX, EBX CH, CL, CX, ECX DH, DL, DX, EDX DI, EDI BP, EBP SI, ESI CS, DS, SS, ES, FS, GS IP, EIP, SP Instrucciones simbólicas: AAA, AAD, AAM, AAS; ADC, ADD, AND, ARPL, BOUND, BSF, BSR, BTn, CALL, CBW, CDQ, CLC, CLD, CLI, CLTS, CMC, CMP, CMPSn, CWDn, DAA, DAS, DEC, DIV, ENTER, ESC, HLT, IDIV, IMUL, IN, INC, INSw, INT, INTO, IRET, JA, JAE, JB, JBE, JCXZ, JE, JECXZ, JG, JGE, JL, JLE, JMP, JNA, JNAE, JNB, JNBE, JNE, JNG, JNGE, JNL, JNLE, JNO, JNP, JNS, JNZ, JO, JP, JPE, JPO, JS, JZ, LAHF, LAR, LDS, LEA, LEAVE, LES, LFS, LGDT, LGS, LIDT, LLDT, LMSW, LOCK, LODSn, LOOP, LOOPE, LOOPNE, LOOPNZ, LOOPZ, LSL, LSS, LSS, LTR, Página 30 Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I MOV, MOVSn, MOVSX, MOVZX, MUL, NEG, NOP, NOT, OR, OUTn, POP, POPA, POPAD, POPF, POPFD, PUSH, PUSHAD, PUSHF, PUSHFD, RCL, RCR, REN, REP, REPE, REPNE, REPNZ, REPZ, RET, RETF, ROL, ROR, SAHF, SAL, SAR, SBB, SCASn, SETnn, SGDT, SHL, SHLD, SHR, SHRD, SIDT, SLDT, SMSW, STC, STD, STI, STOSn, STR, SUB, TEST, VERR, VERRW, WAIT, XCHG, XLAT, XOR Directivas: ALIGN,.ALPHA, ASSUME, .CODE, COMM, COMMENT, CONST, CREF, DATA, .DATA?, DB, DD, DF, DOSSEG, DQ, DT, DW, ELSE, END, ENDIF, ENDM, ENDP, ENDS, EQU,.ERRnn, EVEN, EXITM, EXTRN, .FARDATA, .FARDATA?, GROUP, IF, IFI, IF2, IFB, IFDEF, IFDIF, IFE, IFIDN, IFNB, IFNDEF, INCLUDE, INCLUDELIB, IRP, IRPC, LABEL, LALL, LFCOND, LIST, LOCAL, MACRO, MODEL, NAME, ORG, OUT, PAGE, PROC, PUBLIC, PURGE, RADIX, RECORD, REPT, SALL, SEGMENT, SEQ, SFCOND, STACK, STRUC, SUBTTL,.TFCOND, TITLE,.XALL, .XCREF,.XLIST Operadores: AND, BYTE, COMMENT, CON, DUP, EQ, FAR, GE, GT, HIGH, LE, LENGTH, LINE, LOW, LT, MASK, MOD, NE, NEAR, NOT, NOTHING, OFFSET, OR, PTR, SEG, SHL, SHORT, SHR, SIZE, STACK, THIS, TYPE, WHILE, WIDTH, WORD, XOR Elaborado por: José Díaz Chow Página 31 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Anexo B: El conjunto de Instrucciones. I.- Conjunto de Instrucciones de la Familia ix86. Listado General: I. Aritméticas ADD: Suma binaria. ADC: Suma con acarreo. INC: Incremento en uno. SUB: Resta binaria. SUBB: Resta con el bit prestado. DEC: Decremento en uno. MUL: Multiplicación. IMUL: Multiplicación con signo. DIV: División entera. IDIV: División entera con signo NEG: Negación aritmética. Lógicas AND: NOT: OR: XOR: Y lógica. Negación lógica. O lógica. O Exclusiva lógica. Corrimiento de bits RCL: Rotación a izquierda con acarreo. RCR: Rotación a derecha con acarreo. ROL: Rotación a izquierda. ROR: Rotación a derecha. SAL: Corrimiento aritmético a izquierda. SAR: Corrimiento aritmético a derecha. SHL: Corrimiento lógico a izquierda. SHR: Corrimiento lógico a derecha. SHLD: Corrimiento lógico a izquierda en doble precisión. SHRD: Corrimiento lógico a derecha en doble precisión. Comparación CMP: Comparación CMPS: Comparación de cadenas de caracteres TEST: Verificación de bits BSF/BSR: Exploración de bits (32bits). Página 32 Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I BT/BTC/BTR/BTS: Prueba o test de bits (32 bits). Conversión de Tipo CBW: Convierte byte a palabra. CDQ: Convierte palabra doble a cuádruiple. CWD: Convierte palabra a palabra doble. CWDE: Convierte palabra a palabra doble extendida. Conversión ASCII-BCD AAA: AAD: AAM: AAS: DAA: DAS: Ajuste ASCII después de sumar. Ajuste ASCII antes de dividir Ajuste ASCII después de multiplicar Ajuste ASCII después de restar. Ajuste decimal después de sumar. Ajuste decimal después de restar. Transferencia de datos MOV: Transfiere o copia datos enteros. MOVS: Transfiere cadenas de caracteres. MOVSX: Mueve con extensión de signo. MOVZX: Mueve con extensión de cero. LEA: Carga dirección efectiva. LDS: Carga el registro de segmento de datos. LES: Carga el registro de segmento extra. LSS: Carga el registro de segmento de pila. LODS: Carga una cadena. STOS: Almacena una cadena. XCHG: Intercambia el contenido de los operandos. XLAT: Traducción. Operaciones con la pila PUSH: Introduce un elemento a la pila. POP: Remueve un elemento de la pila. PUSHA: Introduce los GPR a la pila. POPA: Restaura los GPR desde la pila. Transferencia de Entrada-Salida IN: Lee desde un puerto E/S a un registro. OUT: Escribe a un puerto de E/S. Elaborado por: José Díaz Chow Página 33 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Operaciones con banderas CLC: Limpiar acarreo. CLD: Limpiar dirección. CLI: Limpiar interrupción. STC: Establece la bandera de acarreo. STD: Establece la bandera de acarreo. STI: Establece la bandera de acarreo. CMC: Complementa acarreo. LAHF: Cargar banderas en AH. SAHF: Cargar AH en banderas. PUSHF: Introduce las banderas a la pila. POPF: Restaura banderas desde la pila. Operaciones con cadenas CMPS: Compara cadenas. LODS: Carga cadena. MOVS: Mueve una cadena. REP: Repite una cadena. REPE: Repite la cadena mientras sea igual a. REPZ: Repite la cadena mientras sea cero. REPNE: Repite la cadena mientras sea igual a. REPNZ: Repite la cadena mientras sea cero. SCAS: Explora una cadena. STOS: Almacena una cadena. Operaciones de control de programa CALL: Llamada a procedimiento. RET: Regreso de procedimiento. RETN/RETF: Regreso cercano / lejano. INT: Llamada a Interrupción. IRET: Regreso de la interrupción. INTO: Interrupción de desborde. JMP: Salto incondicional. JA/JNBE: Salta si mayor / No menor o igual. JAE/JNB: Salta si mayor o igual / No es menor. JB/JNAE: Salta si es menor / No es mayor o igual. JBE/JNA: Salta si es menor o igual / No es mayor. JC/JNC: Salta si hay acarreo / No hay acarreo JCXZ: Salta si CX es cero, Página 34 Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I JE/JZ: Salta si es igual / Es cero. JG/JNLE: Salta si es mayor / No es menor o igual. JGE/JNL: Salta si es mayor o igual / No es menor. JL/JNGE: Salta si es menor / No es mayor o igual. JLE/JNG: Salta si es menor o igual / No mayor. JNE/JNZ: Salta si no es igual / No es cero. JNP/JPO: Salta si no hay paridad / Paridad es par. JO/JNO: Salta si hay desbordamiento / No hay desbordamiento. JP/JPE: Salta si hay paridad / Paridad es par. JS/JNS: Salta si el signo es negativo / Es positivo. Ciclos LOOP: Repetir el ciclo. LOOPE: Repetir mientras sea igual a. LOOPZ: Repetir mientras sea cero. LOOPNE: Repetir mientras no sea igual a. LOOPNZ: Repetir mientras no sea cero. Control del procesador ESC: Escape. HLT: Introduce en estado de detención. LOCK: Bloquea el bus. NOP: No operar. WAIT: Pone el procesador en estado de espera. II.- Conjunto de Instrucciones de la Familia ix86. Listado detallado: En la siguiente tabla se muestran encolumnados los Mnemónicos (como MOV), los operandos (como fuente, destino) y la descripción de la operación. Los operandos son combinaciones entre tipos (registro, memoria e inmediato) con los direccionamientos admitidos en cada instrucción. Las instrucciones IN y OUT admiten un cuarto tipo de operando: puertos de I/O, con direccionamiento registro o inmediato. II.1- Instrucciones de movimientos de datos MOV destino,fuente ;la única instrucción que utiliza todos los tipos de direccionamiento XCHG destino,fuente ;Intercambia los contenidos de destino y fuente XLAT tabla_fuente ;carga el registro AL con el byte direccionado por (BX+AL) LAHF ;carga las flags S, Z, A, P y C en AH SAHF ;guarda AH en el registro de flags LDS destino,fuente Elaborado por: José Díaz Chow ;transfiere un puntero de 32 bits al registro DS y al registro destino Página 35 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . LES destino,fuente ;transfiere un puntero de 32 bits al registro ES y al registro destino LEA destino,fuente ;transfiere el offset de fuente (una dirección) a destino (un registro) PUSH fuente ;guarda fuente en el stack (en la dirección SS:SP) POP destino ;recupera del stack (dirección SS:SP-1) y guarda en registro destino PUSHF ;almacena el registro de flags en/desde el stack POPF ;recupera el registro de flags en/desde el stack PUSHA ; almacena los reg DI,SI,BP,SP,BX,DX,CX,AX en/desde el stack POPA ;recupera los reg DI,SI,BP,SP,BX,DX,CX,AX en/desde el stack IN origen ;carga desde un puerto origen un byte o word en AL o AX OUT destino ;escribe Al o AX en el puerto destino (direccionamiento inmediato o DX) II.2- Las operaciones aritméticas ADD destino,fuente ;suma fuente + destino y guarda el resultado en destino ADC destino,fuente ;suma fuente + destino + Carry y guarda el resultado en destino SUB destino,fuente ;resta destino - fuente y guarda el resultado en destino SUB destino,fuente ;resta destino - fuente - Carry y guarda el resultado en destino MUL fuente ;multiplica AL o AX * fuente y guarda el resultado en DX:AX IMUL fuente ;igual que la anterior pero con numeros enteros con signo DIV fuente ;divide DX:AX / fuente y guarda cociente en AX y resto en DX IDIV fuente ;igual que la anterior pero con numeros enteros con signo AND destino,fuente ;opera destino AND fuente y guarda resultado en destino OR destino,fuente ;opera destino OR fuente y guarda el resultado en destino XOR destino,fuente ;opera destino XOR fuente y guarda el resultado en destino NOT destino ;el NOT cambia todos los 1 en 0 y los 0 en 1 de destino. NEG destino ;NEG realiza el complemento a 2 de destino INC destino ;Incremente en 1 el contenido de destino DEC destino ;Decrementa en 1 el contenido de destino DAA / DAS ;Efectúa el ajuste decimal en suma / resta del registro AL AAA/AAD/ AAM/AAS ;ajustan el registro AL a valor decimal desempaquetado (para aplicar en operaciones suma, resta, multiplicación y división) II.3- Instrucciones de rotación RCL destino,contador ;rota destino a través de carry a la izquierda contador veces RCR destino,contador ;rota destino a través de carry a la derecha contador veces ROL destino,contador ;rota destino a la izquierda contador veces Página 36 Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I ROR destino,contador ;rota destino a la derecha contador veces SAL destino,contador ;desplaza destino a la izquierda contador veces y rellena con ceros SAR destino,contador ;desplaza destino a la derecha contador veces y rellena con bit SF SHR destino,contador ;desplaza destino a la derecha contador veces y rellena con ceros NOTAS SOBRE INSTRUCCIONES DE ROTACIÓN El bit SF (signo) es el que está más a la izquierda : si destino es operando es de 8 bits"SF" es el bit número 7 y si destino es un operando de 16 bits, es el bit número 15. En el procesador 8086 se permite un dato inmediato en lugar de especificar un registro como contador solo si ese dato inmediato es 1. Por lo tanto, para uno de esos procesadores la instrucción RCL AX,1 es válida mientras que la RCL AX,5 no lo es. A partir de 80286 se puede especificar cualquier numero de rotaciones como dato inmediato. Como DEBUG presupone 8086, cualquier valor inmediato distinto de 1 da error. Elaborado por: José Díaz Chow Página 37 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . Si en un programa para 8086 se desean rotar más de un bit a la vez, el valor contador se carga en CL Para rotar un nibble (lo que es muy común en la conversión de binario a BCD) es más rápido y ocupa menos memoria si se utilizan 4 rotaciones de contador igual a 1 que si se utiliza el registro CL Las instrucciones SAL y SHL son equivalentes La flag de Overflow cambia con una logica precisa si la rotación es de una posición. En caso de rotaciones mayores, OVF queda indefinida. En los procesadores 80286 en adelante la rotación se hace MODULO 32, es decir que se rotará la cantidad de veces igual al resto de la división contador/32, o sea que ROL AX,33 equivale a ROL AX,1 o ROL AX,65. Una rotación con CL=0 equivale a un NOP de dos bytes II.4.- Instrucciones de comparación CMP destino,fuente ;compara fuente y destino. Modifica las flags V, Z, S, C, P y AC TEST destino,fuente ;AND entre fuente y destino . Ninguno de los operandos cambia. TEST modifica las mismas flags que CMP pero siempre deja a V = 0 y C = 0. II.5.- Instrucciones de strings CMPS string_destino,string_fuente ;compara las dos cadenas de a bytes o words CMPSB string_destino,string_fuente ;origen y destino indicados por DS:SI y ES:DI (bytes) CMPSW string_destino,string_fuente ;origen y destino indicados por DS:SI y ES:DI (words) LODS string_fuente ;mueve un byte o una word desde fuente a AL o AX LODSB string_fuente ;origen indicado por DS:SI (mueve un byte a AL) LODSW string_fuente ;origen indicado por DS:SI (mueve una word a AX) STOS string_destino ;mueve un byte o una word al destino desde AL o AX STOSB string_destino ;destino indicado por ES:DI (mueve AL a un byte) STOSW string_destino ;destino indicado por ES:DI (mueve AX a una word) MOVS string_destino,string_fuente ;mueve un byte o word de fuente a destino MOVSB string_destino,string_fuente ;origen y destino indicados por DS:SI y ES:DI (un byte) MOVSW string_destino,string_fuente ;origen y destino indicados por DS:SI y ES:DI (una word) SCAS string_destino ;compara la cadena de destino con AL o AX SCASB string_destino ;destino indicado por ES:DI (compara AL con un byte) SCASW string_destino ;destino indicado por ES:DI (compara AX con una word) En todos los casos, si se utiliza el prefijo REP, la cantidad de elementos de la cadena a operar está dada por el contenido del registro CX, si no es un solo elemento de la cadena. A cada operación, CX es decrementado y SI y DI son incrementados o decrementados de acuerdo con el estado de la flag de dirección (Si D=0, se incrementan). El incremento o decremento de estos registros se hace de a uno si son operaciones de bytes o de a dos si Página 38 Prof. José Díaz Chow A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I I son de a words. Para los casos en que se especifica el largo del operando con la B o W final, la string_destino está apuntada por ES:DI, la string_fuente está apuntada por DS:SI . II.6- Instrucciones de repetición LOOP offset ;decrementa CX. Si CX no es cero, salta a offset (IP = IP + offset) LOOPZ offset ;decrementa CX, Si CX <> 0 y Z = 1 , salta a offset (IP = IP + offset) LOOPNZ offset ;decrementa CX, Si CX <> 0 y Z = 0 , salta a offset (IP = IP + offset) En todos los casos, si no se produce el salto, se ejecuta la próxima instrucción REP instrucción ;decrementa CX y repite la siguiente instrucción MOVS o STOS hasta que CX=0 REPZ instrucción ;igual que REP, pero para CMPS y SCAS. Repite si la flag Z queda en 1 (igualdad) REPNZ instrucción ;igual queREPZ, pero repite si la flag Z queda en 0 (las cadenas son distintas) II.7.- Instrucciones de salto CALL destino ;llama a procedimiento. IP <-- offset de destino y CS <-- segmento de destino RET valor ;retorna desde un procedimiento (el inverso de CALL), valor es opcional INT número ;llamado a interrupción. CS:IP <-- vector de INT.Las flags se guardan en el stack INTO ;llama a la INT 4 si la flag de overflow (V) está en 1 cuando se ejecuta la instrucción IRET ;retorna de interrupción al programa restaurando flags JMP dirección ;Salta incondicionalmente al lugar indicado por dirección JA offset ;salta a IP + offset si las flags C=0 Y Z=0 (salta si primer operando es mayor) JAE offset ;salta a IP + offset si la flag C=0 (salta si primer operando es mayor o igual) JB offset ;salta a IP + offset si las flags C=1 (salta si primer operando es menor)(igual a JC) JBE offset ;salta a IP + offset si las flags C=1 o Z=1 (salta si primer operando es menor o igual) JZ offset ;salta a IP + offset si las flags Z=1 (salta si primer operando es igual al segundo)(=JE) JG offset ;salta a IP + offset si las flags S=V Y Z=0 (salta si primer operando es mayor) JGE offset ;salta a IP + offset si las flags S=V (salta si primer operando es mayor o igual) JL offset ;salta a IP + offset si las flags S<>V (salta si primer operando es menor) JLE offset ;salta a IP + offset si las flags S<>V o Z=1(salta si primer operando es menor o igual) JNC offset ;salta a IP + offset si la flag C=0 (salta si no hay carry) JNZ offset ;salta a IP + offset si la flag Z=0 (salta si no son iguales o no es cero) JNO offset ;salta a IP + offset si la flag V=0 (salta si no hay overflow) Elaborado por: José Díaz Chow Página 39 A R Q U I T E C T U R A D E M Á Q U I N A S C O M P U T A D O R A S I , C U R S O 2 0 0 4 . JNP offset ;salta a IP + offset si la flag P=0 (salta si no hay paridad -o la paridad es impar =JPO) JNS offset ;salta a IP + offset si la flag S=0 (salta si no hay hay bit de signo) JO offset ;salta a IP + offset si la flag V=1 (salta si hay desbordamiento -overflow) JP offset ;salta a IP + offset si la flag P=1 (salta si la paridad es par ) (=JPE) JS offset ;salta a IP + offset si la flag S=1 (salta si el signo es negativo) JCXZ offset ;salta a IP + offset si la flag CX=0 (salta si el registro CX es cero) Las instrucciones de saltos por Above o Below se refieren entre dos valores sin signo (JA, JAE, JB y JBE), mientras que las Greater y Less se refieren a la relación entre dos valores con signo (JG, JGE, JL y JLE). II.8.- Instrucciones que afectan flags CLC/CMC/STC ;pone a cero / complementa / pone en 1 la flag C (carry) CLD/STD ;pone a cero / uno la flag de dirección (D=0 hace que SI y DI se incrementen) CLI/STI ;deshabilita / habilita las interrupciones por hardware enmascarables II.9.- Instrucciones misceláneas NOP ;no-operación: el procesador pasa a la instrucción siguiente sin hacer nada CBW ;convierte el byte de AL en palabra (AX), copiando el bit 7 a todo el registro AH CWD ;convierte word en double-word, copiando bit 15 de AX a todo el registro DX HLT ;el procesador se detiene hasta que llegue un Reset o una interrupción por hard. Página 40 Prof. José Díaz Chow