ESCUELA DE PREPARACIÓN DE OPOSITORES E. P. O. Cl. La Merced, 8 - Bajo A Telf.: 968 24 85 54 30001 MURCIA INF33 - SAl33 Programación eh lenguaje ensamblador. Instrucciones básicas. Formatos. Direccionamientos. Esquema. r 1 INTRODUCCION 2 2 PROGRAMACIÓN EN LENGUAJE ENSAMBLADOR 2 2.1 PROGRAMAClÓN EN LENGUAJE MÁQUINA 2 2.2 LENGUAJE ENSAMBLADOR 3 2.3 PROGRAMACIÓN VERSUS CODIFICACIÓN 4 2.4 PROGRAMACIÓN EN ENSAMBLADOR 4 3 FORMATO DE LAS INSTRUCCIONES 6 3.1.1 Etiqueta 6 3.1.2 Código de la instrucción 6 3.1.3 Operandos 6 3. 1.4 Comentarios 8 r 4 INSTRUCCIONES BASICAS 8 4.1 INSTRUCCIONES DE TRANSFERENCIA DE DATOS 9 4.2 INSTRUCCIONES QUE MODIFICAN LA SECUENCIA DEL PROGRAMA l O 4. 2.1 Bifurcaciones condicionales 1 O 4.2.2 Bifurcaciones con retorno J 1 4.2.3 Instrucciones de bifurcación más comunes 12 4.3 INSTRUCCIONES ARITMÉTICAS 12 4.4 INSTRUCCIONES DE COMPARACIÓN 12 4.5 INSTRUCCIONES LÓGICAS 13 4.6 INSTRUCCIONES DE DESPLAZAMIENTO 13 4.7 INSTRUCCIONES DE BIT 13 4.8 INSTRUCCIONES DE ENTRADA/SALIDA Y MISCELÁNEAS 13 5 DIRECCIONAMIENTOS 13 5.1 DIRECCIONAMIENTO INMEDIATO 14 5 .2 DIRECCIONAMIENTO DIRECTO ABSOLUTO 15 5.3 DIRECCIONAMIENTO DIRECTO RELATIVO 15 5. 3 .1 Direccionamiento relativo al contador de programa PC 16 5.3.2 Direccionamiento directo relativo a registro base 17 5. 3. 3 Direccionamiento directo relativo a registro índice 18 5.3.4 Direccionamiento apila 18 5.4 DIRECCIONAMIENTO INDIRECTO 19 5.5 DIRECCIONAMIENTO IMPLÍCITO 20 5.6 DIRECCIONAMIENTOS DEL IEEE 694 21 6 CONCLUSIONES 21 Escuela de Preparación de Opositores E.P.O. v02 INF33 -SAI33. Página 2 1 Introducción. Este tema presentamos las ideas básicas sobre la programación en lenguaje ensamblador. Este lenguaje está totalmente ligado a la estructura del computador, aunque nosotros abordaremos el estudio del tema sin hacer referencia directa a una máquina específica. Aunque los lenguajes ensambladores son distintos de un computador a otro, la mayor parte de ellos sigue una filosofía concreta, por lo que es de una gran utilidad seguir una terminología común; esto es lo que pretende el estándar IEEE 694 de ensamblador para microprocesadores. Por tanto, para el desarrollo del tema vamos a seguir dicho estándar. En el desarrollo de este tema, presentaremos el formato de las instrucciones en ensamblador, así como las instrucciones básicas, para concluir nuestro estudio con los diferentes modos de direccionamiento, que indican las formas en las que la CPU capta los operandos o almacena los resultados. 2 Programación en lenguaje ensamblador. 2.1 Programación en lenguaje máquina. La programación en lenguaje máquina consiste en definir, en forma binaria, octal o hexadecimal, los códigos y direcciones de las instrucciones necesarias para resolver el problema propuesto. Veamos con un ejemplo, empleando los códigos del Z-80, cómo se desarrolla este tipo de programación. Supongamos que se quieren sumar tres números de 1 octeto cada uno, almacenados en las posiciones 4F3516, 4F3616 y 4F3716 de la memoria. El resultado deberá dejarse en la posición 4FFC16-Supondremos, además, que los registros de la máquina están libres y se pueden usar sin preservar su contenido. De entre las posibles soluciones, se selecciona la compuesta por los siguientes pasos: • Inicializar el doble registro HL con 4F3516· (HL~ 4F3516) • Cargar el primer dato en el acumulador. (A~ M(HL)) • Incrementar HL. (HL Mayor que 7 .LT. o< Menor que 7 .UGT. Sin signo mayor que 7 .ULT. Sin signo menor que Los paréntesis se pueden incluir en las expresiones para especificar el orden en que se aplican los operadores. Sin embargo, es de destacar que, en muchos ensambladores, la expresión no debe tener blancos, pues se tomarían como delimitadores (este no es el caso del IEEE 694, puesto que utiliza siempre la coma como delimitador entre los operandos). Suele existir un símbolo para designar la dirección de la instrucción en curso, En muchos ensambladores este símbolo es el $, pero el IEEE 694 emplea * para esta función. Por ejemplo, *+ 1 OD indica una dirección 1 O posiciones mayor que la dirección de la instrucción donde se incluye esta expresión. Por su lado, la instrucción BR * supone un bucle infinito de ella misma. Notemos que las expresiones van dirigidas al programa ensamblador. Este programa, tomando el valor numérico de los símbolos de la expresión (si es que hay símbolos ), calcula su valor numérico en binario y la sustituye por éste. 3 .1.4 Comentarios. Finalmente, en el campo de comentarios se pueden (y deben) escribir los comentarios explicativos del proceso que se realiza. No es obligatorio, aunque sí muy recomendado, comentar los programas. En cualquier caso, el programa ensamblador los ignora. Los comentarios se suelen especificar mediante el punto y coma (;), pudiéndose emplear líneas que sólo contengan comentarios. 4 Instrucciones básicas. Las instrucciones del ensamblador se refieren a los códigos mnemónicos de las instrucciones de máquina que tenga un computador. En general, cada fabricante tiene sus propios mnemónicos, adaptados a las instrucciones de máquina de sus computadores. Sin embargo, existe una tendencia a uniformar, por lo que los estándares son cada vez más importantes. El juego de instrucciones de un computador debe cumplir dos condiciones: debe ser completo y debe ser eficaz. Que un juego de instrucciones sea completo significa Escuela de Preparación de Opositores E.P.O. v02 INF33 -SAl33. Página 9 que con él se puede calcular, en un tiempo finito, cualquier tarea computable. Esta condición es, evidentemente, necesaria pero no suficiente, puesto que, además, el juego de instrucciones ha de ser eficaz, esto es, ha de permitir una alta velocidad de cálculo, sin exigir a cambio una excesiva complicación de la unidad de control ni de la unidad aritmética. Una función f(x) se dice que es computable si puede ser calculada en un número finito de pasos por una máquina de Turing. Aunque un computador no tiene una memoria infinita, como la postulada en la máquina de Turing, puede emplearse para evaluar prácticamente cualquier función computable. Desde este punto de vista, el juego de instrucciones puede ser realmente sencillo. La máquina de Turing utiliza solamente las cuatro instrucciones de escribir, mover a la izquierda una posición y leer, mover a la derecha una posición y leer, y parar. Del mismo modo se pueden construir computadores con juegos de instrucciones muy reducidos. Por ejemplo, está demostrado que las dos instrucciones siguientes: decrementar y bifurcar si cero, e incrementar, forman un juego de instrucciones completo, con el que se puede resolver cualquier problema resoluble en otros computadores. Aunque el estudio del juego mínimo completo tiene un interés teórico, no cabe duda que, desde el punto de vista de los computadores comerciales, lo que tiene interés es que sean rápidos y económicos, por lo que habrá que dotarles de un conjunto bien seleccionado de instrucciones. La selección del juego de instrucciones de un computadores, por tanto, uno de los puntos más críticos de su diseño. A continuación, presentaremos las instrucciones consideradas por el estándar IEEE 694. 4.1 Instrucciones de transferencia de datos. Las instrucciones de transferencia de datos permiten repetir, en el operando destino, la información almacenada en el operando origen, quedando este último sin modificar. Destino y origen pueden ser registros o posiciones de memoria. En general, no modifican los biestables de estado del computador. Estas instrucciones suelen transferir una palabra aunque existen algunas que transfieren fracciones de palabras y otras que transfieren bloques completos. Las denominaciones más frecuentes son las que se detallan a continuación: MOVE Transfiere el contenido de un registro a otro, o de una posición de memoria a otra. A veces se denomina TRANSFER. STORE Transfiere el contenido de un registro a la memoria. LOAD Transfiere el contenido de una posición de memoria a un registro. Es Ia operación inversa al STORE. MOVE BLOCK Transfiere un bloque de datos. MOVE MULTIPLE Copia el contenido del origen en múltiples posiciones de memoria. EXCHANGE Intercambia el contenido de los operandos especificados. CLEAR Pone a "ceros" el destino. A veces se denomina RESET. SET Pone a "unos" el destino. PUSH Transfiere el origen a la cabecera de la pila. POP Transfiere Ia cabecera de la pila al destino. Escuela de Preparación de Opositores E.P.O. v02 INF33 -SAI33. Página 1 O 4.2 Instrucciones que modifican la secuencia delprograma. Las instrucciones de modificación de secuencia de programa permiten alterar la secuencia normal de ejecución del mismo. De forma genérica se dice que son instrucciones de salto o bifurcación, puesto que, en vez de pasar a la instrucción que ocupa la posición siguiente, "saltan" a ejecutar las instrucciones que se encuentran en otra posición de memoria. La secuencia normal de ejecución de un programa se basa en el contador de programa PC, que es incrementado para pasar de la dirección de una instrucción a la de la siguiente. En concreto, si la instrucción en curso tiene un tamaño de Z palabras, se debe hacer la operación: PC -E- PC+Z, para pasar a la siguiente instrucción. Si se transfiere o "carga" en el registro PC una nueva dirección X (PC -E- X); la siguiente instrucción que se ejecutará será la que ocupe esta posición X, por lo que se habrá bifurcado a la dirección X. Aunque una instrucción de bifurcación no es más que una transferencia en la que el destino es el contador de programa, su trascendencia y alternativas hace que se deban considerar de forma independiente. Existen distintos tipos de bifurcaciones, que se detallarán a continuación. Con mucha :frecuencia la dirección de bifurcación es un valor absoluto, por lo que debe usarse la notación /DIR, de acuerdo al estándar IEEE 694. 4.2.1 Bifurcaciones condicionales. Las bifurcaciones condicionales son instrucciones que tienen dos secuencias distintas: cuando no se cumple la condición de bifurcación, no hacen nada y PC-E-PC+Z; cuando sí se cumple la condición de bifurcación, modifican el PC, que recibe la dirección de bifurcación. Las condiciones de bifurcación se establecen sobre los biestables de estado, biestables que almacenan ciertas condiciones sobre las operaciones realizadas con anterioridad. Estas condiciones pueden hacerse sobre un sólo biestable o sobre varios simultáneamente. El estándar IEEE 694 considera las siguientes condiciones, que reproducimos en inglés con sus códigos mnemónicos. La instrucción de bifurcación se ejecutará si la condición especificada es cierta: Escuela de Preparación de Opositores E.P.O. v02 INF33 -SAI33. Página 11 ZERO (Z) Cero NOT ZERO (NZ) No cero EQUAL (E) Igual NOT EQUAL (NE) Desigual CARRY (C) Acarreo NOT CARRY (NC) Sin acarreo POSITIVE (P) Positivo NOT POSITIVE (NP) No positivo NEGA TIVE (N) Negativo NOT NEGA TIVE (NN) No negativo OVERFLOW (V) Desbordamiento NO OVERFLOW (NV) Sin desbordamiento GREATER THAN (GT) Mayor que GREATER THAN OR EQUAL (GE) Mayor o igual LESS THAN (LT) Menor que LESS THAN OR EQUAL (LE) Menor o igual HIGHER (H) Superior que (sin signo) NOT HIGHER (NH) No superior (sin signo) LOWER (L) Inferior que (sin signo) NOT LOWER (NL) No inferior (sin signo) TRUE (T) Verdadero FALSE(F) Falso PARITY EVEN (PE) Paridad par PARITY ODD (PO) Paridad impar Aunque no es muy frecuente, puede construirse un computador sin biestables de estado. Evidentemente, en este caso las instrucciones de bifurcación condicional no se pueden hacer sobre condiciones anteriores. La propia instrucción de bifurcación ha de generar la condición, por lo que ha de estar compuesta por una comparación y la bifurcación condicional propiamente dicha. 4.2.2 Bifurcaciones con retomo. Las instrucciones de bifurcación con retomo salvaguardan la dirección de la instrucción que ocupa la posición siguiente (esto es, salvaguardan el valor PC+Z). De esta forma, se puede retomar al punto donde se bifurcó y seguir ejecutando en la dirección siguiente a la que causó el salto. El uso más frecuente de la bifurcación con retomo es para llamar a subrutinas (instrucción que suele llamarse CALL o BRANCH TO SUBROUTINE). Muchas máquinas disponen de bifurcaciones con retornos condicionales, de forma que el salto a la subrutina sólo se hace si se cumple una cierta condición. Uno de los problemas clásicos de las bifurcaciones con retomo es la selección del lugar donde se salvaguarda la dirección de retomo. Esta dirección no es más que uno de los parámetros que se deben enviar a una subrutina: 1. Salvaguarda en un registro especial. La solución es sencilla, pero no permite llamadas anidadas, a menos que este registro sea a su vez salvaguardado, lo que complicaría el tratamiento. 2. Salvaguarda en un registro general. Es una solución similar a la anterior con el inconveniente adicional de ocupar uno de los pocos registros generales del computador. 3. Almacenamiento en la subrutina. Por ejemplo, se puede reservar la primera palabra de la subrutina para almacenar la dirección de retomo. El Escuela de Preparación de Opositores E.P .O. v02 INF33 -SAI33. Página 12 procedimiento permite llamadas anidadas de cualquier nivel, pero no así las recursivas, pues se destruirían las posiciones de retomo anteriores. 4. Almacenamiento en una pila de control. El computador debe mantener una pila de control donde se almacenan las direcciones de retomo. Este método permite llamadas anidadas de cualquier nivel, así corno llamadas recursivas. En efecto, cada nueva llamada va introduciendo en la pila su dirección de retomo, sin destruir las anteriores. Dado que los retornos se hacen en orden inverso a las llamadas, la pila siempre tiene en la cabecera la dirección de retomo adecuada. 4.2.3 Instrucciones de bifurcación más comunes. BRANCH Bifurcación que puede ser condicional o incondicional. También se suele llamar JUMP. A veces se combina con el incremento o decremento automático de un registro, lo que es muy conveniente para formar bucles, puesto que engloba las dos operaciones fundamentales para su construcción. CALL Bifurcación con retomo, que se emplea para llamar a una subrutina. Puede ser condicional o incondicional. También recibe el nombre de JUMP TO SUBROUTINE o de BRANCH AND LINK. RETURN Instrucción complementaria del CALL, restituye la dirección del programa llamante. En algunas máquinas puede ser también condicional. Suele existir un caso especial, el RETURN FROM INTERR'UPT, que sirve para volver de las interrupciones. SKIP Es una bifurcación condicional especial muy compacta que sólo salta una instrucción, por lo que no necesita contener la dirección de bifurcación. Si la condición de la instrucción se cumple, el contador de programa se vuelve a incrementar, con lo que se salta la instrucción siguiente. Se emplea en unión a un BRANCH incondicional para construir bucles. RETURN WITH SKIP Esta instrucción incrementa la dirección de retomo antes de realizar éste. Por los tanto, no retoma a la instrucción siguiente a la llamada, sino a alguna instrucción posterior. 4.3 Instrucciones aritméticas. Las instrucciones que encontramos en el grupo de las aritméticas afectan a los bits de estado. Las denominaciones más corrientes se listan a continuación. ADD Suma. Resta. SUBTRACT Incrementa. INCREMENT Decrementa. DECREMENT Multiplica. MULTIPLY Divide. DIVIDE Cambia de signo. NEGATE Valor absoluto. ABSOLUTE Suma, añadiendo el acarreo del resultado anterior. Es conveniente ADD WITH CARRY para operaciones en precisión múltiple. Resta en orden inverso. SUBTRACT REVERSE SUBTRACT WITH BORROW Resta, teniendo en cuenta el acarreo de resta de la operación anterior. Se usa en precisión múltiple. 4.4 Instrucciones de comparación. La operación de comparación COMPARE consiste en restar o en hacer la operación XOR de cada bit de dos o más operandos. No se almacena el resultado, pero sí se modifican, según proceda, los biestables de estado. Escuela de Preparación de Opositores E.P .O. v02 INF33 -SAI33. Página 13 Suele ir precediendo a una bifurcación condicional, que interrogará el valor de alguno de los biestables de estado que modifique la comparación. La operación TEST . ; es una comparacion con cero. 4.5 Instruccioneslógicas. Las instrucciones lógicas, más corrientes, son AND, OR, NOT, y XOR. Conviene recordar que las operaciones lógicas se realizan en cada uno de los bits de los operandos de forma independiente y que modifican los bits de estado. 4.6 Instrucciones de desplazamiento. Las operaciones de desplazamiento modifican los bits de estado, siendo las denominaciones más corrientes las que se detallan a continuación. SHIFT El SHIFT puede ser a derechas o izquierdas, lógico o aritmético. ROTATE La rotación puede ser a derechas o izquierdas, Además, puede incluirse al bit de acarreo en la rotación. 4.7 Instrucciones de bit. El grupo de las instrucciones de bit incluye las tres instrucciones siguientes: BIT TEST, BIT SET, y BIT CLEAR. 4.8 Instrucciones de entrada/saliday misceláneas. Las instrucciones de entrada/salida son en realidad instrucciones de transferencia, con la peculiaridad de que el destino o el origen es un registro de un periférico. Muchos computadores no tienen este tipo de instrucciones, realizándose estas funciones con las instrucciones de LOAD, STORE y/o MOVE. Las denominaciones más corrientes son las siguientes: INPUT Transfiere la información de un puerto de entrada a un registro o a memoria. A veces se denomina READ. OUTPUT Operación inversa de INPUT. A veces se denominan WRITE. Existen una serie de instrucciones que no se pueden clasificar en ninguna de las categorías anteriores y que llamaremos misceláneas. Entre ellas se pueden destacar las siguientes: WAIT Esta instrucción para la ejecución del programa, hasta que se reciba una interrupción externa. HALT Esta instrucción para el procesador. I CONVERT Tiene por objeto cambiar los formatos de las instrucciones, generalmente, para realizar operaciones de entrada/salida. También se utiliza para hacer extensión de signo. NO OPERATION No realiza ninguna operación. Se puede utilizar para llenar huecos en Ios programas o para temporizar esperas. 5 Direccionamientos. Un modo de direccionamiento es un procedimiento que permite determinar un operando, o la ubicación de un operando o una instrucción. Dado que, generalmente, lo que se especifica es la dirección donde se almacena el dato o la instrucción, la denominación genérica de modo de direccionamiento queda justificada. Llamaremos objeto a la instrucción, operando o resultado que se desea direccionar. El objeto puede residir en la propia instrucción, en un registro o en la Escuela de Preparación de Opositores E.P.O. v02 INF33 -SAl33. Página 14 memoria principal, siendo el objetivo de los modos de direccionamiento especificar el lugar concreto donde se encuentra. Aunque, a primera vista, parecería lo más conveniente que la instrucción incluyese directamente el objeto o su dirección real, ello puede no ser lo más indicado, como apuntan razones tales corno: 1. Ahorro de espacio. Mientras más cortas sean las instrucciones, menos almacenamiento ocupan los programas y menos bits hay que leer de memoria principal para ejecutar un programa. En este sentido, serán convenientes direccionamientos que ocupen poco espacio. 2. Código reubicable y reentrante. El código reubicable (que se puede ejecutar en cualquier zona de memoria) y el código reentrante (que puede ser invocado desde varios puntos simultáneamente), exigen direccionamientos relativos. 3. Estructuras de datos. El manejo de las estructuras de datos, tales como tablas, matrices, colas, listas, ... , se simplifica con el empleo de algunos modos de direccionamiento relativos. En la siguiente tabla vemos una posible clasificación de los modos de direccionamiento. Inmediato De registro Absoluto De memoria De página base Al contador de programa Directo A un registro Postautodecremento Relativo A un registro índice Preautodecremento Postautoincremento Preautodecremento A pila Indirecto Implícito 5.1 Direccionamiento inmediato. El direccionamiento se llama inmediato cuando el objeto, en este caso un I operando, se encuentra contenido en la propia instrucción. Ejemplos: 162A D ~ 2A es una instrucción del Z80 con direccionamiento inmediato, puesto que contiene el valor 2A del operando. 927C47B8 M(X) ~ 7C es una instrucción del IBM 370 con direccionamiento inmediato, pues el operando que se transfiere a la posición de memoria X es 7C, que se encuentra en la propia instrucción (la dirección de memoria X se calcula, con la información 47B8, mediante un direccionamiento relativo con registro base, como se verá más adelante). Hay máquinas que permiten distintos tamaños de operandos inmediatos. Por ejemplo, el VAX permite inmediatos de 6, 8, 16, 32 y 64 bits. Con ello se pretende reducir la memoria necesaria, adaptando la instrucción al tamaño de dato deseado. Escuela de Preparación de Opositores E.P .O. v02 INF33 -SAI33. Página 15 5.2 Direccionamiento directo absoluto. Un direccionamiento se llama directo, en contraposición con el indirecto, cuando expresa la dirección real del objeto. Por otro lado, el direccionamiento absoluto indica que la instrucción contiene una dirección efectiva sin compactar. Por tanto, el direccionamiento directo absoluto indica que la instrucción contiene la dirección real, sin compactar, del objeto. Este tipo de direccionamiento presenta tres alternativas: 1. La información contenida en la instrucción puede ser el identificador de un registro, cuando el objeto deseado se encuentra almacenado en ese tipo de elemento. En algunos textos se considera este caso como otro tipo de direccionamiento que se denomina direccionamiento de registro. 2. La información contenida en la instrucción es una dirección completa de memoria principal. El número de bits necesarios para ello depende del mapa de direcciones del computador. Por ejemplo, el Z80, con un mapa de 64 Koctetos, requiere 16 bits, mientras que el VAX, con un mapa virtual de 4 Goctetos, requiere 32 bits. 3. La información contenida en la instrucción es una dirección limitada, que permite referirse solamente a una parte del mapa de memoria. De esta forma, se reduce el tamaño de la instrucción, pero con la mencionada limitación del mapa de memoria. Este tipo de direccionamiento suele llamarse direccionamiento de página base y es muy frecuente en los microprocesadores. Ejemplos: 3A35F7 A -.. M(F735). Instrucción del Z80 que transfiere al registro A el contenido de la posición F735. D08F B - B - M(8F). Instrucción del MC6800 que resta al acumulador B el contenido de la posición 8F. Siendo 8F una dirección absoluta de página base, que en este microprocesador se reduce a las direcciones O a 255. 5.3 Direccionamiento directo relativo. En el direccionamiento directo relativo la instrucción no contiene la dirección del objeto, sino un desplazamiento D sobre una dirección marcada por un puntero. La dirección se calcula sumando el desplazamiento D al puntero de referencia, que suele estar almacenado en un registro. Este tipo de direccionamiento suele necesitar menos bits que el directo absoluto, puesto que el desplazamiento D puede tener bastantes menos bits que los que exige el mapa de direcciones. Notemos que el registro que sirve de puntero puede ser del tamaño deseado. Por ello, este direccionamiento es más compacto, pero requiere, en contrapartida, realizar la operación de suma del puntero más el desplazamiento. La mayoría de los computadores permiten desplazamientos positivos y negativos. De esta forma, se puede alcanzar una zona de memoria principal alrededor de la posición marcada por el puntero. La siguiente figura representa la zona alcanzada para el caso de un desplazamiento de p bits representado en complemento a 2. En dicha figura se ha supuesto, como es habitual, que el mapa de direcciones tiene m bits y es mayor que el rango del desplazamiento, eso es, que m > p. Escuela de Preparación de Opositores E.P.O. v02 INF33 -SAI33. Página 16 o----- mstruccion Puntero . OP. D B i>-1 8-2 ----- + D + B = Dirección..__ ..,, Zona Direccionable 8 + 2 ·1 - - - - - P·f i. 2m·1....._ __ MEMORIA r . . . Evidentemente, mientras mayor sea la longitud p del desplazamiento D, mayor será el campo direccionable para un puntero determinado, pero más larga será la instrucción. Por ejemplo, el VAX permite desplazamientos de 8, 16 y 32 bits. Aunque pueda parecer que la suma requerida por este direccionamiento debe retardar mucho la ejecución de la instrucción que lo emplea, lo cierto es que no es así. El interés de este tipo de direccionamiento se fundamenta en que es la base del código reentrante y reubicable, puesto que permite cambiar las direcciones de datos y de bifurcaciones sin más que cambiar el contenido de un registro. Además, algunas técnicas de protección de memoria también residen en este direccionamiento. Finalmente, también permite recorrer de forma eficaz las estructuras de datos. Existen distintas posibilidades en cuanto al registro que se emplea como puntero y en cuanto al tratamiento que sufre este último. Veamos seguidamente estas alternativas. 5 .3 .1 Direccionamiento relativo al contador de programa PC. En el direccionamiento relativo a contador de programa, como su nombre indica, el puntero empleado es el contador de programa PC, esto es, el registro que almacena la dirección de la instrucción que se va a ejecutar. Puesto que, normalmente, el contador de programa se incrementa al tiempo que se lee cada instrucción, la posición de referencia es la de la instrucción siguiente, tal y como indica la siguiente figura. Por ejemplo, si la instrucción en curso con direccionamiento relativo a PC, está almacenada en la posición 1725 y contiene un desplazamiento de +52, la posición direccionada es PC + 52, pero PC = 1725 + 1 1726, luego la posición direccionada es 1726 + 52 = 1778. Escuela de Preparación de Opositores E.P .O. v02 INF33-SAI33. Página 17 o.------. Contador de Programa PC + Ob·eto D+PC Dirección 2m-1...____ ...--I MEMORIA Este tipo de direccionamiento está especialmente indicado para alcanzar instrucciones próximas a la que se está ejecutando, por ejemplo, para hacer bifurcaciones que permitan construir bucles. Dado que la mayoría de los bucles son muy cortos, pues contienen unas pocas instrucciones, un desplazamiento de I octeto o menor es perfectamente adecuado, permitiendo un código muy compacto (esto es, unas instrucciones muy cortas). Ejemplo: 38SB PC E- PC+ SB si C=l. Instrucción del Z80 que bifurca, si el biestable C de acarreo está a 1, a la dirección obtenida sumando SB al contador de programa. S.3.2 Direccionamiento directo relativo a registro base. El direccionamiento relativo a registro base emplea como puntero un registro base RB. Generalmente, los computadores disponen de varios registros que pueden actuar como base, ya sean éstos los registros generales o bien registros específicos para ese fin. La instrucción deberá contener la identificación del registro que se emplea como base, así como el desplazamiento. Para obtener la dirección se ha de seleccionar el registro base RB y sumarle el desplazamiento D. La siguiente figura esquematiza esta situación. o..----- Banco de I Registros RB . ' ·.... :; Ob'eto . · D + RB t--_..;.,c....;.._;,-4 Dirección ,,m-1...._ __ ___, MEMORIA Este direccionamiento se diferencia del relativo a índice en que el registro de base no suele modificarse y el de índice sí. El direccionamiento es muy conveniente, por ejemplo, cuando se dispone de una zona de datos. Cargando en el registro base la primera posición de esta zona, se pueden alcanzar los distintos datos sin más que Escuela de Preparación de Opositores E.P.O. v02 INF33 -SAI33. Página 18 conocer su posición relativa dentro de la zona de datos. Un pequeño desplazamiento será suficiente para recoger esta posición relativa. Ejemplos: 927C47B8 M(R4 + 7B8) - 7C. Instrucción del IBM 370. El direccionamiento del destino es relativo, y viene especificado por 47B8. El primer carácter representa el registro base (esto es el registro R4) y el resto representa un desplazamiento de 12 bits de valor 7B8. Por tanto, la dirección del destino es R4 + 788. El origen es un inmediato de valor 7C. FD867 A A - A + M(IX + 7A). Instrucción del Z80 que suma al registro A la posición de memoria que se obtiene de forma relativa, sumando el registro IX y el desplazamiento de 1 octeto 7A. 5.3.3 Direccionamiento directo relativo a registro índice. El direccionamiento relativo al registro índice es una variación del anterior. En este caso, el registro puntero (que llamamos registro índice Rl) es modificado para ir recorriendo Ios elementos de una tabla o vector. En efecto, si cada elemento de la tabla ocupa 1 palabra de la memoria y, cada vez que se emplea, el registro índice se incrementa en 1, se van obteniendo las direcciones de los elementos sucesivos de la tabla. Es muy frecuente permitir tanto el autoincremento como el autodecremento del registro índice. En total existen cuatro alternativas diferentes: • Preautoincremento. El registro Rl es incrementado y seguidamente se obtiene la dirección como suma de Rl+D. • Preautodecremento. El registro Rl es decrementado y seguidamente se obtiene la dirección como suma de Rl+D. • Postautoincremento o autoincremento. Primero se calcula la dirección RI+D y seguidamente se incrementa el registro RI. • Postautodecremento o autodecremento. Primero se calcula la dirección RI+D y seguidamente se decrementa el registro RI. En general, el incremento deberá adaptarse a la longitud de los operandos empleados. El VAX, que permite operandos de 1, 2 ó 4 octetos, tiene direccionamientos con autoincremento o autodecremento que utilizan automáticamente incrementos de 1, 2 ó 4, de acuerdo al operando al que se refiera la operación. Por su lado, el UNIVAC 11 OO divide al registro índice en dos partes Xm y Xi. La parte Xm actúa como el registro. índice clásico, sumándose al desplazamiento, mientras que la parte Xi contiene un I incremento de 18 bits, que puede ser positivo o negativo. Después de calcular la dirección, Xm se modifica, añadiéndole Xi. Ejemplo: 5A4537B8 R4 - R4+M(R3+R5+7B8). Operación de suma en binario del IBM 370. El registro 5 es el registro índice y el 3 es el base. Sin embargo, el IBM 370 no tiene ni autoincremento ni autodecremento. 5.3.4 Direccionamiento a pila. El direccionamiento a pila es un caso particular de direccionamiento relativo, muy empleado en los microprocesadores y minicomputadoras. La máquina deberá disponer de uno o varios registros SP, que realicen la función de puntero de la pila. Cada uno de ellos contiene la dirección de la posición de memoria Escuela de Preparación de Opositores E.P.O. v02 INF33 -SAI33. Página 19 principal que actúa de cabecera de pila. La pila puede crecer según direcciones de memoria crecientes o decrecientes. Para el caso de direcciones crecientes, si el puntero SP contiene la cantidad 3721 y se introduce un nuevo elemento en la pila, SP pasará, a tener la dirección 3722. Si, por el contrario, se elimina un elemento deberá pasar a 3720. Los direccionamientos requeridos son: • Para insertar un nuevo elemento, se realiza un direccionamiento relativo al registro SP con preautoincremento. • Para extraer un elemento, se debe hacer postautodecremento. Si la pila crece según direcciones decrecientes, para insertar un elemento hay que hacer preautodecremento y para extraerlo postautoincremento. El direccionamiento a pila permite instrucciones muy compactas, puesto que, si sólo se dispone de un único registro SP, como es muy corriente, la instrucción no requiere ninguna información de dirección. Ejemplo: Fl A -E- M(SP+l); F -E- M(SP); SP E- SP+2. Operación del Z80 que extrae el primer elemento de la pila y lo transfiere al registro F, extrae el segundo elemento de la pila y lo transfiere al registro A y postautoincrementa SP en 2. 5.4 Direccionamiento indirecto. El direccionamiento indirecto comienza con un direccionamiento directo (ya sea absoluto o relativo), pero se diferencia de aquél en que la dirección obtenida no apunta al objeto deseado sino su dirección. Por tanto, para obtener el objeto deseado se requiere un acceso adicional a memoria principal. La siguiente figura esquematiza un direccionamiento indirecto absoluto. o Instrucción c. OP.I o Dirección Absoluta ..... Dir. ObJeto . ... Oblato m-1 2 MEMORIA Por su lado, la siguiente figura plantea indirecciones de más de un nivel, aunque no parece que ello tenga una gran utilidad, puesto que exige varios accesos a memoria y ocupa varias posiciones, de la misma. Escuela de Preparación de Opositores E.P .O. v02 INF33 -SA133. Página 20 o C. OP.I D I • Dir. Dir. Obi. . Dirección Absoluta - Objeto f+ - .... Dir. Objeto ' «: 1 MEMORIA Una aplicación típica del direccionamiento indirecto consiste en el acceso a diversas informaciones mediante una tabla de punteros. En efecto, mediante un acceso indirecto, a través del elemento correspondiente de esa tabla, se puede acceder a la información deseada. La indirección se puede añadir a todos los tipos de direccionamiento relativos vistos anteriormente. Cabe, además, plantear la indirección en diversos puntos del cálculo de la dirección. Veamos algunas alternativas, para el caso de direccionamiento indirecto relativo a índice y base. M(M(RB+RI+D)) Se calcula la dirección primaria como RB+RI+D y seguidamente se realiza la indirección. M(M(RB+D)+RI) Se calcula la dirección primaria como RB+D. Se accede a memoria (indirección) y al contenido de esta posición se añade el RI, obteniéndose así la dirección definitiva. M(M(RB)+D+RI) Se accede a la posición de memoria indicada por RB (indirección) y al valor obtenido se le suma el desplazamiento D y el registro índice RI, obteniéndose así la dirección definitiva. Se podrían complicar estos ejemplos con autoincrementos o autodecrementos. A pesar de las múltiples alternativas que presenta el direccionamiento indirecto relativo, lo más frecuente es que primero se calcule la dirección relativa y seguidamente se aplique la indirección. Aunque son múltiples las aplicaciones de este direccionamiento, muchas arquitecturas no lo incluyen (por ejemplo el IBM 370). 5.5 Direccionamiento implícito. En el direccionamiento implícito, la instrucción no contiene información sobre la ubicación del objeto, porque éste está en un lugar predeterminado (registro o posición de memoria). la ventaja del direccionamiento implícito es que no ocupa espacio en la instrucción. Por el contrario, su inconveniente es que restringe la aplicación de la mencionada operación. Varias de las instrucciones del Z80 que se han utilizado anteriormente emplean direccionamiento implícito del registro A, esto es, del acumulador. Este registro no viene especificado en la instrucción, pero es uno de los operandos. Escuela de Preparación de Opositores E.P.O. v02 INF33 -SAI33. Página 21 5.6 Direccionamientos del IEEE 694. El estándar IEEE 694 considera los tipos de direccionamientos que se incluyen en la siguiente tabla. Modo Prefijo Ejemplo Absoluto Prefijo I /dir Página base Prefijo ! !dir Indirecto Corchetes [dir] Relativo a PC Prefijo$ $dir Inmediato Prefijo# #valor Relativo a registro base Corchetes desp[.reg] o [.reg,desp J Registro Prefijo . .dir Autopreincremento Prefijo++ ++dir Autopostincremento Sufijo++ dir++ Autopredecremento Prefijo -- --dir Autopostdecrernento Sufijo -- dir-- El direccionamiento relativo a registro base se puede indicar con corchetes y un desplazamiento que puede preceder a dichos corchetes, o que puede incluirse dentro de ellos. Ambas notaciones se refieren al direccionamiento en el que la dirección de un dato se obtiene sumando un desplazamiento y el contenido de un registro base. Observemos que el direccionamiento a registro con un nivel de indirección se puede contemplar como un caso particular de direccionamiento relativo a registro con desplazamiento nulo. Finalmente hay que destacar que los incrementos y decrementos de los cuatro últimos casos de la tabla son de una unidad. En caso de desear un incremento o decremento de valor a hay que añadir ":a" tras el prefijo o sufijo correspondiente. 6 Conclusiones. La programación en lenguaje máquina consiste en definir, en forma binaria, octal o hexadecimal, los códigos y direcciones de las instrucciones necesarias para resolver el problema propuesto. El lenguaje ensamblador surge como una herramienta para simplificar la programación en instrucciones de máquina. Esta simplificación tiene dos aspectos fundamentales: el empleo de códigos mnemónicos, y el empleo de nombres simbólicos. De esta forma, se libera al programador de tener que especificar posiciones de memoria y de recordar los códigos de cada instrucción. La programación consiste en convertir las especificaciones o descripción del problema, redactados en lenguaje natural, en un algoritmo específico para resolver el problema. La codificación, por su parte, consiste en la conversión de estos pasos en sentencias del lenguaje empleado. El proceso de codificación en ensamblador conlleva dos partes principales: la asignación de posiciones específicas a los datos, y la traducción de los pasos del problema en instrucciones elementales del computador. Existen dos clases de sentencias en ensamblador: las sentencias propiamente dichas, que corresponden a instrucciones máquina, y las pseudoinstrucciones, que son órdenes al programa ensamblador que se encarga de traducir el programa a código , . maquina. El formato típico de ensamblador ocupa una línea por sentencia, incluyendo los campos: etiqueta, código, operandos, y comentarios. El campo etiqueta sirve para identificar la instrucción o pseudoinstrucción especificada en esa línea. El código de la instrucción contiene el código mnemónico de la instrucción que se desea. Los Escuela de Preparación de Opositores E.P .O. v02 INF33 -SAI33. Página 22 operandos especifican la dirección fisica o el dato propiamente dicho. Los comentarios son explicativos del proceso que se realiza. Las instrucciones del ensamblador se refieren a los códigos mnemónicos de las instrucciones de máquina que tenga un computador. En general, cada fabricante tiene sus propios mnemónicos. Sin embargo, existe una tendencia a uniformar, por lo que los estándares son cada vez más importantes. El juego de instrucciones de un computador debe cumplir dos condiciones: debe ser completo y debe ser eficaz. En este tema hemos estudiado las instrucciones consideradas por el estándar IEEE 694, clasificadas por: instrucciones de transferencia de datos, instrucciones que modifican la secuencia del programa, instrucciones aritméticas, instrucciones de comparación, instrucciones lógicas, instrucciones de desplazamiento, instrucciones de bit, e instrucciones de entrada/salida y misceláneas. Un modo de direccionamiento es un procedimiento que permite determinar un operando, o la ubicación de un operando o una instrucción. El direccionamiento se llama inmediato cuando el objeto, en este caso un operando, se encuentra contenido en la propia instrucción. Un direccionamiento se llama directo cuando expresa la dirección real del objeto. Por otro lado, el direccionamiento absoluto indica que la instrucción contiene una dirección efectiva sin compactar. Por tanto, el direccionamiento directo absoluto indica que la instrucción contiene la dirección real, sin compactar, del objeto. En el direccionamiento directo relativo la instrucción no contiene la dirección del objeto, sino un desplazamiento sobre una dirección marcada por un puntero. En el direccionamiento relativo a contador de programa el puntero empleado es el contador de programa PC. En el direccionamiento relativo a registro base se emplea corno puntero un registro base RB. En el direccionamiento relativo al registro índice el registro puntero es modificado para ir recorriendo los elementos de una tabla o vector. Por último, en el direccionamiento a pila la máquina deberá disponer de uno o varios registros SP, que realicen la función de puntero de la pila. El direccionamiento indirecto comienza con un direccionamiento directo (ya sea absoluto o relativo), pero se diferencia de aquél en que la dirección obtenida no apunta al objeto deseado sino su dirección. En el direccionamiento implícito, la instrucción no contiene información sobre la ubicación del objeto, porque éste está en un lugar predeterminado (registro o posición de memoria).