Академический Документы
Профессиональный Документы
Культура Документы
Captulo 1
Introduccin
1.1
Visin general
Introduccin
1.2
Concepto de traductor.
1.2.1
Tipos de traductores
1.2.1.2 Compiladores
Es aquel traductor que tiene como entrada una sentencia en lenguaje formal
y como salida tiene un fichero ejecutable, es decir, realiza una traduccin de un cdigo
de alto nivel a cdigo mquina (tambin se entiende por compilador aquel programa
que proporciona un fichero objeto en lugar del ejecutable final).
1.2.1.3 Intrpretes
Es como un compilador, solo que la salida es una ejecucin. El programa de
entrada se reconoce y ejecuta a la vez. No se produce un resultado fsico (cdigo
mquina) sino lgico (una ejecucin). Hay lenguajes que slo pueden ser interpretados,
como p.ej. SNOBOL (StriNg Oriented SimBOlyc Language), LISP (LISt Processing),
algunas versiones de BASIC (Beginners All-purpose Symbolic Instruction Code), etc.
Su principal ventaja es que permiten una fcil depuracin. Entre los
inconvenientes podemos citar, en primer lugar, la lentitud de ejecucin , ya que al
ejecutar a la vez que se traduce no puede aplicarse un alto grado de optimizacin; por
ejemplo, si el programa entra en un bucle y la optimizacin no est muy afinada, las
mismas instrucciones se interpretarn y ejecutarn una y otra vez, enlenteciendo la
ejecucin del programa. Otro inconveniente es que durante la ejecucin, el intrprete
debe residir en memoria, por lo que consumen ms recursos.
3
Introduccin
1.2.1.4 Preprocesadores
Permiten modificar el programa fuente antes de la verdadera compilacin.
Hacen uso de macroinstrucciones y directivas de compilacin. Por ejemplo, en lenguaje
C, el preprocesador sustituye la directiva #include Uno.c por el cdigo completo que
contiene el fichero Uno.c, de manera que cuando el compilador comienza su
ejecucin se encuentra con el cdigo ya insertado en el programa fuente (la figura 1.3
ilustra esta situacin). Algunas otras directivas de preprocesamiento permiten compilar
trozos de cdigos opcionales (lenguajes C y Clipper): #fi, #ifdef, #define, #ifndef, etc.
Los preprocesadores suelen actuar de manera transparente para el programador,
pudiendo incluso considerarse que son una fase preliminar del compilador.
Introduccin
con lo que se consigue una mayor portabilidad en los programas de alto nivel.
Por ejemplo, si un ordenador slo dispone de un compilador de Pascal, y
queremos ejecutar un programa escrito para otra mquina en COBOL, pues un
conversor de COBOL a Pascal solucionar el problema. No obstante el programa
fuente resultado puede requerir retoques manuales debido a diversos motivos:
En situaciones en que el lenguaje destino carece de importantes caractersticas
que el lenguaje origen s tiene. Por ejemplo un conversor de Java a C,
necesitara modificaciones ya que C no tiene recolector de basura.
En situaciones en que la traduccin no es inteligente y los programas destino
son altamente ineficientes.
1.2.2
produce un compilador.
Pero, por qu no se genera directamente un fichero ejecutable?
Sencillamente, para permitir la compilacin separada, de manera que varios
programadores puedan desarrollar simultneamente las partes de un programa ms
grande y, lo que es ms importante, puedan compilarlos independientemente y realizar
una depuracin en paralelo. Una vez que cada una de estas partes ha generado su
correspondiente fichero objeto, estos deben fusionarse para generar un solo ejecutable.
Como se ha comentado, un fichero objeto posee una estructura de mdulos
tambin llamados registros. Estos registros tienen longitudes diferentes dependiendo
de su tipo y cometido. Ciertos tipos de estos registros almacenan cdigo mquina, otros
poseen informacin sobre las variables globales, y otros incluyen informacin sobre los
objetos externos (p. ej, variables que se supone que estn declaradas en otro ficheros.
El lenguaje C permite explcitamente esta situacin mediante el modificador extern).
Durante la fase de enlace, el enlazador o linker resuelve las referencias
cruzadas, (as se llama a la utilizacin de objetos externos), que pueden estar
declarados en otros ficheros objeto, o en libreras (ficheros con extensin lib o dll),
engloba en un nico bloque los distintos registros que almacenan cdigo mquina,
estructura el bloque de memoria destinado a almacenar las variables en tiempo de
ejecucin y genera el ejecutable final incorporando algunas rutinas adicionales
procedentes de libreras, como por ejemplo las que implementan funciones matemticas
o de e/s bsicas. La figura 1.5 ilustra este mecanismo de funcionamiento.
Introduccin
etc.
Cuando el enlazador construye el fichero ejecutable, asume que cada
segmento va a ser colocado en la direccin 0 de la memoria. Como el programa va a
estar dividido en segmentos, las direcciones a que hacen referencia las instrucciones
dentro de cada segmento (instrucciones de cambio de control de flujo, de acceso a
datos, etc.), no se tratan como absolutas, sino que son direcciones relativas a partir de
la direccin base en que sea colocado cada segmento en el momento de la ejecucin.
El cargador carga el fichero .exe, coloca sus diferentes segmentos en memoria (donde
el sistema operativo le diga que hay memoria libre para ello) y asigna los registros base
a sus posiciones correctas, de manera que las direcciones relativas funcionen
correctamente. La figura 1.6 ilustra el trabajo que realiza un cargador de programas.
Figure 6Labor realizada por el cargador. El cargador suele ser parte del
sistema operativo
Cada vez que una instruccin mquina hace referencia a una direccin de
memoria (partiendo de la direccin 0), el microprocesador se encarga automticamente
de sumar a dicha direccin la direccin absoluta de inicio de su segmento. Por ejemplo
para acceder a la variable x almacenada en la direccin 1Fh, que se encuentra en el
segmento de datos ubicado en la direccin 8A34h, la instruccin mquina har
referencia a 1Fh, pero el microprocesador la traducir por 8A34h+1Fh dando lugar a
un acceso a la direccin 8A53h: dir absoluta del segmento en memoria + dir relativa
de x en el segmento = dir absoluta de x en memoria.
Introduccin
1.2.2.4 Autocompilador
Es un compilador escrito en el mismo lenguaje que compila (o parecido).
Normalmente, cuando se extiende entre muchas mquinas diferentes el uso de un
compilador, y ste se desea mejorar, el nuevo compilador se escribe utilizando el
lenguaje del antiguo, de manera que pueda ser compilado por todas esas mquinas
diferentes, y d como resultado un compilador ms potente de ese mismo lenguaje.
1.2.2.5 Metacompilador
Este es uno de los conceptos ms importantes con los que vamos a trabajar.
Un metacompilador es un compilador de compiladores. Se trata de un programa que
acepta como entrada la descripcin de un lenguaje y produce el compilador de dicho
lenguaje. Hoy por hoy no existen metacompiladores completos, pero s parciales en los
que se acepta como entrada una gramtica de un lenguaje y se genera un autmata que
reconoce cualquier sentencia del lenguaje . A este autmata podemos aadirle cdigo
para completar el resto del compilador. Ejemplos de metacompiladores son: Lex,
YACC, FLex, Bison, JavaCC, JLex, Cup, PCCTS, MEDISE, etc.
Los metacompiladores se suelen dividir entre los que pueden trabajar con
gramticas de contexto libre y los que trabajan con gramticas regulares. Los primeros
se dedican a reconocer la sintaxis del lenguaje y los segundos trocean los ficheros
fuente y lo dividen en palabras.
PCLex es un metacompilador que genera la parte del compilador destinada a
reconocer las palabras reservadas. PCYACC es otro metacompilador que genera la
parte del compilador que informa sobre si una sentencia del lenguaje es vlida o no.
JavaCC es un metacompilador que ana el reconocimiento de palabras reservadas y la
aceptacin o rechazo de sentencias de un lenguaje. PCLex y PCYACC generan cdigo
C y admiten descripciones de un lenguaje mediante gramticas formales, mientras que
JavaCC produce cdigo Java y admite descripciones de lenguajes expresadas en
10
notacin BNF (Backus-Naur Form). Las diferencias entre ellas se irn estudiando en
temas posteriores.
1.2.2.6 Descompilador
Un descompilador realiza una labor de traduccin inversa, esto es, pasa de un
cdigo mquina (programa de salida) al equivalente escrito en el lenguaje que lo gener
(programa fuente). Cada descompilador trabaja con un lenguaje de alto nivel concreto.
La descompilacin suele ser una labor casi imposible, porque al cdigo
mquina generado casi siempre se le aplica una optimizacin en una fase posterior, de
manera que un mismo cdigo mquina ha podido ser generado a partir de varios
cdigos fuente. Por esto, slo existen descompiladores de aquellos lenguajes en los que
existe una relacin biyectiva entre el cdigo destino y el cdigo fuente, como sucede
con los desensambladores, en los que a cada instruccin mquina le corresponde una
y slo una instruccin ensamblador.
Los descompiladores se utilizan especialmente cuando el cdigo mquina ha
sido generado con opciones de depuracin, y contiene informacin adicional de ayuda
al descubrimiento de errores (puntos de ruptura, seguimiento de trazas, opciones de
visualizacin de variables, etc.).
Tambin se emplean cuando el compilador no genera cdigo mquina puro,
sino pseudocdigo para ser ejecutado a travs de un pseudointrprete. En estos casos
suele existir una relacin biyectiva entre las instrucciones del pseudocdigo y las
construcciones sintcticas del lenguaje fuente, lo que permite reconstruir un programa
de alto nivel a partir del de un bloque de pseudocdigo.
1.3
Estructura de un traductor
Un traductor divide su labor en dos etapas: una que analiza la entrada y genera
estructuras intermedias y otra que sintetiza la salida a partir de dichas estructuras. Por
tanto, el esquema de un traductor pasa de ser el de la figura 1.1, a ser el de la figura 1.7.
Bsicamente los objetivos de la etapa de anlisis son: a) controlar la
correccin del programa fuente, y b) generar las estructuras necesarias para comenzar
la etapa de sntesis.
Para llevar esto a cabo, la etapa de anlisis consta de las siguientes fases:
O Anlisis lexicogrfico. Divide el programa fuente en los componentes bsicos
Introduccin
1.3.1
Con frecuencia, las fases anteriores se agrupan en una etapa inicial (frontend) y una etapa final (back- end). La etapa inicial comprende aquellas fases, o partes
de fases, que dependen exclusivamente del lenguaje fuente y que son independientes
de la mquina para la cual se va a generar el cdigo. En la etapa inicial se integran los
anlisis lxicos y sintcticos, el anlisis semntico y la generacin de cdigo
intermedio. La etapa inicial tambin puede hacer cierta optimizacin de cdigo e
incluye adems, el manejo de errores correspondiente a cada una de esas fases.
La etapa final incluye aquellas fases del compilador que dependen de la
mquina destino y que, en general, no dependen del lenguaje fuente sino slo del
lenguaje intermedio. En esta etapa, se encuentran aspectos de la fase de generacin de
12
Introduccin
Muestra una situacin en la que se quiere crear un compilador del lenguaje C para tres
mquinas diferentes: Dec-Alpha (Unix), Motorola (Mac OS) e Intel (MS-DOS). Cada
bloque de lneas punteadas agrupa un front-end con un back-end dando lugar a un
compilador completo.
De manera inversa se podran construir tres compiladores de Pascal, C y
COBOL para una misma mquina, p.ej. Intel, como se ilustra en la figura 1.9.
Por ltimo, la creacin de compiladores de Pascal, C y COBOL para las
mquinas Dec-Alpha, Motorola e Intel, pasara por la combinacin de los mtodos
anteriores, tal como ilustra la figura 1.10.
1.3.2
La tabla de smbolos
1.4
Ejemplo de compilacin
Vamos a estudiar a continuacin las diferentes tareas que lleva a cabo cada
fase de un compilador hasta llegar a generar el cdigo asociado a una sentencia de C.
La sentencia con la que se va a trabajar es la siguiente:
#define PORCENTAJE 8
comision = fijo + valor * PORCENTAJE;
Para no complicar demasiado el ejemplo, asumiremos que las variables
referenciadas han sido previamente declaradas de tipo int, e inicializadas a los valores
deseados.
Comenzaremos con el preprocesamiento hasta llegar, finalmente, a la fase de
generacin de cdigo mquina en un microprocesador cualquiera.
15
Introduccin
1.4.1
Preprocesamiento
1.4.2
Etapa de anlisis
En esta etapa se controla que el texto fuente sea correcto en todos los sentidos,
y se generan las estructuras necesarias para la generacin de cdigo.
16
Introduccin
Trabaja con una gramtica de contexto libre y genera el rbol sintctico que
reconoce su sentencia de entrada. En nuestro caso las categoras gramaticales del
anlisis lxico son los terminales de la gramtica. Para el ejemplo que nos ocupa
podemos partir de la gramtica:
S <ID> <ASIG> expr <TERM>
expr <ID>
| <ID> <+> expr
| <ID> <*> expr
| <NUM>
de manera que el anlisis sintctico intenta generar un rbol sintctico que encaje con
la sentencia de entrada. Para nuestro ejemplo, dicho rbol sintctico existe y es el de
la figura 1.14. El rbol puede representarse tal y como aparece en esta figura, o bien
1.4.2.2.1
1.4.3
Etapa de sntesis
19
Introduccin
registros.
Siguiendo el mismo ejemplo, y utilizando los registros R1 y R2 de un
microprocesador hipottico, la traduccin del cdigo optimizado podra ser:
MOVE [1Ah], R1
MULT #8.0, R1
MOVE [15h], R2
ADD R1, R2
MOVE R2, [10h]
El primer y segundo operandos de cada instruccin especifican una fuente y
un destino, respectivamente. Este cdigo traslada el contendido de la direccin [1Ah]
al registro R1, despus lo multiplica por la constante real 8.0. La tercera instruccin
pasa el contenido de la direccin [15h] al registro R2. La cuarta instruccin le suma el
valor previamente calculado en el registro R1. Por ltimo el valor del registro R2 se
pasa a la direccin [10h]. Como el lector puede suponer, la variable comision se
almacena en la direccin [10h], fijo en [15h] y valor en [1Ah].
21
Introduccin
22