| INSTITUTO POLITÉCNICO NACIONAL ESCUELA SUPERIOR DE CÓMPUTO |

Introducción | Contenido | Bibliografía

Introducción
Contenido
UNIDAD I
UNIDAD II
UNIDAD III
UNIDAD IV
UNIDAD V
UNIDAD VI
UNIDAD VII
UNIDAD VIII
UNIDAD IX Introdución 9.1 Máquina Virtual 9.2 Máquina Objeto 9.3 Administración de la memoria durante la ejecución

9.4 Código de 3 y 4 direcciones

9.5 Estructuras de control de flujo y de repetición (if then else, case, while, for)

PROBLEMARIO
Bibliografía

9.4 Código de 3 y 4 direcciones

> Con el objetivo de facilitar la comprensión de la fase de generación de código, es mejor no centrarse en el código máquina puro de ningún microprocesador concreto, sino en un código intermedio cercano a cualquiera de ellos. Esta aproximación facilitará, además, la optimización del código generado.

> Cada una de las instrucciones que se pueden generar posee un máximo de cuatro apartados:

> - Operando 1º (dirección de memoria donde se encuentra el primer operando).

> - Operando 2º (dirección de memoria donde se encuentra el segundo operando).

> - Operador (código de operación).

> - Resultado (dirección de memoria donde albergar el resultado, o a la que saltar en caso de que se trate de una operación de salto).

> Se asume que se permite tanto el direccionamiento directo como el inmediato, esto es, la dirección de un operando puede sustituirse por el operando en sí.

> A este tipo de instrucciones se las denomina códigos de 3 direcciones, tercetos, o códigos de máximo 3 operándoos.
> En esencia, los tercetos son muy parecidos a cualquier código ensamblador, existiendo operaciones para sumar, restar, etc. También existen instrucciones para controlar el flujo de ejecución, y pueden aparecer etiquetas simbólicas en medio del código con objeto de identificar el destino de los saltos.

> No todas las instrucciones tienen porqué poseer exactamente todos los apartados mencionados. A modo introductorio, los tercetos que se pueden usar son:

> - Asignación binaria: x := y op z, donde op es una operación binaria aritmética o lógica. Aunque debe haber operaciones diferentes en función del tipo de datos con el que se trabaje (no es lo mismo sumar enteros que sumar reales), para facilitar nuestro estudio asumiremos que tan sólo disponemos del tipo entero.

> - Asignación unaria: x := op y, donde op es una operación unaria. Las operaciones unarias principales incluyen el menos unario, la negación lógica, los operadores de desplazamiento de bits y los operadores de conversión de tipos.

> - Asignación simple o copia: x := y, donde el valor de y se asigna a x.

> - Salto incondicional: goto etiqueta.

> - Saltos condicionales: if x oprelacional y goto etiqueta.

> Como puede deducirse de los tercetos propuestos, las direcciones de memoria serán gestionadas de forma simbólica, esto es, a través de nombres en lugar de números. Por supuesto, para generar tercetos más cercanos a un código máquina general, cada uno de estos nombres debe ser traducido a una dirección de memoria única. Las direcciones de memoria se tomarían de forma consecutiva teniendo en cuenta el tamaño del tipo de datos que se supone alberga cada una de ellas; por ejemplo, se puede asumir que un valor entero ocupa 16 bits, uno real ocupa 32 bits, un carácter ocupa 8 bits, etc.

> Con los tercetos anteriores cubriremos todos los ejemplos propuestos en el presente capítulo. No obstante, estos tercetos no recogen todas las posibilidades de ejecución básicas contempladas por un microprocesador actual. Por ejemplo, para llamar a una subrutina se tienen tercetos para meter los parámetros en la pila de llamadas, para invocar a la subrutina indicando el número de parámetros que se le pasa, para tomar un parámetro de la pila, y para retornar:

> - param x: mete al parámetro real x en la pila.

> - call p, n: llama a la subrutina que comienza en la etiqueta p, y le dice que tome n parámetros de la cima de la pila.

> - pop x: toma un parámetro de la pila y lo almacena en la dirección x.

> - return y: retorna el valor y.

> Otros tercetos permiten gestionar el direccionamiento indirecto y el indexado:

> - Direccionamiento indexado: los tercetos son de la forma y := x[i] y x[i] := y, donde x es la dirección base, e i es el desplazamiento.

> - Direccionamiento indirecto: los tercetos son de la forma y:=&x y x:=*y, donde el símbolo & quiere decir “la dirección de ...” y el símbolo * quiere decir “el valor de la dirección contenida en la dirección ...”.

> La elección de operadores permisibles es un aspecto importante en el diseño de código intermedio. El conjunto de operadores debe ser lo bastante rico como para permitir implementar todas las operaciones del lenguaje fuente. Un conjunto de operadores pequeño es más fácil de implantar en una nueva máquina objeto, pero si es demasiado limitado puede obligar a la etapa inicial a generar largas secuencias de instrucciones para algunas operaciones del lenguaje fuente. En tal caso, el optimizador y el generador de código tendrán que trabajar más si se desea producir un buen código.

> A continuación se muestra un ejemplo de código de tercetos que almacena en la variable c la suma de a y b (nótese que b se destruye como consecuencia de este cálculo):

> c = a
> label etqBucle
> if b = 0 goto etqFin
> b = b-1
> c = c+1
> goto etqBucle
> label etqFin

> Atrás Siguiente

##### Introducción / Contenido / Unidad I / Unidad II / Unidad III / Unidad IV / Unidad V / Unidad VI / Unidad VII / Unidad VIII / Unidad IX / Problemario / Bibliografía

##### Inicio

##### Créditos

José Sánchez Juárez, Andrés Ortigoza Campos, Fabiola Ocampo Botello