martes, 31 de mayo de 2016

EJEMPLOS DE COMPILACION DE CODIGO ENSAMBLADOR USANDO TASM Y TLINK

EJEMPLOS DE COMPILACIÓN DE CÓDIGO ENSAMBLADOR USANDO TASM Y TLINK

Antes de iniciar la realización de cualquier programa en Lenguaje Ensamblador debemos conocer algunos conceptos básicos. En este caso es primordial el software que utilizaremos para todo el proceso de realización de dichos programas. 

TASM.

El Turbo Assembler (TASM), un paquete ensamblador principalmente destinado a la plataforma del IBM PC y sus compatibles. Fue la oferta de Borland en el mercado de herramientas de programación en lenguaje ensamblador para la familia de los microprocesadoresx86.   

Turbo Assembler también se refiere a un ensamblador común, basado en el microprocesador 6502 para el Commodore 64, creado por la compañía alemana Omikron en 1985. 

TLINK.

El enlazador o linkador permite combinar varios módulos objeto, realizando las conexiones entre ellos y, finalmente, los convierte en módulo ejecutable de tipo EXE (empleando el ML de MASM 6.X se obtiene directamente el fichero EXE ya que invoca automáticamente al linkador). El linkador permite el uso de librerías de funciones y rutinas. TLINK, a diferencia de LINK, permite generar un fichero de tipo COM directamente de un OBJ si se indica el parámetro /t, lo que agiliza aún más el proceso. Puede obtenerse ayuda ejecutándolo sin parámetros. Los parámetros de TLINK son sensibles a mayúsculas y minúsculas, por lo que /T no es lo mismo que /t.   

Un enlazador (en inglés, linker) es un programa que toma los ficheros de código objeto generado en los primeros pasos del proceso de compilación, la información de todos los recursos necesarios (biblioteca), quita aquellos recursos que no necesita, y enlaza el código objeto con su(s)biblioteca con lo que finalmente produce un fichero ejecutable o una biblioteca.. En el caso de los programas enlazados dinámicamente, el enlace entre el programa ejecutable y las bibliotecas se realiza en tiempo de carga o ejecución del programa. 

EDITOR DE TEXTO PARA EL CÓDIGO FUENTE. 

Un editor de texto es un programa que permite crear y modificar archivos digitales compuestos únicamente por texto sin formato, conocidos comúnmente como archivos de texto ó texto plano. Se utiliza para escribir el código fuente de los programas considerando que al guardarse no conserve la extencion txt, ya que debe cambiarse por la extensión asm. En el caso de Windows se usa el Block de Notas de Microsoft, en linus podemos usar gedit o nano.   

PROCESO DE COMPILACIÓN CON TASM Y TLINK  

Para iniciar la compilación de los programas de ejemplo, debemos copiar los dos archivos ejecutables TASM.EXE y TLINK.EXE.

Con los archivos de código fuente y los ejecutables al iniciar el proceso de compilación, vamos al directorio y ejecutamos el comando que corresponda. 


CODIGOS DE EJEMPLO, COMPILADO Y LINKADO 


Creamos el primer ejemplo llamado saludo.asm 
  1. Entramos al símbolo del sistema (MS-DOS) nos direccionamos en donde se encuentra nuestra carpeta   
  2. Una vez situados en la dirección correcta, nos dirigimos a compilar nuestro programa.  
  3.  Para la compilación se debe ejecutar la siguiente instrucción:   tasm /zi saludo.asm  
  4. Una vez compilado nos aparecerá un reporte, el cual nos muestra si hay errores en nuestras líneas de código.   

Con esto se ah realizado la compilación de nuestro programa y está listo para ser ligado. Para linkar el programa. Esto lo haremos con la siguiente instrucción.   
tlink /v saludo 


El último paso es la ejecución del programa. Solo escribimos el nombre del programa, sin extensiones.   
Saludo   



Al ejecutarlo podemos comprobar que no se realiza acción alguna y que genera ciertos mensajes de advertencia, es porque el programa solo tiene la estructura básica y no estamos indicando que realice una acción determinada. 

Los caracteres especiales /v y /z tiene la siguiente finalidad. 







Lenguaje Ensamblador.

Lenguaje Ensamblador.

El término ensamblador (del inglés assembler) se refiere a un tipo de programa informático que se encarga de traducir un fichero fuente escrito en un lenguaje ensamblador, a un fichero objeto que contiene código máquina, ejecutable directamente por la máquina para la que se ha generado. 

El propósito para el que se crearon este tipo de aplicaciones es la de facilitar la escritura de programas, ya que escribir directamente en código binario, que es el único código entendible por la computadora, es en la práctica imposible. 

La evolución de los lenguajes de programación a partir del lenguaje ensamblador originó también la evolución de este programa ensamblador hacia lo que se conoce como programa compilador.

Historia.

El primer compilador fue escrito por Grace Hopper, en 1952 para el lenguaje de programación A-0. 

En 1950 John Backus dirigió una investigación en IBM sobre un lenguaje algebraico. 

En 1954 se empezó a desarrollar un lenguaje que permitía escribir fórmulas matemáticas de manera traducible por un ordenador; le llamaron FORTRAN (FORmulae TRANslator). 

Fue el primer lenguaje de alto nivel y se introdujo en 1957 para el uso de la computadora IBM modelo 704.

El primer compilador de FORTRAN tardó 18 años persona en realizarse y era muy sencillo.

El primer compilador autocontenido, es decir, capaz de compilar su propio código fuente fue el creado para Lisp por Hart y Levin en el MIT en 1962. Desde 1970 se ha convertido en una práctica común escribir el compilador en el mismo lenguaje que este compila, aunque Pascal y C han sido alternativas muy usadas.
Crear un compilador autocontenido genera un problema llamado bootstrapping, es decir el primer compilador creado para un lenguaje tiene que o bien ser compilado por un compilador escrito en otro lenguaje o bien compilado al ejecutar el compilador en un intérprete.

Componentes.

Los elementos básicos del lenguaje ensamblador son:
  • Etiquetas
  • Instrucciones
  • Operandos
  • Directivas
  • Comentarios

Etiquetas.

Una etiqueta es una palabra utilizada para designar alguna línea o sección del programa, se pueden utilizar para saltar de una parte hacia esa etiqueta.

Es importante que las etiquetas empiecen con una letra o con un guión bajo "_". La longitud de una etiqueta puede ser de hasta 32 caracteres y como ya se dijo se deben escribir en la primer columna.

Instrucciones.

Las instrucciones son las operaciones  que realiza el microcontrolador, así que estas ya están definidas para cada familia de  PIC.

MicrocontroladorPIC 

Los PIC son una familia de microcontroladores tipo RISC fabricados por Microchip Technology Inc. y derivados del PIC1650, originalmente desarrollado por la división de microelectrónica de General Instrument. El nombre actual no es un acrónimo. En realidad, el nombre completo es PICmicro, aunque generalmente se utiliza como Peripheral Interface Controller (controlador de interfaz periférico).




Operandos.

Son los elementos que emplea la instrucción que se está ejecutando. Usualmente los operandos son los registros, las variables o las constantes.

Directivas.

  • Las directivas son similares a las instrucciones, pero a diferencia de  estas las directivas son propias del lenguaje ensamblador e independientes del microcontrolador que se utilice. 
  • Las directivas representan algunas características del lenguaje ensamblador, se utilizan para especificar el procesador empleado así como la configuración de este, también para asignar locaciones de memoria.

Comentarios.

Los comentarios son las palabras, frases y oraciones que se pueden escribir en el código para hacer el programa más claro y legible, o solo para recordar. 

Los comentarios se pueden escribir en cualquier parte del código pero siempre deben empezar con punto y coma ";".

Software editores.

Un programador escribe el programa origen en  lenguaje ensamblador utilizando cualquier editor de textos o procesador de palabras que sea capaz de  producir una salida de texto en ASCII. Una vez que el código origen ha sido escrito, el archivo origen es  ensamblado mediante su procesamiento a través de algún ensamblador.

Software reglas de programación.

Para la programación se utiliza una cierta tabulación que se debe respetar, además utilizar una tabulación adecuada hace los programas más claros y le gibles. 

Las etiquetas 

Se escriben en la primer columna de cualquier línea, las instrucciones y directivas en la  segunda y por último, en la tercer columna, los operandos. 

Los comentarios 

Se pueden escribir en cualquier parte del programa.

Software ENS2001


Software MASM



Software TAST





Software MASM Y TLINK

El Turbo Assembler (TASM) un paquete ensamblador principalmente destinado a la plataforma del IBM PC y sus compatibles. 

El enlazador o linkador LINK permite convertir el código objeto generado por TASM en archivo ejecutable de tipo EXE*.

*empleando el ML de MASM 6.X se obtiene directamente el fichero EXE ya que invoca automáticamente al linkador.

Registros.

Se trata de una serie de "variables", que contienen información que puede ser cambiada.

REGISTROS IP Y CS.

El registro CS es una variable de un tamaño de dos bytes. Contiene el Segmento actual en que se encuentra el programa.


El registro IP es la variable, de dos bytes también, que contiene el Offset actual. Esto significa, el ordenador va interpretando las secuencias de bytes, pero necesita "algo" que le indique donde tiene que leer.

COMBINACION DE REGISTROS IP Y CS

La combinación CS:IP contiene la dirección en la que el ordenador está interpretando información en el momento. Indica la dirección de la próxima instrucción que se va a ejecutar.


El registro DS y el registro ES también sirven para guardar direcciones de Segmentos, y también son variables de dos bytes, pueden ser utilizados para por ejemplo mover datos en memoria, imprimir cadenas, etc. Son "punteros", que apuntan a cierta zona de memoria. El registro SS apunta a la pila, y el SP es el que contiene el offset de la pila.

Instrucciones.

Se pueden clasificar en los siguientes grupos:


  • De Transferencia. 
  • Aritméticos. 
  • Lógicos. 
  • De salto.
















Análisis Semántico

Análisis Semántico.

¿Que es la semántica?

Se refiere a los aspectos del significado, sentido o interpretación del significado de un determinado elemento, símbolo, palabra, expresión o representación formal.



Se trata de determinar el tipo de los resultados intermedios, comprobar que los argumentos que tiene un operador pertenecen al conjunto de los operadores posibles, y si son compatibles entre sí, etc. En definitiva, comprobará que el significado de lo que se va leyendo es válido.

El análisis semántico se realiza posteriormente al sintáctico y mucho más difícil de formalizar que éste.

La salida “teórica” de la fase de análisis semántico sería un árbol semántico.

¿Que es un árbol semántico?

Es una estructura jerárquica en la cual se registran las operaciones que implica u operan dentro del programa fuente.

En cada una de las ramas del  árbol semántico se registra el valor o significado que este debe tener, y el análisis semántico se encarga de terminar cual de los valores registrados en las ramas es aplicable.

Tabla de símbolos en esta fase.

Un compilador necesita guardar y usar la información de los objetos que se va encontrando en el texto fuente, como variables, etiquetas, declaraciones de tipos, etc.

Esta información se almacena en una estructura de datos interna conocida como tabla de símbolos.

El compilador debe desarrollar una serie de funciones relativas a la manipulación de esta tabla como consultar un elemento en ella, y consultar la información relacionada con un símbolo, etc.

Como se tiene que acceder mucho a la tabla de símbolos los accesos deben ser lo más rápidos posible para que la compilación sea eficiente.

Sistemas de tipo:

Es el conjunto de reglas que determinan el criterio para asignar expresiones de tipo a las diferentes partes del código fuente.
  • Tipo básico: entero, carácter, real, lógico 
  • Nombres de tipo 
  • Constructores de tipo: estructuras, uniones, objetos 
  • Apuntadores: referencias a tipos ◦ Funciones a=suma();
Chequeos de tipos (y otros)

Un compilador debe realizar una serie de chequeos estáticos, como chequeos de tipos:
  • Consistencia: unicidad, existencia, no-ciclicidad, ... 
  • Equivalencia y compatibilidad de tipos 
  • Inferencia de tipos (en valores) 
  • Sobrecarga de funciones y operadores
COMPROBACIONES SEMÁNTICAS TIPOS

Comprobaciones ESTÁTICAS. 
  • Las comprobaciones sintácticas y semánticas. 
Comprobaciones DINÁMICAS. 
  • Realizadas en tiempo de ejecución.
COMPROBACIONES SEMÁNTICAS TIPOS

Comprobaciones SEMÁNTICAS
 
De TIPO.
Verificación del tipo de los operando en las expresiones.

De FLUJO de CONTROL.

Verifica los puntos del programa de salida y entrada del control.


COMPROBACIONES SEMÁNTICAS


De UNICIDAD. 

Verifica la presencia de símbolos de forma única. (ejemplo: declarar un símbolo una sólo vez).

 Relación de NOMBRES. 

Un mismo nombre puede aparecer más de una vez.

Análisis Sintáctico.

Análisis Sintáctico.


  •  Determina  la  sintaxis,  o  estructura  de  un programa.
  •  Es un análisis a nivel de sentencias, y es mucho más complejo que el análisis léxico.
  •  Su función es tomar  el  programa  fuente  en  forma  de  tokens,  que  recibe  del analizador  léxico,  y  determinar  la  estructura  de  las sentencias del programa.
  •  Este proceso es similar a determinar la estructura de una frase

La tarea del AS es determinar la estructura sintáctica de un programa a partir de los tokens producidos por el AL. 
En resumen una función que toma como entrada la secuencia de tokens y salida el AS.

Secuencia de tokens <> árbol sintáctico

El árbol se define como estructura de datos dinámica, nodos, atributos, campos del atributo.
Manejo de errores, no solo mostrar mensaje sino recuperarse (inferir código corregido) y continuar el análisis, para encontrar tantos errores como sea posible.

Al proceso de reconocer la estructura del lenguaje fuente se conoce con el nombre de análisis sintáctico (parsing). 
 
Hay distintas clases de analizadores o reconocedores sintácticos, pero en general se clasifican en 2 grandes grupos: 
 
A.S. Ascendentes y A.S. Descendentes.

Tipos de Análisis Sintácticos

Análisis descendente: 
Partimos de la raíz del árbol (donde estará situado el símbolo inicial de la gramática) y se van aplicando reglas por la izquierda de forma que se obtiene una derivación por la izquierda de la cadena de entrada. 

Para decidir qué regla aplicar, se lee un token de la entrada.

Análisis ascendente: 
Partiendo de la cadena de entrada, se construye el árbol de análisis sintáctico empezando por las hojas (donde están los tokens) y se van creando nodos intermedios hasta llegar a la raíz (hasta el símbolo inicial), construyendo así el árbol de abajo a arriba. 

El recorrido del árbol se hará desde las hojas hasta la raíz.

La principal tarea del analizador sintáctico no es comprobar que la sintaxis del programa fuente sea correcta, sino construir una representación interna de ese programa y en el caso en que sea un programa incorrecto, dar un mensaje de error.

Función principal

Comprueba que el orden en que el analizador léxico le va entregando los tokens es válido. Si esto es así significará que la sucesión de símbolos que representan dichos tokens puede ser generada por la gramática correspondiente al lenguaje del código fuente.




Análisis Léxico.

Análisis Léxico y Díagramas de Transición.

  • Está constituido por todas las palabras y símbolos que lo componen. Para un lenguaje de programación la definición también es válida.
  • Lo constituyen todos los elementos individuales del lenguaje, denominados frecuentemente en inglés tokens.
¿Que es Token?

Son palabras reservadas del lenguaje, los símbolos que denotan los distintos tipos de operadores, identificadores (de variables, de funciones, de procedimientos, de tipos, etc.), separadores de sentencias y otros.

¿Que es Patrón?

  • Expresión regular que define el lenguaje.
  • Letra (Letra | Dígito)*
¿Que es Lexema?

  • Secuencia de caracteres que concuerda con un patrón.
  • Numero, carácter.

¿Que son Atributos?
  • Estructura de datos de cada token para almacenarse en la TS.
  • Depende del tipo de token.
  • [ID. Lexema, Tipo, Valor, Línea]

Un programa fuente es una serie de símbolos que representan las construcciones del lenguaje tales como variables, etiquetas, palabras reservadas, constantes, operadores, entre otros.

El programa fuente se trata inicialmente con el analizador léxico.

 Pasos del AL.

  • Identificar la colección de tokens.
  • Estructurar la colección de tokens.
  • Describir el lenguaje como expresiones regulares.



El análisis léxico es un análisis a nivel de caracteres, su misión es reconocer los componentes léxicos o tokens, enviando al analizador sintáctico.

Analizador léxico que reconozca los siguientes elementos: 
  • Números enteros 
  • Operadores aritméticos suma, resta, producto, división, incremento y decremento (+, - *, /, ++,--) 
  • Identificadores 
  •  WHILE
Especificación formal 
  1. Gramáticas Lineales:  Recursivas a izquierdas y Recursivas a derechas 
  2. Expresiones regulares .
  3. Autómatas Finitos (Diagramas de Transición).
  4. Tratar con la tabla de símbolos 
  5.  Generar tokens bajo demanda del analizador sintáctico 
  6.  Manejar el fichero fuente 
  7. Ignorar comentarios 
  8. Contabilizar posición de tokens 
  9. Preprocesar macros, constantes, includes…


lunes, 30 de mayo de 2016

Tabla de Simbolos

 Tabla de Símbolos.

Almacena todos los nombres declarados en el programa y sus atributos (tipo, valor, dirección, parámetros, etc).

Se usa en las distintas fases del compilador.

Estructura de datos.

Almacena información sobre:
  • Los identificadores.
  • Las palabras reservadas.
  • Las constantes.
Contiene una entrada para cada uno de los símbolos definidos en el programa fuente.

Sobre los identificadores, y opcionalmente sobre las palabras reservadas y las constantes.

Información sobre el lexema, tipo de datos, ámbito y dirección en memoria.

Por cada entrada en la tabla de símbolos habrá que guardar:
  • Lexema correspondiente.
  • Tipo.(depende de la implementación).
  • Ámbito.(depende de la implementación).
  • Dirección de memoria asignada.
  • Forma.(depende de la implementación).
¿Utilidad de la tabla de símbolos?

  • Analizador Léxico: Pasa en el token y la entrada de la TS creada.
  • Analizador Sintáctico y Semántico: busca el token y si no la encuentra crea una nueva entrada.

Datos que se almacenan:
Para un array:
  • Tipo de los elementos.
  • Número de elementos.
  • Limites inferior y superior.
Para una función:
  • Número de parámetros.
  • Tipo de los parámetros.
  • Forma de paso de parámetros.
  • Tipo de retorno.
Operaciones Principales.
  • Insertar: introduce un símbolo tras una declaración.
  • Buscar: recupera información asociada a un símbolo.
  • Eliminar: borra la información.
Ejemplo de Uso I.

Declaración previa al uso de variables:
  • En las declaraciones, inserción en la TS.
Aparición de una variable en una sentencia, búsqueda en la TS:
  • Si se encuentra Fue declarada.
  • Si no se encuentra Error de compilación.
Ejemplos de Uso II.

Acceso a una posición de un array:
  • Declaración > Inserción en la TS.
  • Acceso a un array > Búsqueda en la TS.
  1. Comprobación de tipo array.
  2. Comprobación acceso a una posición válida.
Tabla de Símbolos.


Ejemplo:



  • Analizador Lexicográfico: Inserta en TS cada id que detecta y si corresponde da error si ya existe.
  • Analizador Sintáctico: Inserta el tipo de id.
  • Analizador Semántico: Verifica que cada id sea declarado antes de usarlo y recupera el tipo de id.
  • Generación de Código Intermedio: recupera tipo y dirección del id.
  • Generación de Código: Inserta y recupera información sobre la memoria asignada.
Estructuras usadas para implementar una tabla de símbolos.
Lista
  1. Simple de implementar.
  2. Lenta cuando se trabaja con muchos identificadores.
Árbol
  1. Rápida.
  2. Consume más memoria.
  3. Es útil cuando hay muchas declaraciones.
Tabla de Hashing

  1. Rápida.
  2. Difícil de implementar.
  3. Se debe definir una función de hashing apropiada para evitar colisiones.

Operaciones sobre TS.
  • Búsqueda (lexema): entero;
  • Inserción (lexema, descriptor): boolean;
  • Obt_atributo (lexema, atributo): valor;
  • Eliminación (lexema): entero.
Manejo de palabra

Si el scanner diferencia entre un identificador y una palabra reservada, entonces devuelve al parser el código correspondiente. Aquí no se requiere el ingreso de la palabra clave en la TS.

Si el scanner no las diferencia de los identificadores:

  • Pueden almacenarse en una tabla separada.
  • Estar inicializadas al principio de la TS.
  • Una entrada, en TS para una palabra reservada.
Entrada en la TS.

Una primera desagregación de una entrada de la tabla de símbolos.

No todos los atributos se introducen a la vez, estos se completan conforme avanzan las etapas de compilación.

Parte Fija.


Parte Variante.

  • Depende del objeto computacional asociado con el identificador.
  • Variable Simple: la parte variante es vacía excepto cuando se admitan valores de inicialización.
  • Variable Estructurada (Arreglo).





Procedimiento o Función.


Operaciones sobre TS: Lenguajes estructurados a bloques.

Crean un ámbito, una visibilidad y un tiempo de vida para los identificadores.


Tareas que se deben realizar cuando se ingresa a un nuevo bloque:
  • Dar de alta un nuevo bloque.
  • Insertar cada identificador encontrado en dicho bloque.

Tareas realizadas cuando se finaliza el análisis de un bloque:
  • Eliminar cada identificador en el bloque.
  • Eliminar el bloque.
Operaciones sobre TS: Lenguajes Estructurados a Bloques.

Cuando se busque un identificador en la TS se debe retornar el último identificador insertado, es decir, el identificador declarado en el bloque actual, si en tal bloque no existe el identificador buscarlo en el bloque que lo contenga, y así sigue hasta encontrarlo. Si el identificador no se encuentra en ninguno de los bloques anidados entonces no existe.

Ejemplo:


Lectura obligatoria.

Capítulo 8 de “The Theory and Practice of Compiler Writing”, Tremblay& Sorenson. McGrawHill. 1985.

















Clase 2.1 Introducción al proceso de compilación

¿Que es un Traductor?

Un traductor es un programa que toma como entrada un texto escrito en un lenguaje y da como salida otro texto en un lenguaje diferente.




Ejemplos del traductor.

Mensaje de error.

Tipos de Traductores.

  • Compilador: es un traductor que convierte un texto escrito en un lenguaje de alto nivel a un lenguaje de bajo nivel (código objeto o máquina).
  • Ensamblador: es un lenguaje de bajo nivel, donde cada sentencia del lenguaje fuente se traduce a una instrucción en código máquina.
  • Interprete: no genera código objeto, analiza y ejecuta directamente cada proposición del código fuente.
  • Preprocesador: procesan un texto fuente modificándolo en cierta forma previamente a la compilación.
¿Como saber si estamos ante un compilador?

Cuando el lenguaje fuente esta en un lenguaje de programación de alto nivel y el objeto generado sea de bajo nivel (ensamblador o código de maquina).


Resultado del compilador:



Ventajas de los compiladores.
  • Producen un código optimizado.
  • La ejecución del programa objeto es mucho mas rápida que si se interpreta el programa fuente
  • El compilador tiene una visión global del programa, por lo que la información de mensajes de error es más detallada.

Desventajas de los compiladores.
  • Se debe de ejecutar muchas veces el código fuente para ver los cambios en el resultado.
  • Mayor consumo de memoria.
Interprete: 

Es un programa que analiza y ejecuta simultáneamente el programa fuente, es decir no producen un código objeto, siendo su ejecución simultánea a la del programa fuente.

Comportamiento del Interprete:

Un interprete es como un compilador, solo que la salida es una ejecución. El programa de entrada se reconoce y ejecuta a la vez. No se produce un resultado físico (código máquina) sino lógico (una ejecución).

Resultado del interprete




Contexto del compilador.


Etapas de compilación.


Token: es una cadena de caracteres que tiene un significado coherente un lenguaje de programación.

En la etapa de análisis se divide el programa fuente en sus piezas constituyentes y crea una representación intermedia del mismo.

En la etapa de síntesis se construye el programa destino deseado a partir de una descripción en un lenguaje de representación intermedia.


Análisis Léxico.
El analizador léxico o scanner, transforma el texto fuente en una secuencia ordenada de elementos léxicamente válidos (tokens).






Funciones del Análisis Léxico.

El analizador léxico debe reconocer y presentar los caracteres Tokens en una representación más útil para el analizador sintáctico.

Además de:
  • Eliminar espacios.
  • Ignorar comentarios.
  • Tratar con la tabla de símbolos.
  • Reconocer identificadores y palabra reservada.
  • Manejar el fichero fuente.
  • Contabilizar posición de tokens.
  • Procesar macros, constantes, includes..
  • Generar tokens bajo demanda del analizador sintáctico.
  • Estructurar la colección de tokens.
  • Identificar la colección de tokens.
  • Describir el lenguaje como expresiones regulares.
  • Especificar un diagrama de transición.
  • Traducir el diagrama a una tabla de transición.
Analizador Sintáctico.

El analizador sintáctico o parser recibe los tokens y comprueba su ordenación correcta. Genera un árbol sintáctico.


Tipos de Analizadores Sintácticos.


Análisis Semántico
  • El analizador semántico comprueba que el árbol sintáctico es semánticamente válido.
  • Revisa el programa fuente para comprobar que las reglas semánticas se cumplen.
  • Genera un árbol semántico o etiquetado.

Generación de código intermedio.
  • Después de los análisis sintácticos y semánticos, algunos compiladores generan una representación intermedia explicita del programa fuente.
  • Se puede considerar esta representación intermedia como un programa para una maquina abstracta.
  • Esta representación intermedia debe tener dos propiedades importantes, debe ser fácil de producir y fácil de traducir al programa objeto.
Optimización de código.
  • La fase de optimización de código trata de mejorar el código intermedio, de modo que resulte un código de Maquina más rápido de ejecutar.
  • Hay mucha variación en la cantidad de optimización de código que ejecutan los distintos compiladores, una parte significativa del tiempo del compilador se ocupa en esta fase. 
  • La fase Final de un compilador es la generación de código objeto, que por lo general consiste en código máquina relocalizable 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 ejecutan la misma tarea.







domingo, 29 de mayo de 2016

Clase Nº 2 Clasificación de los interpretes.

¿Que es un interprete?

  • En lugar de producir un programa objeto como resultado de una traducción, un interprete realiza las operaciones que implica el programa fuente.
  • Un interprete no genera un programa equivalente, sino que toma una sentencia del programa fuente en un lenguaje de alto nivel, la traduce al código equivalente y al mismo tiempo la ejecuta.
  • Un interprete es un programa que analiza y ejecuta simultáneamente el programa fuente, es decir no producen un código objeto, siendo su ejecución simultanea a la del programa fuente.
Comportamiento de un interprete.
  • Un interprete es como un compilador, solo que la salida es una ejecución. El programa de entrada se reconoce y ejecuta a la vez. No se produce un resultado físico (código maquina) sino lógico (una ejecución).
  • Además de que la traducción optimiza el programa acercándolo a la máquina, los lenguajes interpretados tienen la característica de que permiten construir programas que se pueden modificar así mismos.
Resultado del interprete.


Ventajas de los interpretes.
  • Su principal ventaja es que permiten una fácil depuración. Permiten una mayor  interactividad con el código en tiempo de desarrollo.
  • En algunos lenguajes (Smalltalk, Prolog, LISP) está permitido y es frecuente añadir código según se ejecuta otro código, y esta característica solamente es posible implementarla en un interprete.
  • Puede ser interrumpido con facilidad.
  • Puede ser rápidamente modificado y ejecutado nuevamente.
  • Un interprete necesita menos memoria que un compilador.
  • Facilita la búsqueda de errores.
  • En algunos lenguajes esta permitido añadir código según se ejecuta otro código.
  • Menor consumo de memoria.
Desventajas de los interpretes.
  • Lentitud de ejecución, ya que al ejecutar a la vez que se traduce no puede aplicarse un alto grado de optimización. Cada instrucción  debe ser traducida a código maquina tantas veces como sea ejecutada.
  • Durante la ejecución, el interprete debe residir en memoria ya que no genera código objeto.
  • Tamaño del programa objeto, que exige añadir el intérprete al programa propiamente dicho.
Clasificación de los interpretes.
  • Interpretes Puros.
  • Interpretes Avanzados.
  • Interpretes Incrementales.
¿Que son los interpretes Puros?
  • Los interpretes puros son los que analizan una sentencia y la ejecutan, y así sucesivamente todo el programa fuente. Fueron los interpretes desarrollados en la primera generación de ordenadores, pues permitían la ejecución de largos programas con ordenadores de memoria muy reducida, ya que sólo debían contener en memoria el interprete y la sentencia a analizar y ejecutar.
  • El principal problema de este tipo de interpretes es que si a mitad del programa fuente se producen errores, se debe de reiniciar el proceso.
En la figura se representa el esquema general de un interprete puro, donde se puede observar que el lenguaje fuente se traduce a una representación interna (texto o binaria) que puede ser almacenada en memoria o en disco. Esta presentación interna tiene todas las instrucciones numeradas o colocadas consecutivamente en estructuras de tamaño fijo (por ejemplo un array o posiciones consecutivas de memoria, o un fichero binario de estructuras de tamaño fijo). Mientras se realiza este paso se puede construir la tabla de etiquetas, que es una tabla que contiene una estructura donde están todas las etiquetas y su posición en el programa fuente (las etiquetas se utilizan tanto en las instrucciones de salto como en las llamadas a procedimiento y funciones). Una vez que este proceso ha finalizado, comienza la ejecución por la primera instrucción del código, que se envía al evaluador de instrucciones, este la ejecuta (recibiendo datos si es necesario o enviando un mensaje de error). El evaluador de instrucciones también determina la instrucción siguiente a ejecutar, en algunos casos previa consulta a la tabla de etiquetas. En el caso de que no se haya saltos (GOTO) o llamadas a procedimientos o funciones se ejecuta la siguiente instrucción a la instrucción en curso. El evaluador de instrucciones puede utilizar dos métodos de evaluación. El método clásico es la evaluación voraz o ansiosa, donde se evalúan las expresiones completamente. Otro método clásico es la evaluación perezosa, evaluándose sólo la parte necesaria de la expresión (el resto no se evalúa).

Interpretes Avanzados.

Los interpretes avanzados o normales incorporan un paso previo de análisis de todo el programa fuente. Generando posteriormente un lenguaje intermedio que es ejecutado por ellos mismos. De esta forma en caso de errores sintácticos no pasan de la fase de análisis.


Un ejemplo de interprete avanzado es el que utiliza el lenguaje Java. Así un programa en lenguaje java (con la extensión .java) se compila y produce uno o varios ficheros con la extensión .class, estos ficheros están en un formato binario denominado bytecode independiente de plataforma, que se interpreta posteriormente. Esto permite que el bytecode se ejecute en cualquier sistema operativo que disponga de un intérprete de bytecode. Dado que la mayor parte de los navegadores de Internet levan inmenso un interprete de bytecode, esto ha permitido al lenguaje Java ser uno de los más utilizados en aplicaciones que usen Internet.

Interpretes Incrementales.

Algunos lenguajes no se pueden compilar, debido a que entre sus características pueden manejar objetos o funciones que no son conocidos en tiempo de compilación, ya que son creados en ejecución. Para este tipo de lenguajes existen los interpretes incrementales, que permiten compilar los módulos completamente definidos, y recompilar en tiempo de ejecución los nuevos módulos. Los interpretes incrementales tienen gran interés en los lenguajes que permiten no definir los problemas completamente en tiempo de compilación. En estos casos se utilizan evaluadores parciales que toman como entrada el programa fuente junto con algunos datos (pero no todos), realizándose los cálculos que se pueden hacer con dicho subconjunto de datos, y produciendo una salida que contienen un residuo del programa fuente que se ha introducido.






Unidad 01 Introducción a los Traductores.

Existen dos tipos principales de traductores de lenguajes de programación de alto nivel:
  • Compiladores. 
  • Interpretes
¿Que son Lenguajes de programación?
Son los que ocupan una posición intermedia entre los lenguajes naturales humanos y los precisos lenguajes de máquina.
Gracias a la progresiva complejidad de los lenguajes traductores que permitenconvertir las instrucciones de un lenguaje de programación al lenguaje de máquina, la programación puede usar lenguajes de computación que se parecen cada vez más a los lenguajes naturales.
A los lenguajes máquina se les conoce como lenguajes de primera generación.
Los ensambladores son los lenguajes de segunda generación.
Los simbólicos de alto nivel de tipo procedural se les denomina de tercera generación y a los relacionales se considera que son de cuarta generación.
A la tercera generación pertenecen lenguajes conocidos como el FORTRAN, COBOL, RPG, BASIC, PL1, SIMULA, ALGOL, PASCAL, ADA, C, LISP, PROGOL.
SQL es un lenguaje convertido en estándar mundial como lenguaje de cuarta generación, una serie de lenguajes orientados a objetos. Entre estos destaca elVisual Basic de Microsoft. Además hay que prestar una seria atención al lenguaje de programación Java, desarrollado por SUN.
¿Que es un Compilador?
Es el proceso de traducción que convierte un programa fuente escrito en un lenguaje de alto nivel a un programa objeto en código máquina y listo por tanto para ejecutarse en el ordenador, con poca o ninguna preparación adicional.

Un compilador analiza el programa y lo traduce al idioma “maquina”. La acción fundamental de los compiladores es equivalente a la de un traductor humano , que toma nota de lo que esta escuchando y reproduce por escrito en otra lengua.

Esquema del compilador.


Fases del compilador.



¿Que es un Interprete?
Es el que analiza el programa fuente y lo ejecuta directamente, Ejemplo del traductor humano, éste sería un traductor humano que conforme a lo que está escuchando va ejecutando, sin generar ningún escrito, es decir que sobre la marcha va traduciendo.

Datos curiosos de los Compiladores.
  • En los 50 los compiladores eran considerados programas muy difíciles.
  • FORTRAN se desarrolló en grupo durante 18 años.
  • Se han desarrollado técnicas sistemáticas, entornos de programación y herramientas software que facilitan la tarea de desarrollo.
Linea de tiempo.