TECNOLOGICO DE ESTUDIOS SUPERIORES DE IXTAPALUCA

ING. EN SISTEMAS COMPUTACIONALES

ASIGNATURA: PROGRAMACION DE SISTEMAS

(ANALOGIA DE LOS TEMAS EN CLASE)

PROF.: GARCIA CORTES DAVID

ALUMNA: GOMEZ MERCADO GUADALUPE

GRUPO: 1502

MATRICULA: 200920834

FECHA DE ENTREGA: 30 DE ENERO DE 2012

INDICE
1

Introducción………………………………………………………………… ……………………………….6 Unidad I.- Introducción a la programación de Sistemas…………………………………7 1.1 ¿Qué es y que estudia la programación de sistemas? 1.2 Herramientas desarrolladas con la teoría de P.S. 1.3 Lenguajes 1.3.1 Lenguajes naturales 1.3.2 Lenguajes artificiales 1.3.3 Proceso de la comunicación 1.4 Traductor y su estructura 1.4.1 Ensambladores 1.4.2 Compiladores 1.5.3Interpretes 1.5 Generadores de código para compiladores (compilador de compilador) Unidad II Introducción al diseño de los lenguajes de programación…………..12 2.1 Visión del problema 2.2 Consideraciones preliminares 2.3 Objetivos y filosofías del diseño de los lenguajes de programación 2.4 Diseño detallado 2.5 Caso de estudio

2

Unidad III Análisis Léxico………………………………….. …………………………………………15 3.1 Introducción a los Autómatas finitos y expresiones regulares. 3.2 Analizador de léxico. 3.3 Manejo de localidades temporales de memoria (buffers). 3.4 Creación de tablas de símbolos. 3.6 Manejo de errores léxicos. 3.6 Generadores de código léxico: Lex y Flex. Unidad IV Análisis Sintáctico……………………………….. ……………………………………..23 4.1 Introducción a las Gramáticas libres de contexto y árboles de derivación. 4.2 Diagramas de sintaxis. 4.3 Precedencia de operadores. 4.4 Analizador sintáctico. 4.4.1 Analizador descendente (LL). 4.4.2 Analizador ascendente (LR, LALR). 4.5 Administración de tablas de símbolos 4.6 Manejo de errores sintácticos y su recuperación 4.7 Generadores de código para analizadores sintácticos: Yacc, Bison.

3

6.Unidad V Análisis Semántico ………………………………………………………………………35 5.3 Prefija. 6.3.2 Verificación de tipos en expresiones.7 Manejo de errores semánticos.1 Analizador semántico 5. 5.4 Acciones agregadas en un analizador sintáctico descendente (top-down).2 Código P.4 Esquemas de generación.1 Notación Polaca. 6.3.3.2 Notaciones.3.5 Pila semántica en un analizador sintáctico ascendente (bottom-up).1 Lenguajes intermedios.1 Infija. 5. 6.2. 5.2. 6.3 Representación de código intermedio.3 Triplos.3 Conversión de tipos. 6.4 Cuádruplos.2 Postfija. 6. 4 .7 Administración de la tabla de símbolos. 5. 5. 6. 6. Unidad VI Generación de Código Intermedio ……………………………………………41 6.2. 6.

4.4. 7.2 Costos. 7.1.4.4. Unidad VII Optimización………………………………………………………………… ……………46 7.2. 7.2. 7. 6. Estatuto de asignación. Declaración de variables.6. Funciones. 7.4.4.1. 7.1 Lenguaje máquina. 6. Expresiones.2.4 De mirilla. 6.3 Herramientas para el análisis del flujo de datos.1.2 Criterios para mejorar el código. Estatuto condicional. Estatuto de ciclos 6. 6. constantes 6.2 Bucles. Arreglos.1 Locales. 5 .3 Globales.1 Costo de ejecución.4. 7.1 Tipos de optimización.1. Unidad VIII Generación de código intermedio ……………………………………………49 8. 7.

2 Almacenamiento.4 Administración de memoria. 8.3 Registros.1 Distribución.1.. 8.1 Características. 8.2.3.2 Lenguaje ensamblador. 8. 8. 8.3.53 6 .8. 8.2 Direccionamiento.2.2 Asignación. 8. Bibliografía………………………………………………………………… …………………………….1 Características.1.

INTRODUCCION En esta antología tenemos un resumen de todo lo visto durante la asignatura de programación de sistemas. Esta asignatura es muy importante para la carrera de ing. En sistemas computacionales ya que tocan temas fundamentales de ella. La programación es un sistema es un conjunto de componentes que se relacionan entre si, para lograr un objetivo común. Las personas se comunican en un lenguaje que es un sistema formado por palabras y símbolos que tienen un significado para quien lo habla y quien loe escucha, lo mismo es para las computadoras. La programación consta de convertir las especificaciones de los sistemas en instrucciones de máquina que producen resultados deseados.

7

Unidad I Introducción a la programación de Sistemas 1.1 ¿Qué es y qué estudia la programación de sistemas? • Programa: conjunto de instrucciones que ejecuta una computadora para realizar una actividad. • Sistema: conjunto de elementos autónomos que trabajan en armonía para alcanzar un objetivo en común. Tipos de sistemas • Sistemas físicos: reales, Hardware equipo, maquinaria, objetos

• Sistemas abstractos: ideas, hipótesis, conceptos, planes, Software • Sistemas abiertos y cerrados dependiendo del ambiente en que se ejecutan. Características de un sistema • Un sistema puede interactuar con su medio ambiente a través de una interfaz de entradas y salidas que recibe el nombre de parámetros del sistema. • Un sistema puede ser componente de otro sistema 1.2 Herramientas desarrolladas con la teoría de programación de sistemas

8

El caso más sencillo de programación de sistemas es la construcción de compiladores para ejecutar lenguajes de programación. Pero no sólo se aplica en lenguajes de programación, sino también se aplica en cualquier programa que se tenga que hacer un análisis o extracción de información Software de sistemas Editores de texto inteligentes (IDEs con autocompletar, revisores ortográficos, etc) Impresoras estéticas (impresión de gran calidad sin un editor visual, Latex, etc.) Intérpretes (Shells de sistemas operativos o de alguna aplicación como un SMBD) Búsqueda de información que no es tan común en base a patrones, etc. 1.3 Lenguajes Conjunto de palabras y reglas que permiten comunicar información entre dos entidades. El lenguaje que entienden las máquinas (lenguaje formal) es muy diferente del lenguaje que entendemos los humanos • Lenguaje: Son las cadenas que pueden generarse a través de una gramática Repaso de lenguajes y autómatas • Símbolo: representación abstracta de alguna entidad • Alfabeto: conjunto finito de símbolos

• Cadena: yuxtaposición de símbolos de un alfabeto que representan a un objeto
9

3.1 Lenguajes naturales El lenguaje natural es inherentemente ambiguo. 5 • LOAD A.2 Lenguajes artificiales Los lenguajes artificiales son aquellos que los humanos hemos creado para comunicarnos • Las computadoras sólo saben 0 y 1 • Un lenguaje artificial permite implementar un algoritmo en una computadora para resolver un problema. Lenguajes de bajo nivel • Una abstracción más entendible del lenguaje máquina es el uso de lenguajes ensambladores en donde cada instrucción o mnemónico es traducido a una instrucción máquina.• Lenguaje: conjunto de cadenas válidas que se pueden formar a través de un alfabeto 1. es mejor crear otro lenguaje. • ADD AX. por lo que se necesita crear un lenguaje que permita eliminar esas ambigüedades. denominado de alto nivel que es el encargado de mediar entre la abstracción humana y la abstracción de lenguaje de máquina 1. 5 10 .3.

3. 1. En este sentido.Lenguajes máquina El lenguaje máquina es dependiente de cada tipo de arquitectura de computadoras por lo que el código no es fácilmente portable a otras arquitecturas. los humanos escribimos algoritmos en un lenguaje formal que una computadora pueda transformar a un lenguaje entendible por ella. Los lenguajes de alto nivel son más portables en lo que respecta al código fuente pudiendo llevarse a otras arquitecturas de computadoras sin mayor problema. los mediadores enmascaran la complejidad y heterogeneidad de los lenguajes.3 Proceso de la comunicación Para entablar una comunicación se necesita que tanto el emisor como el receptor conozcan el mismo lenguaje o en su defecto tengan un traductor. La traducción puede ser sencilla (literal) o compleja (revisar el contexto) dependiendo del tipo de lenguaje de entrada y salida. 11 . un traductor convierte un lenguaje de entrada (código fuente) a uno de salida (código objeto). Clasificación de Chomsky • Lenguajes sin restricciones (gramática 0) • Lenguajes dependientes del contexto (tipo 1) • Lenguajes independientes del contexto (tipo 1.4 Traductor y su estructura Un traductor es un mediador entre dos entidades: emisoras y receptoras.

4. 58d 4F0188 03 CMP 0 3A00 05 JMP etiqueta 9918 … Etiqueta: 18 MUL AX.4. etc. Pascal. FF 4401FF 1. discurso. o artículo técnico o de investigación Ejemplos de compiladores: C. se necesita de al menos otra revisión (pasada) para hacer una buena traducción. //Encabezados 00 MOV AX. El problema radica en el tiempo y en los recursos para hacerlo 12 . Entre más pasadas se de a un código fuente mayor es la optimización que se puede hacer. Ejemplo: la traducción de un libro. C++.2 Compiladores Es el traductor que se encarga de convertir un lenguaje de alto nivel a código máquina. La característica de este traductor radica en el hecho de que necesita revisar todo el código fuente para poder realizar la traducción.Traducción español a inglés si se hace de manera literal es una mala traducción.1 Ensambladores Ensamblador es el traductor que se encarga de convertir instrucciones de bajo nivel a instrucciones de una máquina en general. 1.

instrucciones SQL. Por una parte se compila un programa fuente para generar código objeto para una máquina virtual (bytecode o MSIL) para posteriormente ejecutarse de manera interpretada en las diferentes máquinas virtuales de cada plataforma. etc.5 Generadores de código para compiladores (compilador de compilador) 13 . 1. Lenguajes interpretados: PHP. Preprocesadores: Macros (expansión de funciones) Inclusión de archivos (bibliotecas) Procesadores racionales Extensiones al leguaje (inclusión de ensamblador en C) 1. PERL. ¿Java es compilado o interpretado? Java al igual que otros lenguajes como C# son lenguajes híbridos. BASIC En algunas ocasiones se necesita de una traducción rápida de algunas instrucciones.3 Intérpretes Se ejecutan línea por línea. instrucción por instrucción.Antes de compilar un programa fuente se sigue una etapa de Pre procesamiento.4. A este compilador se les llama jitter de JIT (Just in Time). como en el Shell.

Desarrollar FORTRAN tardó alrededor de 14 años.Los dos primeros lenguajes de alto nivel desarrollado fueron FORTRAN y COBOL. Desarrollar nuestro compilador tardará menos de 6 meses Son herramientas que auxilian algún aspecto del proceso de traducción Herramientas auxiliares para programación de sistemas • Cargadores y editores de enlace • Generadores de analizadores léxico • Generadores de Analizadores sintácticos • Traductores dirigidos por sintaxis • Generadores automáticos de código • Dispositivos para el análisis de flujo de datos 14 .

sirven para casi todo Se debe identificar que es lo que se piensa hacer con el lenguaje. Java. existen para todos los gustos y/o usos. C++.Unidad II Introducción programación 2. HTML es lenguaje de representación visual OWL es lenguaje de descripción de elementos 15 . ¿Quién cargaría una tonelada de papas en un auto deportivo? Los lenguajes de propósito general son como los autos sedán. C. visualizar información o bien realizar la conversión de un documento. Actionscripts son lenguajes específicos ¿Por qué tal diversidad de lenguajes? Los lenguajes de programación son como los carros. Son lenguajes de programación de propósito general SQL. Pascal.1 Visión del problema al diseño de los lenguajes de ¿Cuál es el propósito de un lenguaje? Los lenguajes de computación pueden ser de propósito general o específicos. etc. PROMELA. ya que puede ser sólo la estructuración de contenido Web.

2. los operadores.3 Objetivos y filosofías del diseño de los lenguajes de programación Algunos usos de los lenguajes de programación son: – Comunicación humana – Prevención y Detección de errores – Usabilidad – Portabilidad – Independencia de la máquina Filosofías Es más importante que un programa sea leíble que escribible. si es un lenguaje para profesionales. ya que un programa generalmente se escribe una vez y se lee muchas veces (documentación.2 Consideraciones preliminares Debemos tomar en cuenta las palabras reservadas del lenguaje. los tipos de datos. Debemos considerar el objetivo del lenguaje. mantenimiento.C es un lenguaje programación 2. si es un lenguaje de enseñanza.) La tendencia actual implementación es separa la interfaz de la Tratar de hacer lenguajes para múltiples arquitecturas de computadoras (máquinas virtuales) Control de apuntadores Control de tipo de datos robustos 16 . si el código desarrollado va a ser mejor. etc.

Simplicidad por eficiencia 2. componentes) – Excepciones – Validaciones – Marco de trabajo – Utilerías auxiliares (preprocesador. APIs. enlazador) – Inclusión de otros lenguajes 2. sintaxis) – Semántica – Si existe código intermedio – Si se mejora ese código – El código objeto final 17 .5 Caso de estudio Explicar el lenguaje que se va a desarrollar en el curso: – ¿Por qué se va a desarrollar (problemática)? – Vocabulario del lenguaje (léxico palabras clases que hacen) – Reglas de estructura (gramática.4 Diseño detallado • Considerar características como: – Patrones de diseño – Paquetes (bibliotecas.

18 .1 Introducción a los Autómatas finitos y expresiones regulares ¿Qué es un autómata? Es un modelo matemático que sirve para determinar si una cadena pertenece a un lenguaje no.Unidad III Análisis Léxico 3.

&. . Esto elimina ambigüedades • Una expresión regular representar lenguajes: es una forma abreviada de • a Representa el lenguaje de las letras a • a* Representa el lenguaje que tiene 0 hasta n a’s Autómatas • Oprel <|>|<=|>=|=|<> • Un solo autómata varios sub_autómatas • Programar un autómata: • Identificador letra (letra|digito|gb)* Expresión Regular Generar la expresión electrónicos válidos. Formato: 19 regular para identificar correos .M=(Q. F) – Q = conjunto de estados = alfabeto de entrada – & = funciones de transición – F = conjunto de estados de aceptación Autómatas finitos La característica que tienen los autómatas finitos es que solo existe una función de transición definida para un símbolo de entrada.

Autómatas.2 Analizador Léxico • Primera fase de la compilación • Leer caracteres de entrada y generar como salida una secuencia de componentes léxicos • Eliminar espacios en blanco • Eliminar comentarios • Proporcionar información acerca de errores léxicos 20 .mx id@dominio Expresiones Regulares y una gramática Una gramática sirve para generar cadenas de un determinado lenguaje pero también sirve para generarla. Gramática de un if prop _ if expr then prop | if expr then prop else prop |_ expr _ termino oprel termino | termino termino _ id | num oprel _ < |>|=|<=|<>|>=| id _ letra (letra | digito)* num _ digito+ (.edu. Existente una relación uno a uno entre Lenguajes. Expresiones regulares y gramáticas.jcolivar@itmorelia.digito+)?(E(+|-)?digito+)? eb _ delim+ delim _ blanco | tab | linenueva 3.

Reconocedores de identificadores y palabras clave. Los componentes léxicos se tratan como terminales de la gramática del lenguaje fuente. Cada patrón concuerda con una serie de cadenas. La devolución de un componente léxico se hace a través de un número entero. Posicion := inicial + velocidad * 60 Posicion: identificador := símbolo de asignación Inicial: identificador +: signo de suma Velocidad: identificador *: signo de multiplicación 60: numero Se elimina todos los espacios en blancos (espacios.Análisis Léxico El análisis lineal. Especificación de componentes léxicos Expresiones regulares (patrón). se llama léxico o exploración. Expresiones regulares 21 . Las expresiones regulares dan el nombre al conjunto de cadenas con que concuerdan. etc. La tabla de símbolo debe insertar y buscar componentes léxicos. tabuladores. salto de línea. La tabla de símbolos es utilizada por el analizador sintáctico y por otras fases del proceso de traducción Un patrón es una regla que describe el conjunto de lexemas que puede representar a un conjunto léxico.

cada expresión regular r. Para solucionar este problema se sugiere utilizar buffers Manejo de buffers Existen muchas formas de dividir el trabajo. • La forma más eficiente es realizar una copia a la memoria de todo el código fuente.Se construyen a partir de otras expresiones regulares más simples.4 Creación de tablas de símbolos 22 . representa un lenguaje L(r) • Letraaubucu…uz • Dígito1u2u3u…u0 • Identificador letra(letra u dígito)* Abreviaturas • * cero o más casos • + uno o más casos • [a-zA-Z] mayúsculas y minúsculas • [0-9] dígitos • ? Cero o un caso 3. uno al carácter actual y otro al inicial del lexema. pero siempre se deberá llevar dos punteros.3 Manejo de localidades temporales de memoria (buffers) • La forma más fácil de leer un programa es carácter por carácter pero es ineficiente. Pero esto en la gran mayoría de las ocasiones es impráctico por las dimensiones de los programas. El manejo de buffers es esencial para realizar el análisis de grandes programas de mejor manera 3.

5 Manejo de errores léxicos • Son pocos los errores que se pueden detectar al hacer análisis léxico • fi (a == f(x)) //Error de sintaxis • Pero puede existir algún error si ninguno de los patrones con cuerda con el prefijo de entrada Técnicas de recuperación de errores • Borrar un carácter extraño • Insertar un carácter que falta • Reemplazar un carácter incorrecto por otro correcto • Intercambiar dos caracteres adyacentes Técnicas para realizar analizadores léxicos 23 .En general el proceso de análisis léxico puede describirse simplemente como el reconocimiento de caracteres de un lenguaje para generar una tabla de símbolos. el cual se encarga de verificar que no existan caracteres no presentes en el lenguaje. la va identificar como un lexema y le va asociar un identificador numérico para posteriormente utilizarlo. 3. El primer paso consiste en crear un escáner. Tabla de símbolos La tabla de símbolos va a guardar cada palabra analizada. La tabla de símbolos debe estar en memoria para realizar un análisis rápido.

• Si el lenguaje no cumple con las reglas de construcción de documentos XML. falla el proceso.6 Generadores de código léxico: Lex y Flex FLEX es la versión de software libre del popular generador de analizadores léxicos LEX para sistemas *NIX.c –o analizador –lfl Programa Lex %{ Definiciones globales ‘C’ 24 .lex flex lex. El generador se encarga de manejar buffers • Escribir el analizador en un lenguaje de alto nivel haciendo uso de la E/S del lenguaje • Escribir el lenguaje ensamblador y manejar explícitamente la E/S Análisis Léxico en XML • El análisis léxico en documentos XML lo realiza cualquier herramienta o API que utilice XML.• Utilizar un analizador léxico como FLEX.c gcc Programa ejecutable analizador • $gcc lex.yy. ya que debemos cerciorarnos que el lenguaje esté bien formado.yy. • Realizar análisis léxico de XML en Java o C# 3. genera código C aunque existen otras herramientas que generan código en otros lenguajes • Analizador.

}% Definiciones flex %% Acciones %% Código ‘C’ auxiliar Definiciones regulares en flex %% Separadores de secciones Def Acciones {def} {código ‘C’ asociado} “@” {código ‘C’ asociado} Programa que reconoce flotantes % { #include <stdio.h> Int ocurrencias.] Exp [eE] Signo[\+\-] Digitos {digito}+ 25 expresión . }% Digito[0-9] Punto [\.

yytext). } Programa para reconocer direcciones IP Digito [0-9] Punto [\. ] 26 . printf(“%d flotantes encontrados\n”. fclose(f). } %% main(int argc. } “@” { printf(“Arroba\n”). yyin = f. ocurrencias). } .Decimal {punto} {digitos}({exp}{signo}{digitos})? Flotante {digitos}{decimal}? Programa que reconoce flotantes % % {flotante} { printf(“flotante encontrado\n”) ocurrenicas++. while(yylex()). “r”). char *argv[]) { FILE *f. { printf(“Inválido: %s\n”. F = fopen(argv[1].

”).IP {digito}+{punto}{digito}+{punto}+{digito} {punto}{digito}+ %% {IP} { strcpy(aux. break. i<4. for(i =0 . i++) { cadnum = strtok(aux. strcat(aux. if(atoi (cadnum)>255) { printf(“Error\n”). } if(i==4) printf(“Dirección IP: %s\n”. yytext). } 27 .”) . yytext). “. “.

Se define como la cuarteta G= (N. S es conjunto de símbolos terminales. . Reglas de producción • Son las reglas que permiten decidir si la cadena pertenece a un lenguaje y la estructura que lleva: •S A|aB •A aA|bC •S B C e e Genera cadenas del lenguaje a*b u a 28 . Un analizador sintáctico implementa estas reglas haciendo uso de GICs Gramáticas Son un formalismo matemático que permite decidir si una cadena pertenece a un lenguaje dado. Los símbolos no terminales (N) son aquellos que pueden seguir derivando en otros. S es el símbolo inicial (S pertenece a N) y P es un cojunto de reglas de producción. S. P). mientras que los terminales el proceso finaliza allí.1 Introducción a las Gramáticas libres de contexto y árboles de derivación Todo lenguaje posee una serie de reglas para describir los programas fuentes (sintaxis).Unidad IV Análisis Sintáctico 4. en donde N es el conjunto de símbolos terminales.

• Por medio de las GICs es fácil construir analizadores sintácticos • Es sencillo añadir funcionalidades a un analizador sintáctico GICs 29 . Gramáticas Independientes del Contexto Son aquellas G cuya reglas de producción son de la forma: . Gramáticas Regulares Son las que se forman a través de Autómatas Finitos Deterministas y Expresiones regulares. en donde a pertenece aNy ß pertenece (N u )* Las ventajas de uso de GICs son: •Proporcionan una estructura sintáctica precisa y fácil de comprender • Proporciona al lenguaje fuente una estructura adecuada para la generación del código. Desafortunadamente este tipo de gramáticas no permiten expresar todos los lenguajes posibles y en especial los humanos por lo que se necesitan otros tipos de gramáticas. No presentan ambiguedades. debido a que no presentan anomalías de ningún tipo.Tipos de gramáticas Las gramáticas más sencillas son las gramáticas regulares. Las más utilizadas en informáticas son las libres del contexto.

• Algunas formas de eliminar esa ambigüedad es utilizando técnicas como algoritmos CYK y las formas normales de Chomsky (FNCh) y Greibach (FNG). donde a y ß pertenecen a (u N)* salvo ) y las ramáticas del tipo 0 o sin restricciones. Ejemplos de GICs • Expresiones válidas en lenguajes C: Expr NUM • Error sintáctico: cuando la secuencia de componentes léxicos no puede ser generada por la gramática del lenguaje fuente.• Hay que revisar que la gramática no sea inherentemente ambigua para poder eliminar esa ambigüedad o rediseñar la gramática sin anomalías. Árboles de Derivación 30 . GIC tipo 2) son las gramáticas sensible al contexto (tipo 1. las cuales sus reglas de producción pueden ser de cualquier tipo. donde ||<||. (expr) | -expr | expr op expr| VAR | Jerarquía de Chomsky • Las otras dos gramáticas en las cuales clasificó Chomsky (GR tipo 3.

una sintaxis para representar sintaxis. Es un estándar para representar lenguajes. Si para la misma cadena existen dos o más árboles de derivación la gramática es ambigua. es decir.2 Diagramas de sintaxis 31 . A través de los árboles de derivación se puede verificar la sintaxis de un lenguaje así como comprobar el significado de las palabras. Se crea utilizando el símbolo inicial como la raíz. los símbolos N representan nodos del árbol y los símbolos S las hojas del árbol.Es la representación gráfica de la derivación de una cadena. • La barra vertical | para representar O • La doble flecha • ::= indica indica las derivaciones las producciones • [] indican elementos opcionales • {} indican términos repetitivos 4. Los paréntesis triangulares < y > sirven para indicar los símbolos no terminales. BNF La Forma Backus-Naur es una meta-sintaxis.

• En aritmética existen prioridades.• Es otra forma (al igual que los árboles de derivación) de especificar gramáticas del tipo 2.3 Precedencia de operadores • La precedencia de operadores es de vital importancia en el proceso de análisis sintáctico ya que nos representará la forma en que debe construirse el árbol de derivación. por ejemplo: * y / tienen preferencia sobre + y -. sino de la forma a = b + (c/2) 32 . • La característica de este esquema es que permite ver las derivaciones al instante de que ocurren. Prioridad de operadores • La instrucción a = b + c / 2 en la mayoría de los lenguajes no se evalúa de la forma a = (b + c) /2. () indican la máxima prioridad. <W>::=<W1> < W2> <W3> <W>::=ab <W> <W>::=< W1> < W2> | <W1>a | ab <W2> 4.

• La forma de evaluación depende de cómo se construyan los operadores. ya sea en infijo. 33 . • Las operaciones se realizan de abajo hacia arriba. postfijo o prefijo.

4. Los lenguajes habitualmente reconocidos por los analizadores sintácticos son los lenguajes libres de contexto.4. Los analizadores sintácticos de lenguajes de programación suele hacerse de izquierda a derecha.4 Analizador sintáctico Un analizador sintáctico (Parser) es un programa que reconoce si una o varias cadenas de caracteres forman parte de un determinado lenguaje. GNU bison y javacc. cosa que permitió la creación de programas generadores de analizadores sintácticos a partir de una especificación de la sintaxis del lenguaje.1 Analizador descendente (LL) 34 . Es el proceso de determinar si una cadena dada puede ser generada por una gramática. Los analizadores sintácticos fueron extensivamente estudiados durante los años 70 del siglo XX. tales y como YACC. viendo un componente léxico a la vez Los analizadores pueden clasificarse dependiendo de la forma en como se construyen los nodos del árbol de derivación sintáctico: ascendentes y descendentes Tipos de analizadores sintácticos • LL (left to left) leen la cadena de izquierda a derecha y derivan por la izquierda • LR (left to right) •S •A •B •C aA aBbC b c 4. detectándose numerosos patrones de funcionamiento en ellos.

5 Administración de tablas de símbolos La tabla de símbolos se crea durante la fase de análisis léxico a través de los componentes léxicos. 4. El analizador trata de reducir la cadena de entrada w al símbolo inicial S. La mayoría caen en una de dos categorías: ascendentes y descendentes. Generalmente se agregan valores de tipo y significado para el análisis sintáctico.2 Analizador ascendente (LR.4. Los descendentes lo hacen en modo inverso. Los ascendentes construyen el árbol desde las hojas hacia la raíz.Existen diferentes métodos de análisis sintáctico. 4. 4. LALR) Algunos problemas no se pueden resolver de forma descendente ya que no están fácil quitar la ambigüedad. Un analizador ampliamente utilizado se denomina método de análisis predictivo descendente recursivo que es muy sencillo.6 Manejo de errores sintácticos y su recuperación. Generalmente los analizadores sintácticos LR(k) son del tipo “bottom-up”. No sólo es necesaria una gramática que no presente ambigüedades sino que también tenga el valor de k más pequeño. En un proceso que recorre el árbol de derivación en sentido inverso que se llama reducción. En algunos casos es más fácil demostrar algo ya existente. pero en el proceso de análisis sintáctico sufren algunas modificaciones. Si los traductores tuvieran que procesar programas correctos el proceso de implantación se simplificaría mucho. 35 .

• Semánticos: como un operador aplicado a un operando incompatible. • Lógicos: como una llamada infinitamente recursiva • La mayoría de los errores se centra en la fase de análisis sintáctico. • El manejador de errores debe: Informar la presencia de errores con claridad y exactitud. • No debe retrasar de manera significativa procesamiento de programas correctos. • Sintácticos: como una expresión aritmética con paréntesis no equilibrados. • Debe indicar informativo la línea del error y algún el mensaje Estrategias de recuperación de errores 36 . Administrador de errores • Recuperar de cada error con la suficiente rapidez como para detectar errores posibles. palabra clave u operador.¿Cómo debe de responder un compilador de pascal a un código Fortran? Ningún método de recuperación de errores resuelve todos los problemas Tipos de errores • Léxicos: como escribir mal un identificador.

Estos caracteres son el punto y como (. } main( ) { int a.c. int a. } Recuperación a nivel de frase 37 .b. struct c { … .• Modo Pánico • Nivel de Frase • Producciones de error • Corrección global Recuperación en modo pánico Es el más sencillo de implantar. El analizador sintáctico desecha componentes léxicos hasta encontrar un carácter de sincronización.) entre otros.

La dificultad radica en el sentido de encontrar esas reglas gramaticales para generar error. El problema radica en que el implementar estas estrategias son muy costosas en tiempo y espacio. Son traductores que corrigen errores. 4. Producciones de error Se pueden generar gramáticas para generar producciones de error y así de esta forma seguir con el proceso. For (i<3. por . Bison YACC (YET ANOTHER COMPILERCOMPILER): provee una herramienta general para describir la entrada de un programa de computación. Esta técnica permite sustituir . etc. a<10.. eliminación o intercambio. sería recomendable que un traductor hiciera el mínimo de cambios para procesar una entrada inválida. Desafortunadamente para muchos casos no aplican por lo que no se utilizan demasiados. ya sea por inserción.7 Generadores de código para analizadores sintácticos: Yacc. junto con el código que será invocado en la medida en que cada una de esas estructuras es reconocida.Esta técnica utiliza una corrección de caracteres adyacentes. YACC/BISON 38 . En algunos casos sería inclusiva más extensa que la gramática del propio lenguaje. El usuario de YACC especifica las estructuras de su entrada. Este algoritmo genera menores costos globales para realizar cambios. i++) Corrección global Idealmente.

c”) analizador. • GNU Bison es un generador de parsers de propósito general que convierte una descripción gramatical desde una gramática libre de contexto LALR en un programa en C para hacer el parser. • La subrutina de entrada producida por YACC llama a la rutina provista por el usuario para devolver el próximo ítem básico de la entrada. • Cualquier persona que esté familiarizada con Yacc podría utilizar Bison sin problemas.yy. Es necesaria experiencia con C para utilizar Bison. YACC • Yet Another Compiler-Compiler • Analizador.c) gcc analizador • $gcc analizador. • GNU Bison tiene compatibilidad con Yacc: todas las gramáticas bien escritas para Yacc.• YACC convierte esa especificación en una subrutina que maneja el proceso de entrada.y (#include “lex. funcionan en Bison sin necesidad de ser modificadas.tab. • Es utilizado para crear parsers para muchos lenguajes.c –o analizador -lfl Estructura de un programa en Bison %{ Declaraciones globales C }% Declaraciones bison 39 bison .c (y. desde simples calculadoras hasta lenguajes complejos.

Gramática vacía Gramática: prod1| prod2| .%% Gramáticas Nombre:prod1|prod2|…|prodn.lex %{ #include “ytab.h” 40 . • Reduce/Reduce • Shift/Reduce •S •A •A •A A b a|b|c demasiada profundidad x|y|z S b ambigüedad infinita Analizador. %% Código auxiliar C Tips Todo lexema debe ser un entero #define VAR 200 (256) return (VAR).

%% Analizador.c” }% %token IF PI PD LLI LLD %token ID NUM OPREL OPLOG %% programa: linea programa | . Linea: if linea | .y %{ #include “lex.yy. } .} “(” {return (PI). return (ERROR). if: if PI condicion PD LLI campo LLD . 41 .}% sp [\n\r\t] If [i][f] %% {if} {return (IF).

lex $bison analizador.. “r”) .c –o analizador –lfl • yytext componente léxico • yyin flujo de entrada • yylineno línea de error %% 42 .} %% main(int argc. yyin = f.y $gcc analizador. } Bison $flex analizador. while (yyparse()) .: {printf(“Error sintáctico”). fclose(f) . char *argv[]) { FILE *f = fopen(argv[1].

1 Analizador semántico • Ajuste significativo • Comprobación de tipos: operandos-operadores • Comprobación del flujo de control: 43 . } Unidad V Análisis Semántico 5. yylineno).yyerror() { printf(“Error sintáctico en %d linea”.

44 . lógico • Nombres de tipo • Constructores de tipo: estructuras. real.. //una sola vez • Comprobación relacionadas con nombres • Tabla de símbolos: – Estructura en memoria – Almacena información sobre los tipos • Sistemas de tipo: • Tipo básico: entero. carácter. objetos • Apuntadores: referencias a tipos • Funciones a=suma(). w= a+2.for(. uniones. } Analizador semántico • Comprobación de unicidad • int a. • char a. ) { … break.

} 5.2 Verificación de tipos en expresiones • La verificación de los tipos de datos se hace asignando el valor de tipo de cada una de los componentes léxicos. • Estos valores se comparan para verificar que los tipos de datos coincidan y sean congruentes.• Sistema de tipos: conjunto de reglas que determinan el criterio para asignar expresiones de tipo a las diferentes partes del código fuente • Cada analizador semántico implementa un sistema de tipos • Comprobación dinámica y estática • Estática: compilación • Dinámica: Ejecución char a[5].3 Conversión de tipos 45 . tipo. 5. • Fuertemente tipificado • Débilmente tipificado Símbolo { nombre. de lo contrario no se pueden realizar los cálculos. ámbito. “abcdefghijk”) . strcpy(a.

Ejemplos: 46 . si el compilador reconoce que la variable destino tiene la suficiente precisión para contener el valor origen.• Hay situaciones en las cuales se tiene un valor de un tipo dado y se desea almacenar ese valor en una variable de un tipo diferente. dado que se estrecha explícitamente el valor para que quepa en el destino. (tipo) valor. dado que este tipo de datos es de mayor precisión que el primero. • En Java se puede almacenar un valor byte en una variable int. por ejemplo. Si por el contrario. dado que el tipo más pequeño se ensancha o promociona al tipo compatible más grande. Comprobación de tipos • Existen dos tipos de comprobación: estática y dinámica. • A esto se le llama estrechamiento. se desea asignar un valor de variable int a una variable byte se necesita realizar una conversión de tipos explícita. • En algunos tipos es posible almacenar simplemente el valor sin una conversión de tipos. • La comprobación ayuda a evitar la mayoría de los errores de programación. lo que se denomina conversión automática. • byte a. • Esto sólo es posible en algún lenguaje de programación. • La conversión de un tipo se realiza poniendo delante un nombre de tipo entre paréntesis. • En algunos casos se puede realizar la conversión pero se pueden perder datos. a=(byte) b. • A esto se le llama ensanchamiento o promoción. como por ejemplo al pasar un valor flotante a un entero. int b.

• El operador % ocupa que los dos operandos sean enteros. • + es una función suma(a. Las demás comprobaciones son rutinarias. Ejemplo: break. • Diferenciar el uso de +.b) que está sobrecargada para distintos tipos de datos • Siempre se diseñan reglas de tipos como los valores numéricos se convierten al de mayor jerarquía o el tipo de datos punteros sólo apunta al tipo de datos declarado. goto. • Comprobación relacionadas con nombres. Para saber si el operador aplicado a los operadores es correcto • Comprobación de flujo de control. * enteros que con punteros (aritmética de punteros) • Al conjunto de reglas que se definen para la comprobación de los tipos de datos se denomina sistema de tipos • La mayoría de veces la recuperación de errores se suele omitir ya que el programa no finaliza pero tal vez no obtenga los valores deseados 47 . • Algunos lenguajes revisan el tamaño de los arreglos (Java) de manera estática otros lo hacen de manera dinámica (en tiempo de ejecución). • Comprobación de unicidad: definir un objeto una sola vez. Variables que se declaran pero no utilizan Comprobación de tipos • La comprobación de tipos es la más complicada.• Comprobación de tipos. Se debe verificar que las instrucciones que cambia el flujo de un programa sean válidos. El mismo nombre debe aparecer dos veces.

• Un ejemplo de polimorfismo son las plantillas en algún lenguaje de programación.5 Pila semántica en un analizador sintáctico ascendente (bottom-up).4 Acciones agregadas descendente (top-down) en un analizador sintáctico Muchas de las actividades que realiza un analizador semántico no son estándares. • Se debe considerar el ámbito de las variables (locales y globales). dependerán del objetivo del lenguaje de programación.• Polimorfismo: una función puede tener el mismo nombre con diferentes elementos. su análisis como sistema y su codificación. 5. por ejemplo. • La Web es una base de datos en la mayoría de los casos sin sentidos por lo que la tercera generación de la Web será la llamada Web semántica. en algunas aplicaciones es interesante conocer que los datos estén en algún rango válido o que ciertos valores se utilicen para uso reservado Acciones agregadas a un analizador semántico • En algunas ocasiones nos interesa conocer el significado de las palabras de algún lenguaje dependiendo del contexto (gramáticas de tipo 1) para diferenciar palabras polisemánticas. El diseño ascendente se refiere a la identificación de aquellos procesos que necesitan computarizarse con forme vayan apareciendo. El tipo de datos debe ser diferente. 5. o 48 .

La tabla de símbolos se mantiene durante todo el proceso de traducción agregando elementos específicos en cada paso.amb=ambito.6 Administración de la tabla de símbolos La tabla de símbolos también recibe el nombre de ambiente.} • Var TIPO {tipo=obtengo(yytext()).} 49 . la adquisición de paquetes de software para satisfacer el problema inmediato. Un ambiente contiene un conjunto de parámetros que sólo son visibles en ese ambiente.} listavar var {inserta(símbolo). Pila semántica • Los problemas de integración entre los subsistemas son sumamente costosos y muchos de ellos no se solucionan hasta que la programación alcanza la fecha limite para la integración total del sistema.tipo=tipo. símbolo. Operaciones sobre la tabla de símbolos • Inserta(símbolo) • Existe(nombre) • Tipo(nombre) • Declaración PYC • Listavar {inserta(simbolo). • Se necesita una memoria auxiliar que nos permita guardar los datos intermedios para poder hacer la comparación.} | var ID {simbolo=yytext. simbolo.bien. 5.

Los demás errores ya son muy difíciles de detectar y generalmente se dan en tiempo de ejecución.} 5. • Else • A=ERROR_TIPO.} PD • |NOT exprlog {A=A.} OPLOG exprlog {A2=A • If(A1==INT && A2==INT) • A=INT. al tratar de obtener código existente de algunas funciones/métodos ya implementadas en bibliotecas/APIs.7 Manejo de errores semánticos Los errores semánticos son pocos y los que existen no se pueden detectar tan fácilmente.} • |exprlog {A1=A. 50 . Algunos problemas se presentan durante la fase de gestión de memoria al pasar argumentos o al crear la pila semántica. Muchos errores se generan durante la etapa del enlazador.• Exprlog PI exprlog {A=A. Hasta esta etapa los errores son mostrados a los usuarios.

Se debe considerar tanto la memoria estática como dinámica. La notación postfija es una manera linealizada de representar un árbol sintáctico. y en esta se utilizan generalmente pilas. Se puede representar un árbol sintáctico con un Grafo Dirigdo Acíclico (GDA). • a := b*-c+b*-c • abc -*bc -*+= • x:=yopz • x+y*z • t1:=y*z • t2:=x+t1 6.Unidad VI Generación de Código Intermedio La administración de la memoria se da en esta etapa.1 Lenguajes intermedios 51 . Los lenguajes intermedios generalmente tienen árboles de derivación más pequeños que su contraparte original.

también ocurre algo similar generándose un archivo . etc. la mayoría de ellos son una representación más simplificada del código original para facilitar la traducción hacia el código final. Las expresiones aritméticas se pueden expresar de tres formas distintas: infija. el 52 . prefija y postfija. En este caso estos lenguajes intermedios se encargan de enmascarar toda la heterogeneidad de las comunicaciones distribuidas en una computadora 6. y para la máquina virtual de .obj para que posteriormente el enlazador cree finalmente el código executable .out.exe En sistemas basados en Unix. se produce un código objeto con extensión .Los lenguajes intermedios nos sirven para representar la producción final de nuestro lenguaje fuente. La diversidad de notaciones corresponde en que para algunos casos es más sencillo un tipo de notación.o y el executable a. Las notaciones también dependen de cómo se recorrerá el árbol sintáctico. Otros lenguajes intermedios famosos son los generados para la máquina virtual de Java el bytecode. base o como Por ejemplo al compilar un programa en C en Windows o DOS. Existen muchos lenguajes intermedios. Otros lenguajes intermedios sirven de representación parcial de otros procesos. CORBA y su IDL. El uso más extendido de las notaciones sirve para expresar operaciones aritméticas.NET el MISL para luego ejecutarse en tiempo de ejecución JIT (Just in Time) Otros lenguajes intermedios se utilizan en sistemas distribuidos como RPC.2 Notaciones Las notaciones sirven de base para expresar sentencias bien definidas.

2. 6. la cual es la más utilizada para la implementación. por lo que la expresión queda: ab+5.cual puede ser en inorden. Por ejemplo a+b-5.La notación posftfija utiliza una estructura del tipo LIFO (Last In First Out) pila.2 Postfija La notación postfija pone el operador al final de los dos operandos.2. No existe una estructura simple para representar este tipo de notación en la computadora por esta razón se utilizan otras notaciones.3 Representación de código intermedio • Existen maneras intermedio. por lo que la expresión anterior queda: +ab-5. preorden o postorden.2.1 Infija La notación infija es la más utilizada por los humanos por que es la más comprensible ya que ponen el operador entre los dos operandos.1 Notación Polaca 53 . 6. Esto se representa con una estructura del tipo FIFO (First In First Out) o cola. 6.3. teniendo una relación de uno a uno con la notación de los operadores. • Las estructuras FIFO son ampliamente utilizadas pero tienen problemas con el anidamiento aritmético. 6.3 Prefija • La notación prefija pone el operador primero que los dos operandos. formales para representar código • Estas notaciones simplifican la traducción de nuestro código fuente a nuestro código objeto ya que ahorran y acotan símbolos de la tabla de símbolos 6.

y el álgebra. Para garantizar la portabilidad del código se necesita que el lenguaje este estandarizado por algún instituto y que dicho código no tenga extensiones particulares. switch. while. El problema de utilizar cuádruplos radica en que se tienen que colocar los valores temporales en la tabla de símbolo. 6. En muchos caso la P se asociado a código portable el cual garantiza que el código compilado en una máquina se pueda ejecutar en otras.2 Código P El código P hace referencia a máquinas que utilizan o se auxilian de pilas para generar código objeto. Las estructuras de control (if. También se recomienda la no utilización de carácterísticas especiales exclusivas de alguna arquitectura de computadoras en particular. y todavía puede ser analizada sin ambigüedad. El lógico polaco Jan Łukasiewicz inventó esta notación alrededor de 1920 para simplificar la lógica proposicional. for) son realmente etiquetas goto disfrazadas. arg1 y arg2 54 . es una forma de notación para la lógica.3. dicha estructura recibe el nombre de triples y tiene los siguientes campos: op. Si la aridad de los operadores es fija. do-while.3 Triplos Las proposiciones de tres direcciones se parece mucho al ensamblador. el resultado es una sintaxis que carece de paréntesis u otros signos de agrupación. Con una estructura de tres campos se pueden omitir los valores temporales.La notación polaca. 6. también conocida como notación de prefijo o notación prefija. el cual es un lenguaje intermedio más entendible para la máquina.3. la aritmética. Su característica distintiva es que coloca los operadores a la izquierda de sus operandos.

1 Intérpretes Los intérpretes generalmente utilizan este triplos para generar el código intermedio para ejecutarse una vez considerado la instrucción como válido.Generalmente el código que generan los triples recibe el nombre de código de dos direcciones. de declaración. Cuando se utilizan triples se ocupan punteros a la misma estructura de los triples. expresiones booleanas. En este sentido.3.4. en el caso del operador OR si se encuentra una condición verdadera todo será verdadera 6. para el operador AND con una condición que se detecte como falsa toda la expresión es falsa. La evaluación de expresiones en corto circuito implica que se evalúan condiciones revisando valores anteriores. Las expresiones lógicas también pueden pasarse a código de tres direcciones. utilizando para ello expresiones en corto circuito. • * b t1 t2 //cuádruplos • * b (0) //triple Se debe tener en cuenta el proceso de asignación. aunque en ocasiones puede variar. un compilador es más difícil de implementar ya que tendrá que mantener todas las estructuras generadas que en muchas ocasiones serán cuadrúplos. 55 . por ejemplo.

Los operadores unarios como x:=-y no utilizan arg2. arg2 y resultado. 6.c. arg1.3.4.4. respectivamente. intc. de tal forma que una expresión sea lo más mínimo posible.6.1 Expresiones Para generar expresiones estas deben representarse de manera más simple y más literal para que su conversión sea más rápida. int b. Generalmente arg1.b. 6.4 Esquemas de generación Los esquemas de generación son las estrategias o acciones que se deberán realizarse y tomarse en cuenta en el momento de generar código intermedio. 56 .2 Declaración de variables.3 Estatuto de asignación Las operaciones de asignación deben quedar expresadas por una expresión sencilla. Tomaremos algunos esquemas de generación del lenguaje C. si está es compleja se debe reducir hasta quedar un operador sencillo. constantes Las declaraciones de variables y constantes deben separarse de tal manera que queden las expresiones una por una de manera simple. 6. arg2 y resultado son valores de tipo puntero y apuntan a una entrada en la tabla de símbolos. OP tiene un código intermedio.4. 6. Por ejemplo int a. se descompone a int a. Los esquemas de generación dependen de cada lenguaje.4 Cuádruplos Es una estructura tipo registro con cuatros campos que se llaman: op. Por ejemplo la traducción de operaciones aritméticas debe especificarse una por una.

6. 6.6 Arreglos Los arreglos se descomponen en estructuras básicas de manejo de manera simple. debe quedar de la forma y = b/5.4. por lo que ciclos while. lo que se hace es expander el código original de la función. se reduce a: a[0]=‘H’. a[4]=‘\0’. Por ejemplo una instrucción como: if (a == b && f!=5 && f %3==0) se evalúa primero x = (a==b && f!=5) y = x && f %3==0. En el caso de C. for y dowhile tienen la misma representación interna. Las condiciones lógicas también pueden ser evaluadas en cortocircuito y reducidas.4 Estatuto condicional Las condiciones deben expresarse de manera lo más sencilla posible de tal forma que puedan evaluarse en cortocircuito. a[2]=‘l’. x=z. a[1]=‘o’.4.7 Funciones Las funciones pueden reducir a en línea. todo queda en forma de while. Las funciones se descomponen simplificando los parámetros de manera individual al igual que el valor de retorno. z = a+y.• Por ejemplo: x = a+b/5.4.5 Estatuto de ciclos Los ciclos se descomponen en un ciclo genérico. 6. if (y) • Las instrucciones de decisión compleja como switch se reducen a una versión complejas de if’s 6. a[3]=‘a’. así por ejemplo: char *a=“Hola”. 57 .4.

Unidad VII Optimización 7. Las optimizaciones se realizan en base al alcance ofrecido por el compilador. procesador. Algunos editores ofrecen una versión de depuración y otra de entrega o final. espacio. entre más optimización mayor tiempo de compilación. Tipos de optimización Como el tiempo de optimización es gran consumidor de tiempo (dado que tiene que recorrer todo el árbol de posibles soluciones para el proceso de optimización) la optimización se deja hasta la fase de prueba final. La optimización es un proceso que tiene a minimizar o maximizar alguna variable de rendimiento. es decir. La optimización se realiza reestructurando el código de tal forma que el nuevo código generado tenga mayores beneficios.1 Tipos de optimización Las optimizaciones pueden realizarse de diferentes formas. La mayoría de los compiladores tienen una 58 . La optimización va a depender del lenguaje de programación y es directamente proporcional al tiempo de compilación. generalmente tiempo. etc. Desafortunamente no existen optimizador que hagan un programa más rápido y que ocupe menor espacio.

la concurrencia. 7. y si dichas acciones están mal realizadas. métodos.1. Ciclos while(a == b) { intc=a. La mayoría de las optimizaciones sobre ciclos tratan de encontrar elementos que no deben repetirse en un ciclo. En la mayoría de las ocasiones a través de funciones.…. La optimización local sirve cuando un bloque de programa o sección es crítico por ejemplo: la E/S.2 Bucles Los ciclos son una de las partes más esenciales en el rendimiento de un programa dado que realizan acciones repetitivas. se necesita de compiladores especiales para realmente optimizar el código. Como el espacio de soluciones optimización local es más rápida 7. } es más pequeño la 59 . c=5. La característica de las optimizaciones locales es que sólo se ven reflejados en dichas secciones. la rapidez y confiabilidad de un conjunto de instrucciones. procedimientos.optimización baja. etc. el problema se hace N veces más grandes. clases.1.1 Locales La optimización local se realiza sobre módulos del programa.

En algunos casos es mejor mantener variables globales para agilizar los procesos (el proceso de declarar variables y eliminarlas toma su tiempo) pero consume más memoria.2 Costos Los costos son el factor más importante a tomar en cuenta a la hora de optimizar ya que en ocasiones la mejora obtenida puede verse no reflejada en el programa final pero si ser perjudicial para el equipo de desarrollo. E/S. sobre todo en instrucciones de bifurcación como son las decisiones. El problema de la optimización en ciclos y en general radica es que muy difícil saber el uso exacto de algunas instrucciones. Este tipo de optimización es más lenta pero mejora el desempeño general de todo programa. Las optimizaciones globales pueden depender de la arquitectura de la máquina.En este caso es mejor pasar el int c =a.1.3 Globales La optimización global se da con respecto a todo el código. Así que no todo código de proceso puede ser optimizado. fuera del ciclo de ser posible.) 7. siendo el salto lo más pequeño posible 7.4 De mirilla La optimización de mirilla trata de estructurar de manera eficiente el flujo del programa.1. utilizar instrucciones en ensamblador. Algunas optimizaciones incluyen utilizar como variables registros del CPU. La idea es tener los saltos lo más cerca de las llamadas. 7. ciclos y saltos de rutinas. Otros uso de la optimización pueden ser el mejoramiento de consultas en SQL o en aplicaciones remotas (sockets. La optimización de una pequeña mejora tal vez tenga una pequeña ganancia en 60 . etc.

Pero en cambio si esa optimización se hace por ejemplo en un ciclo. Otro tipo de aplicaciones que deben optimizarse son las aplicaciones para dispositivos móviles. el mejor uso de memoria y otros recursos de hardware tiene mayor rendimiento. la mejora obtenida puede ser N veces mayor por lo cual el costo se minimiza y es benéfico la mejora. i++).1 Costo de ejecución. Por ejemplo: for(int i=0.g. por lo que el espacio y la velocidad del microprocesadores son elementos que se deben optimizar para tener un mercado potencial más amplio.tiempo o en espacio pero sale muy costosa en tiempo en generarla. Costos de ejecución Las aplicaciones multimedias como los videojuegos tienen un costo de ejecución alto por lo cual la optimización de su desempeño es crítico. En algunos programas se tiene un mínimo para ejecutar el programa.2. tarjetas de video) o de mucha memoria.2 Criterios para mejorar el código 61 . si la ganancia es de 30 ms 300s 7.2. la gran mayoría de las veces requieren de procesadores rápidos (e. Los costos de ejecución son aquellos que vienen implícitos al ejecutar el programa. 7. En algunos casos es preferible tener la lógica del negocio más fuerte en otros dispositivos y hacer uso de arquitecturas descentralizadas como cliente/servidor o P2P. Los dispositivos móviles tiene recursos más limitados que un dispositivo de cómputo convencional razón por la cual. i < 10000.

1 Lenguaje máquina El lenguaje máquina sólo es entendible por las computadoras.1. La optimización al igual que la programación es un arte y no se ha podido sistematizar del todo.3 Herramientas para el análisis del flujo de datos Existen algunas herramientas que permiten el análisis de los flujos de datos. Unidad VIII Generación de código intermedio 8. Se basa en una lógica binaria de 0 y 1.2. Los criterios de optimización siempre están definidos por el compilador. Criterios de optimización Muchos de estos criterios pueden modificarse con directivas del compilador desde el código o de manera externa. generalmente implementada por mecanismos eléctricos. En general el lenguaje máquina es difícil de entender para los humanos por este motivo hacemos uso de lenguajes más parecidos a los lenguajes naturales. entre ellas tenemos los depuradores y desambladores.La mejor manera de optimizar el código es hacer ver a los programadores que optimicen su código desde el inicio. 8. el problema radica en que el costo podría ser muy grande ya que tendría que codificar más y/o hacer su código más legible. 7.1 Características 62 . Este proceso lo realizan algunas herramientas del sistema como los ofuscadores para código móvil y código para dispositivos móviles.

repetitiva) El lenguaje máquina es dependiente del tipo de arquitectura. ejecutable directamente por la máquina para la que se ha generado.1. Fue la primera abstracción de un lenguaje de programación. posteriormente aparecieron los compiladores.2 Lenguaje ensamblador El ensamblador (del inglés assembler) es un traductor de un código de bajo nivel a un código. Recordar que un programa no puede ejecutarse sino se encuentra en memoria principal. pero en general existen dos tipos de direccionamiento: directo e indirecto. La forma de acceder a la memoria depende del microprocesador. NOT) y de control (secuencial. sólo realizan operaciones del tipo aritmética (+. OR. /). pero son más lentos que los RISC ya que estos tienen registros más grandes. 8. El direccionamiento directo también recibe el nombre de direccionamiento absoluto y el acceso a las direcciones se hace de manera directa. decisión.2 Direccionamiento Es la forma en como se accede a la memoria.1 Características 63 .-. 8. Así un programa máquina para una arquitectura intel x86 no se ejecutará en una arquitectura Power PC de IBM (al menos de manera nativa). 8.El lenguaje máquina realiza un conjunto de operaciones predeterminadas llamadas micro operaciones. generalmente el inicio del programa.*. Algunos microprocesadores implementan más funcionalidades llamado CISC. lógicas (AND.2. El direccionamiento indirecto también recibe el nombre de direccionamiento relativo y se basa a partir de una dirección genérica.

Descendientes de los ensambladores básicos. las bifurcaciones y el paso de parámetros. Clasificación ensambladores Ensambladores básicos. Un macroinstrucción es el equivalente a una función en un lenguaje de alto nivel. 64 . Además nos permite acceder directamente a los recursos de la máquina para un mejor desempeño. parámetros y cosas tales como los modos de direccionamiento.3 Registros Los registros son la memoria principal de la computadora. fueron muy populares en las décadas de los 50 y los 60. 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. 8.2. antes de la generalización de los lenguajes de alto nivel.2 Almacenamiento Una de las principales ventajas del uso del ensamblador. Son de muy bajo nivel. y su tarea consiste básicamente en ofrecer nombres simbólicos a las distintas instrucciones. o macro ensambladores. Existen diversos registros de propósito general y otros de uso exclusivo. es que se encarga de administrar de manera transparente para el usuario la creación de memoria. 8. Ensambladores modulares.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. Algunos registros de propósito general son utilizados para cierto tipo de funciones.

etc. Con respecto al ensamblador.1 Distribución La distribución es el proceso en el que el programa generado puede ejecutarse en otras máquinas. 8. pero nunca de memoria a memoria. si son estáticas se incluyen en el ejecutable por lo que el programa se hace gráfico. puntero de instrucción.Existen registros acumuladores. o de registro a memoria. la mayoría del direccionamiento se hace relativo para que el programa sea relocalizable por un programa llamado cargador En el caso de programas compilados se necesitan de las librerías. Cuando se trata de memoria dinámica se debe seguir el rastro de los datos 65 .2 Asignación La asignación de valores a variables se hace a través de un proceso de mover el contenido de memoria a registro.3. 8. de pila.3. si son dinámicas no pero el programa es más pequeño.

de tal modo que su mal o buen uso tiene una acción directa sobre el desempeño de memoria. • Los lenguajes más recientes controlan el uso de punteros y tienen un programa denominado recolector de basura que se encarga de limpiar la memoria no utilizada mejorando el desempeño. 66 .8. En general un ensamblador tiene un administrador de memoria más limitado que un compilador. Administración de memoria En la mayoría de los lenguajes de programación el uso de punteros no estaba vigilado por lo que se tienen muchos problemas con el uso de memoria.4 Administración de memoria La administración de la memoria es un proceso hoy en día muy importante.

pdf 67 .BIBLIOGRAFIA www.mx/~jcolivar/courses/ps207a/ps2_u1.com/Main/ProgramacionDeSistemas www.edu.mx/.ith.pdf antares...mitecnologico.itmorelia.sistemas./Programacion%20de%20sistemas_ISC.

Sign up to vote on this title
UsefulNot useful