UNIDAD 2_AUTOMATAS.pdf
Short Description
Download UNIDAD 2_AUTOMATAS.pdf...
Description
GENERACIÓN DE CÓDIGO INTERMEDIO UNIDAD II
COMPILADORES TEORÍA E IMPLEMENTACION JACINTO RUIZ CATALÁN ALFAOMEGA
CONSTRUCCION DE COMPILADORES PRINCIPIOS Y PRACTICA KENNETH C. LOUDEN THOMSON EDITORES
TRADUCTORES Y COMPILADORES CON LEX YACC JFLEX CUP Y JAVACC SERGIO GALVES ROJAS MIGUEL ANGEL MORA MATA
Analizar
una máquina virtual que ejecute código intermedio a partir del código fuente de un lenguaje prototipo.
2.1 Notaciones 2.1.1 Prefija 2.1.2 Infija 2.2.3 Postfija
2.2 Representaciones de código Intermedio.
2.2.1 Notación Polaca 2.2.2 Código P 2.2.3 Triplos 2.2.4 Cuádruplos.
2.3 Esquema de generación.
2.3.1 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6
Variables y constantes. Expresiones. Instrucción de asignación. Instrucciones de control. Funciones Estructuras
Fases dependientes del lenguaje Fuente e independientes de la Maquina final
CODIGO FUENTE
Fases independientes del lenguaje Fuente pero dependientes del código Intermedio y de la maquina final
CODIGO INTERMEDIO
ANALISIS LEXICO
OPTIMIZACION DE CODIGO INTERMEDIO
ANALISIS SINTACTICO
GENERACION DE CODIGO FINAL
ANALISIS SEMANTICO GENERACIÓN DE CODIGO INTERMEDIO
FRONT END
OPTIMIZACIÓN DE CODIGO FINAL
CODIGO FINAL / EJECUTABLE
BACK END
Diferencia
entre código fuente y código
ejecutable. Diferencia
entre código código ejecutable nativo.
Obtención
interpretable
de código ejecutable.
y
Arquitectura básica de Von Neumann “En la memoria se almacena el programa y los datos necesarios para que éste opere”
Instrucciones del procesador Son las instrucciones básicas que puede realizar la UCP. Con ellas se construyen los programas que puede entender la UCP “código máquina” Cada instrucción básica “instrucción máquina” se especifica mediante un código de instrucción junto con la información sobre cómo obtener los operandos necesarios. Todo ello conforma el “formato de instrucción”. operador operando1 operando2 FORMATO DE INSTRUCCIÓN
Unidad Central de Proceso CPU Componente encargado de ejecutar las instrucciones que están en memoria principal. Capaz de ejecutar millones de instrucciones MHz
instrucciones de los programas son almacenados en la memoria primaria. La primer tarea del CPU es leer una instrucción de la memoria.
EL PROCESADOR
Las
unidad Prefetch le indica al bus que instrucción o conjunto de instrucciones tiene que leer (direcciones de memoria). Prelectura de la instrucción desde la memoria principal.
EL PROCESADOR
La
Unidad de Decodificación toma las instrucciones leídas y las traslada a una forma adecuada para el procesamiento interno de CPU. operador operando1 operando2 FORMATO DE INSTRUCCIÓN
EL PROCESADOR
La
Unidad de Control coordina y organiza cuales elementos del CPU realizarán funciones.
EL PROCESADOR
La
Unidad Aritmético Lógica (Logic Unit) se encarga de ejecutar las operaciones correspondientes. Incluye registros de 32 o 64 bits generalmente.
EL PROCESADOR
La
Creación
y ejecución de programas en código nativo (Lenguaje C) Archivo de texto escrito por el programador
Ejecución de código intermedio (interpretado)
Creación y ejecución de programas en código interpretado. (Java) Bite Code hola.class
El
código intermedio (CI) es la representación en un lenguaje sencillo de la secuencia real de las operaciones que se harán como resultado de las fases anteriores.
Se
trata de representar de una manera formalizada las operaciones a llevar a cabo en un lenguaje más cercano a la máquina final, aunque no a una máquina concreta si no a una máquina abstracta.
Ventajas
del código intermedio
Aumenta la portabilidad del compilador de una máquina a otra. EJEMPLO Java Fácil de producir. Reglas claras de construcción. Fácil de traducir al lenguaje objeto.
Las
notaciones son una forma especial en la que se pueden expresar una expresión matemática y puedan ser de 3 formas: infija, prefija y posfija. Los prefijos, Pre - Pos - In se refieren a la posición relativa del operador con respecto a los dos operandos.
a
+
b
Operando
Operador
Operando
La
característica distintiva de esta notación es que coloca los operadores a la izquierda de sus operandos. 2+3 + 2 3
No
requiere de paréntesis para indicar el orden de precedencia de operadores. Se evalúa de izquierda a derecha hasta que se encuentre el primer operador seguido inmediatamente de un par de operandos.
(3*6)/
(2+4)
LECTURA FINAL
EVALUACIÓN
/*36+24 EVALUACIÓN
EVALUACIÓN
(3*6)/ (2+4) 4
2
+
6
3
*
/*36+24
LECTURA FINAL
+ )
)
E
/
/
)
*
/
/
E
/*36+24 EVALUACIÓN
3 2
4
4
2+4
6
6
6
18
6
6
6
3*6
3
18/6
Nodo,
Hijo_izquierdo, Hijo_derecho expexp op exp|num (3*6)/ (2+4)
/ *
3
/*36+24
+
6
2
4
Es
la notación común de fórmulas aritméticas y lógicas, en la cual se escriben los operadores entre los operandos en que están actuando: 2+2 No es tan simple de analizar por las computadoras, como la notación prefija o la notación postfija, aunque muchos lenguajes de programación la utilizan debido a su familiaridad.
Hijo_izquierdo,
Nodo, Hijo_derecho expexp op exp|num (3*6)/ (2+4) /
3*6 / 2+4
*
3
+
6
2
4
Se refiere a que el operador ocupa la posición después de los operandos.
S=A+B*C S A B C * + =
Su principio es el de evaluar los datos directamente cuando se introducen y manejarlos dentro de una estructura LIFO (Last In First Out), lo que optimiza los procesos a la hora de programar.
(3*6)/
(2+4) EVALUACIÓN
LECTURA FINAL
36*24+/ EVALUACIÓN
(3*6)/
3
6
*
(2+4) 2
EVALUACIÓN
4
+
/
36*24+/
LECTURA FINAL
+
* (
(
E
/
(
(
/
/
E
36*24+/ EVALUACIÓN
4 6 3
3
3*6
18
2
2
6
18
18
18
4+2
3
18/6
Hijo_izquierdo,
Hijo_derecho, Nodo expexp op exp|num (3*6)/ (2+4)
/ *
3
36*24+/
+
6
2
4
Generación
de código:
Simple No utiliza registros
Optimización
Es difícil de reordenar ya que hay que considerar el contenido de la pila (Polaca Inversa)
Interpretación
rápida
Es muy fácil de interpretar ya que solo necesita una pila
Transportable:
Si, ya que todos los procesadores implementan una pila.
Su principio es el de evaluar los datos directamente cuando se introducen y manejarlos dentro de una estructura LIFO (Last In First Out), lo que optimiza los procesos.
if then else
No se puede traducir a If Código generado Salta Si falso Etiqueta1 Salta Etiqueta2 Etiqueta1:
Es
una especificación de una Unidad Central de Procesamiento donde las instrucciones están diseñadas a ser ejecutadas por software (interpretadas) en lugar de Hardware.
El
código P comenzó como un código ensamblador objetivo estándar producido por varios compiladores Pascal en la década de 1970.
Fue
diseñado para una maquina de pila hipotética la idea era hacer que los compiladores de Pascal se transportaran fácilmente.
En la creación de código intermedio se utilizan instrucciones simbólicas para representar los datos (variables, parámetros, etc.) que posteriormente se trasladarán a direcciones reales en el mapa físico de memoria.
Cada instrucción de tres direcciones tiene a lo sumo un operador. El compilador debe generar un nombre temporal para guardar los valores calculados por cada instrucción. Algunas instrucciones de "tres direcciones" tiene menos de tres operadores.
Cuádruplos Triplos
x=x+1; //Supongamos que x representa un entero Pasos para generar el CI R1= valor (x) R2= valor (1) R3= R1 + R2 x=R3
• • • •
CARGAR x null R1 CARGAR 1 null R2 SUMAR R1 R2 R3 CARGAR R3 null x
CODIGO DE TRES DIRECCIONES
CÓDIGO DE TRES DIRECCIONES
Ejemplo:
CARGAR 0 null 10000 CARGAR 10000 null 9000 CARGAR 9000 null 10001 CARGAR 1 null 10002 SUMAR 10001 10002 10003 CARGAR 10003 null 9000
posteriormente se trasladarán a direcciones reales en el mapa físico de memoria
CÓDIGOS DE TRES DIRECCIONES
int x main(){ x=0; x=x+1; }
CI • CARGAR x null R1 • CARGAR 0 null R1 • CARGAR 1 null R2 • SUMAR R1 R2 R3 • CARGAR R3 null x
OTROS ARGUMENTOS DEL CI RESTAR, MULTIPLICAR, DIVIDIR OR, AND MAYOR, MENOR (Si se cumple coloca 1 en el res) IGUAL, DISTINTO ETIQUETA Salto incondicional SALTAR_ETIQUETA null null etiq Saltos condicionales SALTAR_CONDICION
op1 null etiq //SOLO SI ES FALSA
IMPRIMIR_ENTERO 7 null null IMPRIMIR_CADENA cad null null Llamada al procedimiento p(x 1,x 2,...,x n).
param x1 ... param xn Call p,n
EL CI es muy próximo a un lenguaje ensamblador
CARGAR A NULL R1 CARGAR B NULL R2 MAYOR R1 R2 R3 SALTAR_CONDICION R3 E1 E1 NULL NULL E1
CÓDIGOS DE TRES DIRECCIONES
If aY THEN Z=X ELSE Z=Y+1 1 (>, X, Y) 2 (Saltar si falso, (1), 5) 3 (=, Z, X) 4 (Saltar, , 7) 5 (+, Y, 1) 6. (=, Z, (5)) 7. ...
SI FALSO
EJERCICIO:
A=B+C*D/E F=C*D Operaciones 1. (1) 2. (2) 3. (3) 4. (4) 5. (1) 6. (5)
Tripletas (1) *, C, D (2) /, (1), E (3) +, B (2) (4) =, A, (3) (5) =, F, (1)
Los cuartetos son la herramienta más general Inconvenientes
Ocupan
demasiado espacio Requieren muchas variables auxiliares para almacenar los resultados intermedios
Los tercetos resuelven este problema suprimiendo el operando del resultado, queda implícito y asociado a dicho terceto Inconvenientes
La optimización supone mover tripletas y hay que recalcular las referencias
int x = 10; int y = 0; main(){ while(x>0){ y =y+x;
x=x-1; } print(“Si leer”); if(x==0 && y>54){ print(“Si leer”); }else{ print(“No leer”); } }
CARGAR 10 null 10001 CARGAR 0 null 10002 ETIQUETA null null BUCLE_1 CARGAR 10001 null 10003 CARGAR 0 null 10004 MAYOR 10003 10004 10005 SALTAR_CONDICION 10005 null FIN_BUCLE_1 CARGAR 10002 null 10006 CARGAR 10001 null 10007 SUMAR 10006 10007 10008 CARGAR 10008 null 10002 CARGAR 10001 null 10009 CARGAR 1null 10010 RESTAR 10009 10010 10011 CARGAR 10011 null 10001 SALTAR_ETIQUETA null null BUCLE_1 ETIQUETA null null FINBUCLE_1 IMPRIMIR_CADENA cadena1 null null
int x = 10; int y = 0; main(){ while(x>0){ y =y+x;
x=x-1; } print(“Si leer”); if(x==0 && y>54){ print(“Si leer”); }else{ print(“No leer”); } }
CARGAR 10001 null 10013 CARGAR 0 null10014 IGUAL 10013 10014 10015 CARGAR 10002 null 10016 CARGAR 54 null10017 MAYOR 10016 10017 10018 AND 10015 10018 10019 SALTAR_CONDICION 10019 null ELSE_1 IMPRIMIR_CADENA cadena2 null null ETIQUETA null null ELSE_1 IMPRIMIR_CADENA cadena3 null null
int x=10; int y=20; while (x*2x*4){ x=x+1; } }
CARGAR 10 null 10001 CARGAR 20 null 10002 ETIQUETA null null BUCLE_1 CARGAR 10001 null 10003 CARGAR 2 null 10004 MULTIPLICAR 10003 10004 10005 CARGAR 10002 null 10006 MENOR 10005 10006 10007 SALTAR_CONDICION 10007 null FIN_BUCLE_1 ETIQUETA null null BUCLE_2 CARGAR 10002 null 10008 CARGAR 10001 null 10009 CARGAR 4 null 10010 MULTIPLICAR 10009 10010 10011 MAYOR 10008 10011 10012 SALTAR_CONDICION 10012 null FIN_BUCLE_2 CARGAR 10001 null 10013 CARGAR 1 null 10014 SUMAR 10013 10014 10015 CARGAR 10001 null 10015 SALTAR_ETIQUETA null null BUCLE_2 SALTAR_ETIQUETA null null BUCLE_1 ETIQUETA null null FIN_BUCLE_2 ETIQUETA null null FIN_BUCLE_1
int x=1-12; TAREA int y=x*32 CUADRUPLOS main(){ Y TRIPLOS x=1-12; y=x*32; x=(32/12)*y; if(x>7){ while(y>0){ y=y-1; if(y>1){ print(y); } } } }
COMPILADORES TEORÍA E IMPLEMENTACION JACINTO RUIZ CATALÁN ALFAOMEGA
CONSTRUCCION DE COMPILADORES PRINCIPIOS Y PRACTICA KENNETH C. LOUDEN THOMSON EDITORES
TRADUCTORES Y COMPILADORES CON LEX YACC JFLEX CUP Y JAVACC SERGIO GALVES ROJAS MIGUEL ANGEL MORA MATA
GENERACIÓN DE CÓDIGO INTERMEDIO. UNIDAD II
View more...
Comments