CACERES AURELIO Wilfredo
COLONIA ARELLANO Karlos
ESPINOZA CADILLO Christian
GRANADOS HERNANDEZ Eduardo
2019
PEÑA MEZA Miguel
VALLADAREZ RAMIREZ Rhay
Universidad Nacional Santiago
Antúnez de Mayolo
GENERACION DE CODIGO OBJET
TEORIA DE LENGUAJES
Ing. Miguel Ángel Silva Zapata
Compiladores
9-8-2019
Huaraz-Ancash
Medios de Transmisión
Generación de código
objeto
(Compiladores)
Página |1
Medios de Transmisión
DEDICATORIA
El presente trabajo va dedicado
especialmente a nuestros padres
que son nuestra inspiración, y
motivo para seguir adelante en
este andar.
Página |2
Medios de Transmisión
INDICE pag.
II. Generación de Código Objeto…………………………..…. 07
2.1. Concepto……………..…………………………………... 07
2.2. Organización de espacio de almacenamiento…… 08
2.3. Procedimiento…………………………………………08
III. Lenguajes ensamblador……………………………………… 10
3.1. Concepto……………………………………………..…… 10
3.2. Clasificación……………………………………………… 10
3.3. Almacenamiento………………………………………... 10
IV. Lenguajes Maquina……………………………………………. 11
4.1. Concepto……………………………………………..…… 11
4.2. Características…………………………………………… 11
4.3. Direccionamiento………………………………………. 11
V. Registros………………………………………………………….. 12
5.1. Concepto……………………………………………..…… 12
5.2. Distribución……………………………………………… 12
5.3. Tipo de Registros………………………………………. 12
VI. Asignación……………….……………………………………… 14
6.1. Concepto……………………………………………..…… 14
6.2. Aplicación……………………………………………… 15
VII. CONCLUSIONES………………………………………………….. 16
Página |3
Medios de Transmisión
PRÓLOGO
En el transcurso de estos últimos días, se encontró muchas
dificultades a la realización de este trabajo, en cuestión hubo extensas fuentes
de información, y para poder encontrar información relevante a nuestros
objetivos, se tuvo que hacer una búsqueda exhaustiva de entre estas fuentes,
los cuales se logró conseguir y se dará a conocer en la bibliografía.
Página |4
Medios de Transmisión
INTRODUCCION
En el siguiente informe, se presenta uno de los conceptos más
significativos dentro de las fases del compilador y la parte de síntesis.
La fase final de un compilador es la generación de código objeto, que
por lo general consiste en código de máquina relocalizable o código
ensamblador. Las posiciones de memoria se seleccionan para cada una de las
variables usadas por el programa. Después, cada una de las instrucciones
intermedias se traduce a una secuencia de instrucciones de máquina que
ejecuta la misma tarea. Un aspecto decisivo es la asignación de variables a
registros.
Página |5
Medios de Transmisión
OBJETIVOS
OBJETIVO GENERAL
Demostrar la importancia de la fase de generación de código objeto
mediante la explicación a detalle de la estructura del mismo.
OBJETIVOS ESPECÍFICOS
• Profundizar en el tema de generación de código objeto a través de
ejemplos en algunos de los casos.
• Ejemplificar aspectos relacionados a los subconceptos se abarca en
la generación de código objeto.
Página |6
Medios de Transmisión
II. Generación de Código Objeto
2.1. Concepto
El generador de código recibe como entrada una representación
intermedia del programa fuente y la asigna al lenguaje destino. Si el lenguaje
destino es código máquina, se seleccionan registros o ubicaciones
(localidades) de memoria para cada una de las variables que utiliza el
programa. Después, las instrucciones intermedias se traducen en secuencias
de instrucciones de máquina que realizan la misma tarea. Un aspecto crucial
de la generación de código es la asignación juiciosa de los registros para
guardar las variables.
Por ejemplo, usando los registros R1 y R2, el código intermedio, podría
traducirse en el siguiente código de máquina:
LDF R2, id3
MULF R2, R2, #60.0
LDF R1, id2
ADDF R1, R1, R2
STF id1, R1
El primer operando de cada instrucción especifica un destino. La F en
cada instrucción nos indica que trata con número de punto flotante. El código
carga el contenido de la dirección id3 en el registro R2, y después lo multiplica
con la constante de punto flotante 60.0. El # indica que el número 60.0 se va a
tratar como una constante inmediata. La tercera instrucción mueve id2 al
registro R1 y la cuarta lo suma al valor que se había calculado antes en el
registro R2. Por último, el valor en el registro R1 se almacena en la dirección
de id1, por lo que el código implementa en forma correcta la instrucción de
asignación.
Página |7
Medios de Transmisión
2.2. Organización de Espacio de almacenamiento
La asignación de espacio de almacenamiento para los identificadores en
el programa fuente. La organización del espacio de almacenamiento en tiempo
de ejecución depende del lenguaje que se esté compilando. Las decisiones
sobre la asignación de espacio de almacenamiento se realizan durante la
generación de código intermedio, o durante la generación de código.
La fase final de un compilador es la generación de código objeto, que
por lo general consiste en código de máquina relocalizable o código
ensamblador. Las posiciones de memoria se seleccionan para cada una de las
variables usadas por el programa. Después, cada una de las instrucciones
intermedias se traduce a una secuencia de instrucciones de máquina que
ejecuta la misma tarea. Un aspecto decisivo es la asignación de variables a
registros.
El generador de código objeto puede considerarse como la penúltima
fase de un compilador, la cual se encarga de tomar como entrada el código
intermedio generado por el front-end, y producir código objeto de la arquitectura
target para luego entrar en la fase de optimización de código.
Toma como entrada de representación intermedia el programa fuente y
produce como salida un programa objeto equivalente.
2.3. Procedimiento
Administración de memoria: La correspondencia entre los nombres del
programa fuente con direcciones de objetos de datos en la memoria durante la
ejecución la realiza la etapa inicial en cooperación con el generador de código.
Las entradas en la Tabla de Símbolos se van creando conforme se examina las
declaraciones de un procedimiento. El tipo en una declaración determina la
cantidad de memoria necesaria para el nombre declarado.
Según la información de la Tabla de Símbolos se pueden determinar una
Página |8
Medios de Transmisión
dirección relativa para el nombre de un área de datos para el procedimiento.
Selección de instrucciones: Es importante que el conjunto de
instrucciones sea uniforme y completo. Las velocidades de las instrucciones es un
factor importante. Si no se tiene en cuenta la eficiencia del programa objeto, la
selección de instrucciones es sencilla. Para cada tipo de proposición de tres
direcciones, se puede diseñar un esqueleto de código.
Ejemplo: código de tres direcciones de:
x := y + z
MOV y, R0 /* cargar y en el registro R0 */
ADD z, R0 /* suma z a R0 */
MOV R0, x /* almacenar R0 en x */
Asignación de registros: Las instrucciones que implican operandos en
registros son generalmente más rápidas que las de los operandos en memoria.
Por lo tanto, utilizar eficientemente los registros es fundamental para generar un
buen código. El uso de registros se divide en dos subproblemas:
Durante la asignación de los registros, se selecciona el conjunto de
variables que residirá en los registros en un momento del programa.
Durante la fase posterior de asignación a los registros, se escoge el
registro específico en el que residirá una variable.
Elección del orden de evaluación: El orden en que se realizan los
cálculos puede variar la eficiencia del código objeto. Algunos ordenamientos de
los cálculos necesitan menos registros que otros para guardar resultados
intermedios.
Elegir un orden mejor es un problema difícil, NP-completo.
Página |9
Medios de Transmisión
III. Lenguaje Ensamblador
3.1. Concepto
El ensamblador (del inglés assembler) es un traductor de un código de
bajo nivel a un código, ejecutable directamente por la máquina para la que se
ha generado. El programa lee un archivo escrito en lenguaje ensamblador y
sustituye cada uno de los códigos mnemotécnicos por su equivalente código
máquina. Los programas se hacen fácilmente portables de máquina a máquina
y el cálculo de bifurcaciones se hace de manera fácil.
3.2. Clasificación
Ensambladores básicos: Son de muy bajo nivel, y su tarea consiste
básicamente, en ofrecer nombres simbólicos a las distintas
instrucciones, parámetros y cosas tales como los modos de
direccionamiento.
Ensambladores modulares, o macro ensambladores: Descendientes
de los ensambladores básicos, fueron muy populares en las décadas de
los 50 y los 60, fueron antes de la generalización de los lenguajes de
alto nivel. Una macroinstrucción es el equivalente a una función en un
lenguaje de alto nivel.
3.3. Almacenamiento
Una de las principales ventajas del uso del ensamblador, es que se
encarga de administrar de manera transparente para el usuario la creación de
memoria, las bifurcaciones y el paso de parámetros. Además, nos permite
acceder directamente a los recursos de la máquina para un mejor desempeño.
P á g i n a | 10
Medios de Transmisión
IV. Lenguaje Maquina
4.1. Concepto
Es el que proporciona poca o ninguna abstracción del microprocesador
de un ordenador. El lenguaje máquina solo es entendible por las
computadoras. Se basa en una lógica binaria de 0 y 1, generalmente
implementada por mecanismos eléctricos. En general el lenguaje maquina es
difícil de entender para los humanos por este motivo hacemos uso de lenguajes
más parecidos a los lenguajes naturales.
4.2. Características
El lenguaje máquina realiza un conjunto de operaciones
predeterminadas llamadas micro operaciones. Las micro operaciones sólo
realizan operaciones del tipo aritmética (+,- ,*,/), lógicas (AND, OR, NOT) y de
control (secuencial, de control y repetitiva). El lenguaje maquina es
dependiente del tipo de arquitectura. Así un programa máquina para una
arquitectura Intel x86 no sé ejecutara en una arquitectura Power PC de IBM (al
menos de manera nativa). Algunos microprocesadores implementan mas
funcionalidades llamado CISC, pero son más lentos que los RISC ya que estos
tienen registros más grandes.
Ventajas: Mayor adaptación al equipo. Máxima velocidad con mínimo
uso de memoria.
Desventajas: Imposibilidad de escribir código independiente de la
máquina. Mayor dificultad en la programación y en la comprensión de los
programas. El programador debe conocer más de un centenar de
instrucciones. Es necesario conocer en detalle la arquitectura de la
máquina.
4.3. Direccionamiento
Es la forma en cómo se accede a la memoria. Recordar que un
programa no puede ejecutarse sino se encuentra en memoria principal. La
P á g i n a | 11
Medios de Transmisión
forma de acceder a la memoria depende del microprocesador, pero en general
existen dos tipos de direccionamiento: directo e indirecto. El direccionamiento
directo también recibe el nombre de direccionamiento absoluto y el acceso a
las direcciones se hace de manera directa. El direccionamiento indirecto
también recibe el nombre de direccionamiento relativo y se basa a partir de una
dirección genérica, generalmente el inicio del programa. Para acceder a una
dirección relativa se suma a la dirección base el número de espacios de
memorias necesarias. El direccionamiento relativo hace a los programas
relocalizables e independientes. Si la dirección base es el inicio de la memoria
fija el direccionamiento pasa a ser una variante de direccionamiento absoluto.
V. Registros
5.2. Concepto
Los registros son la memoria principal de la computadora. Existen
diversos registros de propósito general y otros de uso exclusivo. Algunos
registros de propósito general son utilizados para cierto tipo de funciones.
Existen registros acumuladores, puntero de instrucción, de pila, etc.
5.2. Distribución
La UCP o CPU tiene 14 registros internos, cada uno de ellos de 16 bits
(una palabra). Los bits están enumerados de derecha a izquierda, de tal modo
que el bit menos significativo es el bit 0.
5.3. Tipos de Registros
Registros de datos:
o AX: Registro acumulador. Es el principal empleado en las
operaciones aritméticas.
o BX: Registro base. Se usa para indicar un desplazamiento.
o CX: Registro contador. Se usa como contador en los
bucles.
P á g i n a | 12
Medios de Transmisión
o DX: Registro de datos. También se usa en las operaciones
aritméticas.
Estos registros son de uso general y también pueden ser
utilizados como registros de 8 bits, para utilizarlos como tales
es necesario referirse a ellos como por ejemplo: AH y AL, que
son los bytes alto (high) y bajo (low) del registro AX. Esta
nomenclatura es aplicable también a los registros BX, CX y
DX.
Registros de segmentos:
o CS: Registro de segmento de código. Contiene la dirección
de las instrucciones del programa.
o DS: Registro segmento de datos. Contiene la dirección del
área de memoria donde se encuentran los datos del
programa.
o SS: Registro segmento de pila. Contiene la dirección del
segmento de pila. La pila es un espacio de memoria
temporal que se usa para almacenar valores de 16 bits
(palabras).
o ES: Registro segmento extra. Contiene la dirección del
segmento extra. Se trata de un segmento de datos
adicional que se utiliza para superar la limitación de los
64Kb del segmento de datos y para hacer transferencias
de datos entre segmentos.
Registros punteros de pila:
o SP: Puntero de la pila. Contiene la dirección relativa al
segmento de la pila.
o BP: Puntero base. Se utiliza para fijar el puntero de pila y
así poder acceder a los elementos de la pila.
Registros índices:
o SI: Índice fuente.
P á g i n a | 13
Medios de Transmisión
o DI: Índice destino.
Puntero de instrucciones:
o IP: Registro puntero de instrucción o contador de programa
(PC). Contiene el desplazamiento de la siguiente
instrucción a ejecutar respecto al segmento de código en
ejecución. Por lo tanto, la dirección completa de la
siguiente instrucción sería CS:IP. La única forma de influir
en este registro es de forma indirecta mediante
instrucciones de bifurcación.
Registro de banderas (flags): Cada bandera es un bit y se usa
para registrar la información de estado y de control de las
operaciones del microprocesador.
o Hay nueve banderas (los 7 bits restantes no se utilizan):
Banderas de estado: Registran el estado del procesador,
normalmente asociado a una comparación o a una
instrucción aritmética.
o CF: Bandera de acareo.
o OF: Bandera de desbordamiento (aritmético).
o ZF: Bandera de resultado 0 o comparación igual.
o SF: Bandera de resultado o comparación negativa.
o PF: Bandera de paridad (número par de bits).
o AF: Bandera auxiliar. Indica si hay necesidad de ajuste en
las operaciones aritméticas con números BCD.
Banderas de control:
o DF: Bandera de dirección. Controla la dirección de las
operaciones con cadenas de caracteres incrementando o
decremento automáticamente los registros índices (SI y
DI).
o IF: Bandera de interrupciones. Indica si están permitidas o
no las interrupciones de los dispositivos externos.
P á g i n a | 14
Medios de Transmisión
o TF: Bandera de atrape. Controla la operación de modo
paso a paso (usada por el programa DEBUG).
VI. Asignación
6.1. Concepto
La arquitectura de los procesadores x86 obliga al uso de segmentos de
memoria para manejar la información, el tamaño de estos segmentos es de
64kb. La razón de ser de estos segmentos es que, considerando que el tamaño
máximo de un número que puede manejar el procesador esta dado por una
palabra de 16 bits o registro, no sería posible acceder a más de 65536
localidades de memoria utilizando uno solo de estos registros, ahora, si se
divide la memoria de la pc en grupos o segmentos, cada uno de 65536
localidades, y utilizamos una dirección en un registro exclusivo para localizar
cada segmento, y entonces cada dirección de una casilla específica la
formamos con dos registros, nos es posible acceder a una cantidad de
4294967296 bytes de memoria, lo cual es, en la actualidad, más memoria de la
que veremos instalada en una PC. Para que el ensamblador pueda manejar los
datos es necesario que cada dato o instrucción se encuentren localizados en el
área que corresponde a sus respectivos segmentos. El ensamblador accede a
esta información tomando en cuenta la localización del segmento, dada por los
registros DS, ES, SS y CS, y dentro de dicho registro la dirección del dato
específico.
6.2. Aplicación
Cuando creamos un programa empleando el Debug en cada línea que
vamos ensamblando aparece algo parecido a lo siguiente:
1CB0:0102 MOV AX, BX.
En donde el primer número, 1CB0, corresponde al segmento de
memoria que se está utilizando, el segundo se refiere a la dirección dentro de
dicho segmento, y a continuación aparecen las instrucciones que se
almacenaran a partir de esa dirección.
P á g i n a | 15
Medios de Transmisión
La forma de indicarle al ensamblador con cuales de los segmentos se va
a trabajar es por medio de las directivas .CODE, .DATA y. STACK. El
ensamblador se encarga de ajustar el tamaño de los segmentos tomando como
base el número de bytes que necesita cada instrucción que va ensamblando,
ya que sería un desperdicio de memoria utilizar los segmentos completos. Por
ejemplo, si un programa únicamente necesita 10kb para almacenar los datos,
el segmento de datos únicamente será de 10kb y no de los 64kb que puede
manejar.
VII. CONCLUSIONES
Las estructuraciones de generación de código, es muy amplia pues
sus conceptos abarcan parte de lenguajes diferentes como el
ensamblador y máquina, dicho caso, aquí cabe la importancia de
esta fase, lo cual es determinante identificar el asignador y el
direccionamiento.
La generación de código objeto, es parte fundamental dentro de la
compilación, pues aquí definimos el espacio de almacenamiento y el
direccionamiento, aspectos que serán útiles en la siguiente fase de
interpretación de código.
Resaltar mucho el conocimiento del lenguaje maquina y
ensamblador, puesto que se manejará directamente con el tipo de
hardware que se usa y respecto a ello, se aplicará el código.
P á g i n a | 16