Monografias.com > Computación > Software
Descargar Imprimir Comentar Ver trabajos relacionados

Software de Sistemas




Enviado por marysol_gtz Gtz



    1. Introducción a Software de
      sistemas
    2. Cargadores y
      Ligadores
    3. Compiladores
    4. Intérpretes

    UNIDAD I.- INTRODUCCIÓN A SOFTWARE DE
    SISTEMAS

    1. ¿QUÉ ES EL SOFTWARE DE
      SISTEMAS?

    Software son las instrucciones electrónicas que
    van a indicar a la PC que es lo que tiene que hacer.
    También se puede decir que son los programas usados
    para dirigir las funciones de un
    sistema de
    computación o un hardware(1).

    El software es el conjunto de instrucciones que las
    computadoras
    emplean para manipular datos. Sin el
    software, la computadora
    sería un conjunto de medios sin
    utilizar. Al cargar los programas en una computadora,
    la máquina actuará como si recibier a una educación
    instantánea; de pronto "sabe" cómo pensar y
    cómo operar. El Software es un conjunto de programas,
    documentos,
    procedimientos, y rutinas asociados con la
    operación de un sistema de computo. Distinguiéndose
    de los componentes físicos llamados hardware.
    Comúnmente a los programas de computación se les
    llama software; el software asegura que elprograma o sistema
    cumpla por completo con sus objetivos,
    opera con eficiencia, esta
    adecuadamente documentado, y suficientemente sencillo de operar.
    Es simp lemente el conjunto de instrucciones individuales que se
    le proporciona al microprocesador
    para que pueda procesar los datos y generar los resultados
    esperados. El hardware por si solo no puede hacer nada, pues es
    necesario que exista el software, que es el conjunto de
    instrucciones que hacen funcionar al hardware(2).

    (1 Dir. http://www.conozca
    su pc.com.ar/soft1.htm) definición de software de
    sistemas

    (2 Dir.
    http://www.salonhogar.com/ciencias/tecnologias/computadoras/definicion

    software.htm)

    Por que estudiarlo

    El software para uso general ofrece la estructura
    para un gran número de aplicaciones empresariales,
    científicas y personales. El software de hoja de
    cálculo, de diseño
    asistido por computadoras (CAD), de procesamiento de texto, de
    manejo de Bases de Datos,
    pertenece a esta categoría. La mayoría de software
    para uso general se vende como paquete; es decir, con software y
    documentación orientada al usuario (
    manuales de
    referencia, plantillas de teclado y
    demás )(1).

    (1 Dir.
    http://www.salonhogar.com/ciencias/tecnologias/computadoras/softwaredeusogeneral.htm
    )

    Diferencias con el software de
    aplicación

    El software de
    aplicación esta diseñado y escrito para
    realizar tareas específicas personales,,empresariales o
    científicas como el procesamiento de nóminas,
    la
    administración de los recursos
    humanos o el control de
    inventarios. Todas éstas aplicacion es procesan datos
    (recepción de materiales) y
    generan información (registros de
    nómina). para el usuario. Sistemas
    Operativos Un sistema Operativo
    (SO) es en sí mismo un programa de
    computadora. Sin embargo, es un programa muy especial,
    quizá el más complejo e importante en una
    computadora. El SO despierta a la computadora y hace que
    reconozca a la CPU, la memoria, el
    tecla do, el sistema de vídeo y las unidades de disco.
    Además, proporciona la facilidad para que los usuarios se
    comuniquen con la computadora y sirve de plataforma a partir de
    la cual se corran programas de aplicación. Cuando
    enciendes una computadora, lo primero que ésta hace es
    llevar a cabo un autodiagnóstico llamado autoprueba de
    encendido (Power On Self Test, POST).
    Durante la POST, la computadora indentifica su memoria, sus
    discos, su teclado, su sistema de vídeo y cualquier otro
    dispositivo conectado a ella. Lo siguiente que la computadora
    hace es buscar un SO para arrancar (boot).

      Una vez que la computadora ha puesto en marcha su
    SO, mantiene al menos parte de éste en su memoria en todo
    momento. Mientras la computadora esté encendida, el SO
    tiene 4 tareas principales.

    1.Proporcionar ya sea una interfaz de línea de
    comando o una interfaz gráfica al usuario, para que este
    último se pueda comunicar con la computadora. Interfaz de
    línea de comando: tú introduces palabras y
    símbolos desde el teclado de la computadora, ejemplo, el
    MS-DOS.Interfaz gráfica del Usuario (GUI),
    seleccionas las acciones
    mediante el uso de un Mouse para
    pulsar sobre figuras llamadas iconos o seleccionar opciones de
    los menús.

    2.Administrar los dispositivos de hardware en la
    computadora. Cuando corren los programas, necesitan utilizar la
    memoria, el monitor, las
    unidades de disco, los puertos de Entrada/Salida (impresoras,
    módems, etc). El SO sirve de intermediario entre los
    programas y el hardware.

    3.Administrar y mantener los sistemas de archivo de
    disco.  Los SO agrupan la información dentro de
    compartimientos lógicos para almacenarlos en el disco.
    Estos grupos de
    información son llamados archivos. Los
    archivos pueden contener instrucciones de programas o
    información creada por el usuario. El SO mantiene una
    lista de los archivos en un disco, y nos proporciona las herramientas
    necesarias para organizar y manipular estos archivos.

    4.Apoyar a otros programas. Otra de las funciones
    importantes del SO es proporcionar servicios a
    otros programas. Estos servicios son similares a aquellos que el
    SO proporciona directamente a los usuarios. Por ejemplo, listar
    los archivos, grabarlos a disco, eliminar archivos, revisar
    espacio disponible, etc. Cuando los programadores escriben
    programas de computadora, incluyen en sus programas instrucciones
    que solicitan los servicios del SO. Estas instrucciones son
    conocidas como "llamadas del sistema" (1)

      (1 Dir.
    http://www.salonhogar.com/ciencias/tecnologias/computadoras/software
    de aplicaciones.htm
    )

    UNIDAD II.-
    ENSAMBLADORES

    2.1 El Nivel Del Lenguaje
    Ensamblador

    Dicho nivel difiere considerablemente de los niveles de
    microprogramación, de maquina convencional y del sistema
    operativo, debido a que se implanta por traducción y no
    por interpretación(1).

    2.2 Funciones De Un Ensamblador

    La tarea fundamental de un ensamblador es
    traducir un programa en lenguaje de ensamblador al código
    correspondiente en lenguaje de máquina
    . En esencia, el
    ensamblador debe realizar las siguientes tareas:

    1. Convertir los códigos ("opcode" o
    mnemónicos: ej. LDA, STX) a su código equivalente
    en lenguaje de máquina

    2. Convertir los operandos simbólicos (las
    etiquetas o variables) en
    las direcciones correspondientes de los operandos

    3. Construir las instrucciones en lenguaje de
    máquina en el formato apropiado

    4. Convertir las constantes definidas en el programa en
    su verdadera representación

    5. Escribir el "listing" en lenguaje de ensamblador con
    el código en lenguaje de máquina
    correspondiente

    6. Procesar las directrices al ensamblador (las
    directrices son instrucciones o comandos
    dirigidos al ensamblador, que éste procesa y ejecuta al
    hallarlos en el programa en lenguaje de ensamblador; estas
    directrices no se traducen a lenguaje de máquina, si no
    que el ensamblador ejecuta alguna acción, como reservar
    memoria para variables, entre otras)

    (Org. De Computadoras Un Enfoque Estructurado,
    Tanenbaum, P.445)

    En general, la mayoría de las tareas se puede
    realizar si se recorre el programa línea por línea.
    Pero surge una dificultad si se trata de traducir una
    instrucción cuyo operando está definido
    más abajo en el programa. Si esto ocurre, el
    ensamblador desconoce la dirección del operando y la
    instrucción no se podría ensamblar(1).

    2.3 Tipos De Ensambladores

    Aunque todos los ensambladores realizan
    básicamente las mismas tareas, podemos clasificarlos de
    acuerdo a características.

    Así podemos clasificarlos en:

    Ensambladores Cruzados
    (Cross-Assembler).

    Se denominan así los ensambladores que se
    utilizan en una computadora que posee un procesador
    diferente al que tendrán las computadoras donde va a
    ejecutarse el programa objeto producido.

    El empleo de este
    tipo de traductores permite aprovechar el soporte de medios
    físicos (discos, impresoras, pantallas, etc.), y de
    programación que ofrecen las máquinas
    potentes para desarrollar programas que luego los van a ejecutar
    sistemas muy especializados en determinados tipos de
    tareas.

    Ensambladores Residentes.

    Son aquellos que permanecen en la memoria principal de
    la computadora y cargan, para su ejecución, al programa
    objeto producido. Este tipo de ensamblador tiene la ventaja de
    que se puede comprobar inmediatamente el programa sin necesidad
    de transportarlo de un lugar a otro, como se hacía en
    cross-assembler, y sin necesidad de programas
    simuladores.

    Sin embargo, puede presentar problemas de
    espacio de memoria, ya que el traductor ocupa espacio que no
    puede ser utilizado por el programador. Asimismo, también
    ocupará memoria el programa fuente y el programa objeto.
    Esto obliga a tener un espacio de memoria relativamente amplio.
    Es el indicado para desarrollos de pequeños sistemas de
    control y sencillos automatismo empleando microprocesadores(1).

    (1)Dir. (http://www.usc.clu.edu/comweb/cco220/ensambladores.htm)

    Ensambladores

    Dir.(http://mx.geocities.com/laura_40cruz/idicelau.htm)

    Página de la arquitectura de
    las computadoras

    La ventaja de estos ensambladores es que permiten
    ejecutar inmediatamente el programa; la desventaja es que deben
    mantenerse en la memoria principal tanto el ensamblador como el
    programa fuente y el programa objeto.

    Macroensambladores.

    Son ensambladores que permiten el uso de
    macroinstrucciones (macros). Debido a
    su potencia,
    normalmente son programas robustos que no permanecen en memoria
    una vez generado el programa objeto. Puede variar la complejidad
    de los mismos, dependiendo de las posibilidades de
    definición y manipulación de las
    macroinstrucciones, pero normalmente son programas bastantes
    complejos, por lo que suelen ser ensambladores
    residentes.

    Microensambladores.

    Generalmente, los procesadores
    utilizados en las computadoras tienen un repertorio fijo de
    instrucciones, es decir, que el intérprete de las mismas
    interpretaba de igual forma un determinado código de
    operación.

    El programa que indica al intérprete de
    instrucciones de la UCP cómo debe actuar se denomina
    microprograma. El programa que ayuda a realizar este
    microprograma se llama microensamblador. Existen procesadores que
    permiten la modificación de sus microprogramas, para lo
    cual se utilizan microensambladores.

    Ensambladores de una fase.

    Estos ensambladores leen una línea del programa
    fuente y la traducen directamente para producir una
    instrucción en lenguaje máquina o la ejecuta si se
    trata de una pseudoinstrucción. También va
    construyendo la tabla de símbolos a medida que van
    apareciendo las definiciones de variables, etiquetas,
    etc.

    Debido a su forma de traducción, estos
    ensambladores obligan a definir los símbolos antes de ser
    empleados para que, cuando aparezca una referencia a un
    determinado símbolo en una instrucción, se conozca
    la dirección de dicho símbolo y se pueda traducir
    de forma correcta. Estos ensambladores son sencillos, baratos y
    ocupan poco espacio, pero tiene el inconveniente
    indicado(1).

    Ensambladores de dos fases.

    Los ensambladores de dos fases se denominan así
    debido a que realizan la traducción en dos etapas. En la
    primera fase, leen el programa fuente y construyen una tabla
    de símbolos
    ; de esta manera, en la segunda fase,
    vuelven a leer el programa fuente y pueden ir traduciendo
    totalmente, puesto que conocen la totalidad de los
    símbolos utilizados y las posiciones que se les ha
    asignado. Estos ensambladores son los más utilizados en la
    actualidad.

    Para mayor información http:
    www.sapag.com

    CONCLUSIONES

    Al parecer así como hay diferentes tipos de
    memoria también hay diferentes tipos de ensambladores
    y diferentes tipos de buses pero bueno me parece que cada
    característica le sirven a cada persona o ustedes
    que opinan..nos vemos(1).

    2.4 El Proceso De
    Ensamble De Uno, Dos O Mas Pasos

    Es por esta razón que la mayoría de los
    ensambladores hacen su trabajo pasando dos veces por el
    programa fuente: una primera vez se pasa para asignar a cada
    etiqueta su dirección correspondiente en el programa
    objeto. El ensamblador pasa una Segunda ocasión por el
    programa fuente para llevar a cabo el ensamblaje de las
    instrucciones una vez ya tiene asignadas las direcciones de todas
    las etiquetas. Estos ensambladores se llaman ensambladores de dos
    pasadas ("two pass assembler").

    Las tareas que el ensamblador lleva a cabo en cada
    pasada son:

    Primera pasada:

    1. asignar una dirección de memoria a cada
    instrucción

    2. guardar en una tabla las direcciones de todas las
    etiquetas del programa

    3. procesar algunas de las directrices

    Segunda pasada:

    1. cambiar los mnemónicos a su código
    correspondiente en lenguaje de máquina

    2. poner las direcciones de los operandos
    simbólicos o etiquetas en las instrucciones

    3. generar los valores de
    las constantes declaradas

    4. procesar el resto de las directrices

    5. escribir el programa en lenguaje objeto y el
    "listing" (1)

    (1)Dir.(http://ww.usc.clu.edu/comweb/cco220/ensambladores.htm)

    Continuación de ensambladores

    El "object program" que se genera se guarda en un
    archivo en disco, para luego ejecutarse. Este archivo contiene
    tres (por ahora) tipos de récords:

    un "header record" con el nombre del programa, su
    dirección inicial y el largo del programa (la
    dirección inicial se obtiene de la directriz START del
    programa fuente)

    varios "text records" con las instrucciones
    ensambladas

    un "end record" con la dirección de la primera
    instrucción ejecutable del programa(1).

    Ensambladores De Dos Pasadas.- consta de una serie de
    sentencias de una línea, parece natural tener un
    ensamblador que lea una sentencia, la traduzca a lenguaje de
    maquina y escriba el código de maquina generando en un
    archivo y la porción del listado correspondiente, si la
    hay, en otro. El proceso se repetirá hasta que todo el
    programa sé haya traducido. Por desgracia, este método no
    funciona.

    La Primera Pasada.- la función
    principal es construir, lo que sé llama tabla de
    símbolos, donde se guardan los valores de
    todos los símbolos. Un símbolo es una etiqueta o un
    valor al que
    se le asigna un nombre simbólico por medio de una
    seudoinstrucción: espacio equ 100

    La Segunda Pasada.- es generar el programa objeto y
    posiblemente, imprimir el listido de ensamblaje. Además,
    debe producir cierta información necesaria para que el
    programa ligador enlace procedimientos ensamblados en momentos
    diferentes(2).

    (2.Org. De Computadoras Un Enfoque Estructurado,
    Tanenbaum, P.453)

    2.5 Literales Y Expresiones

    Literales.- se le llama así a las
    constantes para las cuales el ensamblador reserva memoria
    automática. Además de ahorrar al programador un
    poco de escritura, las
    literales hacen más legibles de los programas al hacer que
    el valor de la constante aparezca en la instrucción
    fuente(1).

    Expresiones.-Una expresión es una
    combinación de símbolos constantes, operadores
    algebraicos y paréntesis. La expresión especifica
    un valor, el cual será utilizado como operando.

    Las expresiones pueden consistir de símbolos,
    constantes o del caracter ‘ * ‘ (denotando el valor
    actual del contador de programa PC) unidos entre sí por
    alguno de los operadores: +, -, *, /, %, &, I, ^.
    (2)

    (1.Org. De Computadoras Un Enfoque Estructurado,
    Tanenbaum, P.500)

    (2 Dir. Members.es.tripod.de/patricio/ensam/ensam1.htm)
    continuación de Macros y Procedimientos

    2.6 Definición De Una Macro

    Una macro es un grupo de
    instrucciones repetitivas en un programa que se codifican solo
    una vez y pueden utilizarse cuantas veces sea
    necesario.

    La principal diferencia entre una macro y un procedimiento es
    que en la macro se hace posible el paso de parámetros y en
    el procedimiento no (esto es aplicable solo para el MASM, hay
    otros lenguajes de
    Programación que si lo permiten). Al momento de
    ejecutarse la macro cada parámetro es sustituido por el
    nombre o valor especificado al momento de llamarla.

    Podemos decir entonces que un procedimiento es una
    extensión de un determinado programa, mientras que la
    macro es un módulo con funciones específicas que
    puede ser utilizado por diferentes programas(1).

    2.6.1 Macroinstrucción

    son las instrucciones normales del nivel de
    maquina convencional, como ADD, MOVE, etc(2).

    2.6.4 Bibliotecas De
    Macros

    Una de las facilidades que ofrece el uso de las
    macros es la creación de bibliotecas, las cuales son
    grupos de macros que pueden ser incluidas en un programa desde un
    archivo diferente.

    La creación de estas bibliotecas es muy sencilla,
    unicamente tenemos que escribir un archivo con todas las macros
    que se necesitarán y guardarlo como archivo de
    texto.

    Para llamar a estas macros solo es necesario utilizar la
    instrucción Include NombreDelArchivo, en la parte de
    nuestro programa donde escribiriamos normalmente las macros, esto
    es, al principio de nuestro programa(1).

    (1 Dir. Members.es.tripod.de/patricio/ensam/ensam1.htm)
    Macros y Pocedimento

    (2.Org. De Computadoras Un Enfoque Estructurado,
    Tanenbaum, P.200)

    2.7 Ensamble Condicional

              Se
    emplean para que el ensamblador evalúe unas condiciones y,
    según ellas, ensamble o no ciertas zonas de código.
    Es frecuente, por ejemplo, de cara a generar código para
    varios ordenadores: pueden existir ciertos símbolos
    definidos que indiquen en un momento dado si hay que ensamblar
    ciertas zonas del listado o no de manera condicional,
    según la máquina. En los fragmentos en ensamblador
    del código que generan los compiladores
    también aparecen con frecuencia (para actuar de manera
    diferente, por ejemplo, según el modelo de
    memoria). Es interesante también la posibilidad de definir
    un símbolo que indique que el programa está en fase
    de pruebas y
    ensamblar código adicional en ese caso con objeto de
    depurarlo. Sintaxis:

    IFxxx [símbolo/exp./arg.] ; xxx es la
    condición

    …ELSE ; el ELSE es opcional

    …ENDIF

    IF expresion (expresión distinta de
    cero)

    IFE expresión (expresión igual a
    cero)

    IF1 (pasada 1 del ensamblador)

    IF2 (pasada 2 del ensamblador)

    IFDEF símbolo (símbolo definido o
    declarado como externo)

    IFNDEF símbolo (símbolo ni definido ni
    declarado como externo)

    IFB <argumento> (argumento en blanco en macros
    -incluir '<' y '>'-)

    IFNB <argumento> (lo contrario, también es
    obligado poner '<' y '>')

    IFIDN <arg1>, <arg2> (arg1 idéntico a
    arg2, requiere '<' y '>')

    IFDIF <arg1>, <arg2> (arg1 distinto de arg2,
    requiere '<' y '>')(1)

    (1 Dir. http://www.usc.clu.edu/comweb/cco220/ensambladores.htm)
    Continuación de Ensambladores

    3.1 Concepto De
    Cargadores y Ligadores

    Un ligador es un programa de sistema que combina dos o
    mas programas objeto separados y permite que se hagan referencias
    unos a otros, o sea, que cada uno de estos programas pueden hacer
    referencia a código ó variables de los otros
    programas con los que está enlazado.

    En muchos programas el cargador hace la labor del
    programa de enlace, por que existe solo un "linking loader" y no
    existe programa de enlace independiente. Es importante
    señalar que no se necesita un programa de enlace ni un
    cargador separado para cada traductor en el sistema, ya que estos
    programas trabajan con el programa objeto, sin importar el lenguaje
    fuente. Por otro lado es importante que cada compilador o
    ensamblador produzca el programa objeto usando el mismo formato.
    Cada programa objeto es un archivo de récord.

    Un cargador es un programa que coloca en la memoria para
    su ejecución, el programa guardado en algún
    dispositivo de almacenamiento
    secundario.

    Un cargador es un programa del sistema que realiza la
    función de carga, pero muchos cargadores también
    incluyen relocalización y ligado.

    Algunos sistemas tienen un ligador para realizar las
    operaciones de
    enlaces y un cargador separado para manejar la
    relocalización y la carga.

    Los procesos de
    ensamblado y carga están íntimamente
    relacionados.

    El cargador consiste en un juego de
    instrucciones que permiten al dispositivo de entrada ( teclado
    ó unidad de cinta ) asignar la dirección de inicio
    de la memoria y asegurar que el computador
    leerá el programa y lo cargara byte a byte.

    3.2 Funciones De Un Cargador Y Un
    Ligador

    Las funciones mas importantes de un cargador son:
    colocar un programa objeto en la memoria e iniciar su
    ejecución. Si tenemos un cargador que no necesita realizar
    las funciones de ligado y relocalización de programas, su
    operación es simple pues todas las funciones se realizan
    en un solo paso. Se revisa el registro de
    encabezamiento para comprobar se ha presentado el programa
    correcto para la carga (entrando en la memoria disponible). A
    medida que lee cada registro de texto, el código objeto
    que contiene pasa a dirección de la memoria indicada.
    Cuando se encuentra el registro de fin, el cargador salta a la
    dirección especificada para iniciar la ejecución
    del programa cargado. Un programa objeto contiene instrucciones
    traducidas y valores de datos del programa fuente y
    específica direcciones en memoria dónde cargaran
    estos elementos.

    Carga que lleva el programa objeto a la memoria para su
    ejecución.

    Relocalización que modifica el programa objeto de
    forma que puede cargarse en una dirección diferente de la
    localidad especificada originalmente.

    Ligado que combina dos o mas programas objeto
    independientes y proporciona la información necesaria para
    realizar diferencias entre ellos.

    El cargador es un programa del sistema que realiza la
    función de carga pero muchos cargadores también
    incluyen relocalización y ligado. Algunos sistemas tienen
    un ligador (ó editor de ligado ) para realizar las
    operaciones de enlace, y un cargador separado para manera la
    relocalización y la carga.

    En la mayoría de los casos todos los traductores
    de programas ( esto es, ensambladores y compiladores ) de un
    sistema en particular producen programas objeto en el mismo
    formato.

    De esta misma forma, puede usarse el cargador o ligador
    del sistema con independencia
    del lenguaje de
    programación fuente original, se suele utilizar el
    término cargador en lugar de cargador y ligador, los
    procesos de ensamblado y carga están íntimamente
    relacionados entre sí.

    Se han desarrollado herramientas especiales de software,
    llamadas cargadores para asistir, al programados en la carga del
    programa. El cargador es normalmente un programa pequeño
    que permite al usuario entrar directamente las palabras de
    instrucción y datos a direcciones concretas de la memoria
    mediante, ó un teclado ó una cinta
    magnética.

    3.3 Tipos de cargadores y Ligadores

    Hay diferentes tipos de cargadores como:

    Cargadores Bootstrap: el programa cargador
    una vez, situado en la memoria del computador, cargará el
    programa de aplicación y los datos. Pero, previamente, se
    ha debido cargar el cargador en la memoria. Y esto se puede
    realizar por los siguientes métodos:

    Entrada manual: mediante
    el teclado el usuario teclea el cargador BOOTSTRAP.
    Después de esto, el cargador se carga así mismo en
    la memoria del computador.

    Entrada por ROM: es posible tener las instrucciones de
    inicialización almacenados permanentemente en alguna
    porción de la ROM, en lugar de introducirlas manualmente
    por teclado o por panel frontal. Cuando se requiere el programa
    de bootstra, el operador simplemente dirige al computador,
    mediante los conmutadores del panel, a ejecutar las instrucciones
    memorizadas en ROM: al estar el programa almacenado en ROM se
    elimina también la posibilidad de borrados
    accidentales.

    Cargadores iniciales: indican a la
    computadora la forma de poner, dentro de la memoria principal
    unos datos que están guardados en un periférico de
    memoria externa ( cinta, disco, etc ). Sirven para cargar en la
    memoria pequeños programas que inician el funcionamiento
    de una computadora .

    Algunas computadoras de carácter
    general no tienen en memoria ningún programa de forma
    permanente y cuando se desconectan pierden toda la
    información de su memoria interna. Al volverlos a conectar
    no son capaces de controlar ningún periférico. Se
    hace así para que sea el usuario el que ponga los
    programas que le interese ejecutar.

    Cargadores absolutos: el programa cargador
    pone en memoria las instrucciones guardadas en sistemas externos.
    Independientemente de que sea un cargador inicial, o no sin
    dichas instrucciones se almacenan siempre en el mismo espacio de
    memoria ( cada vez que se ejecuta el programa cargador ) se dice
    que es un cargador absoluto.

    Cargadores con reubicación: en
    ocasiones un mismo programa necesita ejecutarse en diferentes
    posiciones de memoria. Para esto la traducción debe estar
    realizada en forma adecuada, es decir no utilizando referencias
    absolutas a direcciones en memoria, sino referencias a una
    dirección especial llamada de
    reubicación.

    Cargadores ligadores: conocidos
    también como linker . un linker se un término en
    inglés
    que significa montar.

    Montar un programa consiste en añadir al programa
    objeto obtenido a la traducción las rutinas externas a las
    que hace referencia dicho programa. El ensamblador debe permitir
    dichas referencias y las rutinas deben estar a su vez en lenguaje
    máquina guardadas en algún elemento accesible por
    el montador. Generalmente, dichas rutinas se encuentran guardadas
    en un fichero especial al que suele denominarse librería
    porque están almacenadas todas las rutinas externas
    susceptibles de ser utilizadas por los diferentes programas del
    usuario. Allí va el programa ligador cuando esta
    realizando el montaje de un programa a buscarlas y las adjunta al
    programa objeto.

    Editores de ligado: la diferencia
    fundamental entre un editor de ligado y un cargador ligador
    es:

    Primero.- se ensambla o compila el programa fuente,
    produciendo un programa objeto ( que puede contener varias
    secciones de control
    diferentes ). Una cargador ligador realiza todas las operaciones
    de ligado y relocalización incluyendo búsqueda
    automática en bibliotecas, si se específica, y
    carga el programa ligado directamente en la memoria para su
    ejecución. Por otro lado un editor de ligado produce una
    versión ligada del programa ( llamada a menudo modulo de
    carga ó imagen ejecutable
    ) que se escribe en un archivo o biblioteca para
    su ejecución posterior.

    Cuando el usuario está listo para ejecutar el
    programa ligado, se puede utilizar un cargador relocalizador
    simple para cargar el programa en la memoria. La única
    modificación necesaria al código objeto es la suma
    de una dirección de carga real a los valores relativos del
    programa. El editor de ligado realiza la relocalización de
    todas las secciones de control al inicio del programa ligado. De
    esta forma todos los elementos que necesitan modificarse en el
    momento de la carga tienen valores relativos al inicio del
    programa ligado.

    Los editores de ligado se pueden utilizar para construir
    paquetes de subrutinas u otras secciones de control que se suelen
    utilizar juntas . esto puede ser útil al tratar con
    bibliotecas de subrutinas que manejan lenguajes de
    programación de alto nivel. A veces permiten al usuario
    especificar que las referencias externas no se resuelven por
    búsqueda automática en biblioteca.

    Ligado dinámico: ofrece algunas
    ventajas sobre los tipos de ligado. Proporciona la posibilidad de
    cargar las rutinas sólo cuando si se necesitan. Si las
    subrutinas son grandes ó tienen muchas referencias
    externas se pueden conseguir ahorros considerables de tiempo y espacio
    en memoria.

    El ligado dinámico evita la necesidad de cargar
    la biblioteca completa para cada ejecución. Puede incluso
    hacer innecesario que el programa conozca el conjunto de
    subrutinas que se podría utilizar. El nombre de la
    subrutina se trataría simplemente como otro elemento de
    entrada. En el método que se utilice aquí las
    rutinas que se carguen dinámicamente deben llamarse por
    medio de una solicitud del servicio al
    sistema operativo. Este método también
    podría considerarse como una solicitud a una parte del
    cargador que se mantiene en la memoria durante la
    ejecución del programa.

    Cuando se utiliza ligado dinámico, la
    asociación de dirección real y el nombre
    simbólico de la rutina llamada no se hace hasta que se
    ejecuta la proposición llamada.

    3.4 Proceso De Carga Absoluta

    Para ser ejecutados los programas se deben ubicar e la
    memoria principal. Una tarea muy importante es asociar
    instrucciones y datos con localidades específicas de
    memoria. El trabajo de
    realizar está asociación se deja algunas veces al
    usuario, otras al traductor, otras al programa llamado cargador y
    otras más al sistema operativo. La asociación de
    instrucciones con ciertas localidades de memoria se conoce como
    ligamiento. Dentro de la programación el lenguaje
    máquina, el ligamiento y los sistemas de memoria
    virtual actuales lo realizan de manera dinámica mientras se ejecuta el programa.
    El retraso del ligamiento aumenta la flexibilidad para el usuario
    y el sistema, pero los traductores, ligadores y los sistemas
    operativos resultan más complejos. Un cargador es un
    programa que coloca las instrucciones de un programa y sus datos
    en memoria principal. Un cargador absoluto coloca
    las instrucciones y los datos en las localidades precisas
    indicadas por el programa en lenguaje de
    máquina.

    El proceso de carga absoluta consiste en que con la
    máquina vacía ó inactiva no hay necesidad de
    hacer relocalización de programas tan solo se puede
    especificar la dirección absoluta del programa que se
    cargue en primer lugar. En la mayoría de los casos este
    programa es el sistema operativo que ocupa un lugar predefinido
    en la memoria. Esto significa que se necesitan algunos medios
    para realizar las funciones de el cargador absoluto. Una
    opción es que el operador introduzca en la memoria el
    código objeto de un cargador absoluto, utilizando los
    interruptores en la consola del computador. Algunos computadores
    requerían que el operador hiciera exactamente eso. Sin
    embargo este proceso es demasiado incomodo y propenso a errores
    para ser una buena solución del problema.

    Para ver el gráfico seleccione la
    opción "Descargar" 

    FIGURA 6.12 proceso de carga

    Otra posibilidad es que el programa del cargador
    absoluto resida permanente en una memoria sólo de lectura (
    ROM). Cuando se produce una señal de hardware la
    máquina empieza a ejecutar este programa de la ROM. En
    algunos computadores el programa se ejecuta directamente en la
    ROM; en otros el programa se copia de la ROM a la memoria
    principal y se ejecuta allí. Sin embargo algunas
    máquinas no tienen ese almacenamiento sólo de
    lectura, además puede no ser conveniente cambiar un
    programa en ROM si es necesario hacer modificaciones en el
    cargador absoluto. Una solución inmediata es tener una
    función de hardware incorporada que lea un registro de
    longitud fija de algún dispositivo en alguna localidad
    fija de la memoria; el dispositivo que se utilice puede
    seleccionarse mediante interruptores de la consola. Una vez
    completa la operación de lectura, el control se pasa
    automáticamente a la dirección de la memoria
    dónde se almaceno el registro. Este registro contiene
    instrucciones de máquina que cargan el programa absoluto
    que sigue. Si el proceso de carga requieren de mas instrucciones
    de las que pueden leerse en un solo registro, el primer registro
    causa la lectura de
    otros y estos a su vez pueden originar la lectura aún de
    más registros de ahí el término
    arranque.

    La carga absoluta necesita que el modulo de carga ocupe
    siempre la misma posición de la memoria principal.
    Así pues , todas las referencias del módulo de
    carga para el cargador deben ser direcciones específicas
    ó absolutas en memoria principal. Por ejemplo si x en la
    siguiente figura es la posición de 1024 la primera palabra
    del módulo de carga destinado a esa región de
    memoria tendrá la dirección 1024.

    La asignación de direcciones especificas a la
    referencia a memoria de un programa pueden ser realizada tanto
    por el programador como el tiempo de compilación o
    ensamblaje. Con el primer método se tienen varias
    desventajas. En primer lugar todos los programadores
    tendrán que conocer la estrategia de
    asignación deseada para situar los módulos en
    memoria principal. En segundo lugar si hace alguna
    modificación en el programa que suponga inserciones
    ó borrados en el cuerpo del módulo tendrán
    que cambiarse todas las direcciones. Por consiguiente es
    preferible permitir que las referencias a memoria dentro de los
    programas se expresen simbólicamente y que se resuelvan en
    el momento de la compilación o el ensamblaje. Así
    cuando se presente el módulo para la entrada a un cargador
    absoluto, el ensamblador o el compilador convertirán todas
    estas referencias direcciones específicas.

    3.5 El Proceso De Carga Relocalizable

    En la relocalización se establece la
    correspondencia entre las direcciones usadas en el programa y
    direcciones físicas cada vez que se utilizan durante la
    ejecución del programa. Las direcciones lógicas
    generadas por el ensamblador y el enlazador no se alteran durante
    la carga. Comenzaremos por ver un sencillo método en el
    cuál el programa se carga en posiciones contiguas de la
    memoria; es decir el programa no está disperso por la
    memoria. En la siguiente figura se presenta un cargador sencillo
    que puede usarse con la relocalización dinámica. En
    este caso el cargador lee encabezado del archivo ejecutable y
    determina la cantidad de espacio necesaria para el programa.
    Después asigna espacio suficiente para el programa y copia
    el archivo ejecutable a memoria. Cuando se carga el programa en
    la memoria, el cargador establece la correspondencia necesaria
    para el programa, pasando la dirección de carga y el
    tamaño v del programa a una rutina llamada
    establecer-correspondencia. Al leer este código observe
    que la función de carga devuelve un entero sin signo en
    lugar de un apuntador. Esto refleja el hecho de que la
    dirección inicial es una dirección lógica
    y física.

    Struct enc-ejec {

    Unsigned int dir_ini

    Unsigned int tamaño texto, tamaño_datos,
    tamaño_bss;

    /* otros campos de registro de encabezado*/

    };

    /*** prototipos para las funciones usadas por el
    cargador **/

    struct enc_ejec leer_enc(file*);

    char leer_byte(file*);

    char *obtener_memoria(unsigned int);

    /***______________el cargador____________
    ***/

    unsigned int *carga(file *arch_ejec)

    {

    struct enc_ejec encabezado;

    char *dir_byte, *dir_carga;

    unsigned int tamaño_prog;

    encabezdo=leer_enc(arch_ejec);

    /* determinar el tamaño del programa y asignarle
    espacio */

    tamaño_prog=encabezado.tamaño_texto+
    encabezado.tamaño_datos+
    encabezado.tamaño_bss;

    dir_carga=obtener_memoria(tamaño_prog);

    /* copiar los segmentos de textos y datos */

    dir_byte=dir_carga;

    while(leof(arch_ejec);)

    {

    *dir_byte=leer_byte(arch_ejec);

    dir_byte=dir_byte+1;

    }

    /* establecer la correspondencia de direcciones
    */

    establecer_correspondencia(dir_carga,tamaño_prog);

    return(char*)encabezado.dir_ini);

    }

    FIGURA 10.18 seudo código para un cargador
    sencillo (relocalizable)

    Cuando varios programas comparten la memoria principal
    puede no ser conveniente decidir por adelantado en que
    región de la memoria debe cargarse un módulo en
    particular es mejor tomar esa decisión en el momento de
    carga. Así pues se necesita un módulo de carga que
    pueda ubicarse en cualquier posición de la memoria
    principal. Para satisfacer este nuevo requisito el ensamblador o
    el compilador no generará direcciones reales de memoria
    principal (direcciones absolutas) si no direcciones relativas a
    algún punto conocido, tal como el comienzo del programa
    esta técnica se ilustra en la siguiente figura que es la
    6.13. al comienzo de módulo de carga se le asigna la
    dirección relativa 0 y todas las demás referencias
    dentro del módulo se expresan en relación al
    comienzo del módulo.

    Con todas las referencias a memoria expresadas en forma
    relativa, situar los módulos en la posición deseada
    se convierte en una tarea sencilla para el cargador, si el
    módulo va a ser cargado comenzando por la dirección
    x el cargador simplemente sumará x a cada referencia a
    memoria a medida que cargue el módulo en memoria. Para
    ayudar en esta tarea el módulo de carga debe incluir
    información que indique el cargador dónde
    están las referencias a direcciones y como se interpreten
    (generalmente de forma relativa al comienzo del programa pero
    también es posible que sean relativas a algún otro
    punto del programa, como la posición actual). El
    compilador prepara este conjunto de información que se
    conoce como carga relozalizable.

    3.6 Ligaduras De Subrutinas

    Al estudiar subrutinas es conveniente identificar dos
    funciones distintas : el invocador y el invocado.

    El invocador : es la sección de código que
    inicia la llamada a la subrutina.

    El invocado: es la subrutina llamada por el
    invocador.

    Examinaremos las transferencias de control necesarias
    para implantar la invocación de subrutinas. Al efectuar
    una llamada se transfiere el control al cuerpo de la subrutina;
    cuando esta concluye, devuelve el control a la instrucción
    que está inmediatamente después de la llamada a la
    subrutina desde diversos puntos en el programa, las subrutinas
    deben ser capaces de regresar a distintos lugares del programa.
    La dirección de retorno es la dirección de la
    instrucción que esta inmediatamente después de la
    instrucción que transfiere el control al invocado. El
    invocador proporciona la dirección del retorno al invocado
    como parte de enlace de la subrutina.

    El enlace de subrutina es la estructura con que
    se comparte información sobre el invocador y el invocado.
    El invocador establece parte del enlace de subrutina en una
    secuencia de instrucciones llamada secuencia de arranque.
    El invocado establece lo que resta del enlace de subrutina en el
    prologo de subrutina, el cuál puede estar vacío
    como suponemos de todas las rutinas están bien
    estructuradas, las instrucciones al final de la subrutina
    regresan al invocador. Está secuencia de instrucciones se
    denomina epílogo de subrutina . cuando el control
    regresa al invocador, es posible que este tenga que limpiar el
    enlace; este conjunto de instrucciones se denomina secuencia de
    limpieza y también puede estar vacía.

    En la siguiente figura se presenta un ejemplo de
    secuencia de código:

    Para ver el gráfico seleccione la
    opción "Descargar" del menú superior

    FIGURA 6.1 enlace de subrutina

     Llamada subrutina

     Para ver el
    gráfico seleccione la opción
    "Descargar" 

     La presentación de la figura 6.1 es un poco
    engañosa. Al mostrar lado a lado los componentes del
    programa parece que es posible ver las cuatro secuencias del
    código al mismo tiempo. Sin embargo, esto ocurre rara vez.
    El invocador y el invocado pueden estar separados por varias
    páginas en el listado del programa, además puede
    haber muchas llamadas separadas a la misma rutina. Como las
    secuencias del código están distribuidas por todo
    el programa, no es fácil correlacionar las acciones
    realizadas por estás secciones de código
    relacionadas. Así que es importante adoptar un convenio de
    llamadas a subrutinas cuando escriba código que llame a
    una subrutina o implante el cuerpo de una subrutina. En esencia
    un convenio se llamada subrutina describe la asignación,
    construcción y designación, de
    enlace de subrutina, el enlace debe incluir la dirección
    de retorno, un convenio de llamada especialmente simple almacena
    la dirección de retorno en un registro. Usaremos el
    registro R31 para almacenar la dirección, en la siguiente
    figura se documenta este convenio de llamada listando las
    acciones realizadas en cada secuencia de
    código.

    Secuencia de arranque:

    Almacenar la dirección de retorno R31

    Ramificar a la subrutina

    Prologo de subrutina:

    Nada

    Epílogo de subrutina:

    Ramificar a la dirección almacenada en
    R31

    Secuencia de limpieza:

    Nada

    Convenio de codificación: modos de
    direccionamiento e instrucciones BRANCH

    Observe que el epílogo de subrutina presentado
    usa direccionamiento indirecto por registro con una
    instrucción BRANCH. Muchas máquinas no permiten
    usar de esta manera los modos de direccionamiento pero cuentan
    con operaciones especiales, por ejemplo una operación que
    asigna al contador del programa el valor almacenado en un
    registro.

    Convenio de codificación: ranuras de retardo
    BRANCH

    La mayoría de las máquinas RISC tienen una
    ranura de retardo de ramificación después de cada
    instrucción BRANCH, incluyendo aquellas con que se
    implantan convenios a subrutinas. Seguiremos ignorando la
    posibilidad de ranuras de retardo de ramificación en
    nuestros ejemplos de código.

    Para disponer de subrutinas muchas máquinas
    proporcionan una instrucción que almacena la
    dirección de retorno y hace una ramificación al
    inicio de la subrutina. Algunas máquinas llaman a esta
    operación JSR (jump to subroutine: salto de subrutina)
    otras usan el nombre BL( branch and link: ramificación y
    enlace) ya que la instrucción es una ramificación
    que establece un enlace de subrutina.

    Estas instrucciones requieren tres operandos: uno para
    especificar la dirección de

    retorno, otra para indicar almacenar la dirección
    de retorno y un tercero para especificar la dirección
    inicial de la subrutina el primer operando por lo general no
    está explícitamente en la instrucción si no
    se supone que el operando es la dirección de la siguiente
    instrucción. El segundo operando puede ser
    implícito o explicito dependiendo de la máquina. En
    la especificación implícita la máquina
    designa un registro como de enlace, en el cuál almacena la
    dirección de retorno durante la ejecución de la
    instrucción llamada subrutina. El último operando
    la dirección inicial para la subrutina, por lo general es
    un operando explicito en la instrucción.

    : :otras instrucciones

    :secuencia de arranque

    : no hay secuencia de limpieza

    BL R31

    :otras instrucciones

    : otras partes del programa

    SUB 1 : no hay prologo

    EJEMPLO 6.2 muestra como
    puede usar una instrucción BL en el fragmento de
    código.

    www.google.com,
    www.monografías.com,
    www.t1msn.com

    Sistemas computacionales.- MACCABE.- MCGRAWLL
    HILL

    UNIDAD IV
    COMPILADORES

    1. Funciones de un compilador

    Un compilador es un programa que lee un programa escrito
    en un lenguaje fuente y lo traduce a un programa
    equivalente en otro lenguaje, el lenguaje objeto [Aho et al.
    1990]. Como parte importante de este proceso de
    traducción, el compilador informa al usuario de la
    presencia de errores en el programa fuente.

    En la compilación hay dos partes análisis y síntesis .
    Durante el análisis se determinan las operaciones que
    implica el programa fuente y se registran en una estructura
    jerárquica llamada árbol. A menudo se usa una clase
    especial de árbol llamado árbol sintáctico ,
    donde cada nodo representa una operación y los hijos del
    nodo son los argumentos de la operación.

    Fases de un Compilador

    Un compilador típicamente opera en fases , cada
    una lleva a cabo una tarea sobre el programa fuente. La figura
    4.1 , muestra la descomposición en fases de un
    compilador.

    Las primeras tres fases suelen agruparse en una sola
    fase llamada fase de análisis y las últimas tres en
    una llamada fase de síntesis. La fase de análisis y
    el modulo de manejo de errores se describen posteriormente en
    este mismo capítulo. La fase de síntesis no es
    relevante en el contexto de un lenguaje multibase de datos, ya
    que este sigue un enfoque diferente que el de los lenguajes
    tradicionales, por esta razón solo se menciona.

    Muchas herramientas de software que manipulan programas
    fuente realizan primero algún tipo de análisis,
    entre estas se encuentran los editores de estructuras,
    impresoras estéticas, verificadores estáticos y los
    interpretes1 .

    Figura 4.1

    Tipos de compiladores

    Compilador cruzado: Es el que genera un
    código objeto ejecutable en un ordenador distinto de
    aquél en el que se realiza la
    compilación.

    Compilación-Montaje-Ejecución: En
    las aplicaciones grandes es conveniente fragmentar el programa a
    realizar en módulos que se compilan por separado, y una
    vez que estos estén compilados unirlos mediante un
    programa denominado montador para formar el módulo
    ejecutable. El montador se encarga, a su vez, de incluir las
    librerías donde están guardadas las funciones
    predefinidas de uso común.

    Compilación en una o varias pasadas: Se
    llama pasada a cada lectura que hace el compilador del
    texto fuente.

    Compilación incremental. Este compilador
    actúa de la siguiente manera. Compila un programa fuente.
    Caso de detectar errores al volver a compilar el programa
    corregido sólo compila las modificaciones que se han hecho
    respecto al primero.

    Autocompilador: Es aquél que está
    escrito en el mismo lenguaje que se pretende compilar.
    Supongamos, por ejemplo, que queremos desarrollar la
    versión 2.0 de un compilador Pascal. Dicho
    compilador generará un código mucho más
    rápido y eficiente que el que generaba la versión
    anterior 1.0. Sin embargo, son ya muchas las máquinas (IBM
    370, Serie 1, PDP 11, …) que disponen del antiguo compilador, o
    que al menos tienen otro compilador Pascal. La mejor
    opción consiste en escribir el nuevo compilador en Pascal,
    ya que así podrá (el compilador) ser compilado en
    las distintas máquinas por los compiladores Pascal ya
    existentes.

    Metacompilador: Es un traductor que tiene como
    entrada la definición de un lenguaje y como salida el
    compilador para dicho lenguaje2.

    Decompilador: Es el que traduce código
    máquina a lenguaje de alto nivel. Los decompiladores
    más usuales son los desensambladores, que traducen un
    programa en lenguaje máquina a otro en
    ensamblador.

    Bootstrapping: Es una técnica muy usada
    actualmente para el desarrollo de
    compiladores de lenguajes de alto nivel, en especial si se quiere
    obtener un autocompilador, o sea, un compilador que se compile a
    sí mismo.

    Para describir el proceso de autocompilación se
    emplea la notación en T que representa gráficamente
    los tres lenguajes implicados en el proceso de
    compilación:

    Lenguaje fuente: Lenguaje origen que traduce el
    compilador.

    Lenguaje objeto: Lenguaje meta, al cuál
    traduce el compilador.

    Lenguaje del compilador: Lenguaje en el que
    está escrito el compilador.

    Análisis lexicográfico.

    La cadena de caracteres que constituye el programa
    fuente se lee de izquierda a derecha y se agrupa en componentes
    léxicos, que son secuencias de caracteres que tienen un
    significado colectivo. El análisis léxico se
    encarga de hacer esta agrupación1.

    Las principales funciones que realiza son:

    Identificar los símbolos.

    Eliminar los blancos, caracteres de fin de línea,
    etc…

    Eliminar los comentarios que acompañan al
    fuente.

    Crear unos símbolos intermedios llamados
    tokens.

    Avisar de los errores que detecte.

    Ejemplo: A partir de la sentencia en PASCAL
    siguiente

    nuevo := viejo + RAZON*2

    genera un código simplificado para el
    análisis sintáctico posterior, por
    ejemplo:

    <id1> <:=> <id2> <+> <id3>
    <*> <ent>

    Nota: Cada elemento encerrado entre <> representa
    un único token. Las abreviaturas id y ent significan
    identificador y entero, respectivamente2.

    Análisis sintáctico

    Implica agrupar los componentes léxicos en frases
    gramaticales que el compilador utiliza para sintetizar la salida.
    Por lo general, las frases gramaticales del programa fuente se
    representan mediante un árbol de análisis
    sintáctico como el que se ilustra en la figura
    4.3.

    Figura 4.3

    La división entre el análisis
    léxico y el análisis sintáctico es algo
    arbitraria. Generalmente se elige una división que
    simplifique la tarea completa del análisis. Un factor para
    determinar la división es si una construcción es
    inherentemente recursiva o no. Las construcciones léxicas
    no requieren recursión, mientras que las construcciones
    sintácticas suelen requerirla. Las gramáticas
    independientes de contexto son una formalización de reglas
    recursivas que se pueden usar para guiar el análisis
    sintáctico1.

    Comprueba que las sentencias que componen el texto
    fuente son correctas en el lenguaje, creando una
    representación interna que corresponde a la sentencia
    analizada. De esta manera se garantiza que sólo
    serán procesadas las sentencias que pertenezcan al
    lenguaje fuente. Durante el análisis sintáctico,
    así como en las demás etapas, se van mostrando los
    errores que se encuentran.

    Ejemplo: El esquema de la sentencia anterior
    corresponde al de una sentencia de asignación del lenguaje
    Pascal. Estas sentencias son de la forma:

    • <id> <:=> <EXPRESION>
    • y la parte que se denomina <EXPRESION> es de la
      forma2:
    • <id> <+> <EXPRESION> o
      bien
    • <id> <*> <EXPRESION> o
      bien
    • <real>

    La estructura de la sentencia queda, por tanto, de
    manifiesto mediante el siguiente esquema:

    <id1> <:=> <EXPRESION> / |
    <id2> <+> <EXPRESION> / | <id3>
    <*> <EXPRESION> | <real>

    Análisis semántico

    La fase de análisis semántico utiliza la
    estructura sintáctica determinada por la fase de
    análisis sintáctico para identificar los operadores
    y operandos de expresiones y proposiciones. En el caso de un
    interprete de consultas se debe validar que los nombres de
    atributos y de relaciones sean válidos y tengan sentido
    desde el punto de vista semántico.

    Un componente importante del análisis
    semántico es la verificación de tipos. Aquí,
    el interprete verifica si cada operador tiene operandos
    permitidos por la especificación del lenguaje fuente y
    verifica la compatibilidad de los tipos cuando estos están
    involucrados, por ejemplo, en una
    condición1.

    Se ocupa de analizar si la sentencia tiene algún
    significado. Se pueden encontrar sentencias que son
    sintácticamente correctas pero que no se pueden ejecutar
    porque carecen de sentido. En general, el análisis
    semántico se hace a la par que el análisis
    sintáctico introduciendo en éste unas rutinas
    semánticas.

    Ejemplo: En la sentencia que se ha analizado
    existe una variable entera. Sin embargo, las operaciones se
    realizan entre identificadores reales, por lo que hay dos
    alternativas: o emitir un mensaje de error "Discordancia de
    tipos", o realizar una conversión automática al
    tipo superior, mediante una función auxiliar
    inttoreal2.

    <id1> <:=> <EXPRESION> / |
    <id2> <+> <EXPRESION> / | <id3>
    <*> <EXPRESION> | <real> | <inttoreal> |
    <int>

    Generación de código
    intermedio.

    El código intermedio es un código
    abstracto independiente de la máquina para la que se
    generará el código objeto. El código
    intermedio ha de cumplir dos requisitos importantes: ser
    fácil de producir a partir del análisis
    sintáctico, y ser fácil de traducir al lenguaje
    objeto. Esta fase puede no existir si se genera directamente
    código máquina, pero suele ser conveniente
    emplearla.

    Ejemplo: Consideremos, por ejemplo, un
    código intermedio de tercetos, llamado así porque
    en cada una de sus instrucciones aparecen como máximo tres
    operandos. La sentencia traducida a este código intermedio
    quedaría2:

    temp1 := inttoreal (2)temp2 := id3 * temp1temp3 := id2 +
    temp2id1 := temp3

    Generación de código
    completo.

    A partir de los análisis anteriores y de las
    tablas que estos análisis van creando durante su
    ejecución produce un código o lenguaje objeto que
    es directamente ejecutable por la máquina. Es la fase
    final del compilador. Las instrucciones del código
    intermedio se traducen una a una en código máquina
    reubicable.

    Nota: Cada instrucción de código
    intermedio puede dar lugar a más de una de código
    máquina.

    Ejemplo: El código anterior traducido a
    ensamblador DLX quedaría:

    LW R1,id3MUL R1,R1,2LW R2,id2ADD R2,R2,R1SW
    id1,R2

    en donde id1, id2 y id3 representan las posiciones de
    memoria en las que se hallan almacenadas estas variables; R1 y R2
    son los registros de la máquina; y las instrucciones LW,
    SW, MUL y ADD representan las operaciones de colocar un valor de
    memoria en un registro, colocar un valor de un registro en
    memoria, multiplicar en punto flotante y sumar,
    respectivamente2.

    Optimización de código

    A partir de todo lo anterior crea un nuevo código
    más compacto y eficiente, eliminando por ejemplo
    sentencias que no se ejecutan nunca, simplificando expresiones
    aritméticas, etc… La profundidad con que se realiza esta
    optimización varía mucho de unos compiladores a
    otros. En el peor de los casos esta fase se suprime.

    Ejemplo: Siguiendo con el ejemplo anterior, es
    posible evitar la función inttoreal mediante el cambio de 2
    por 2.0, obviando además una de las operaciones
    anteriores. El código optimizado queda como
    sigue2 :

    temp1 := id3 * 2.0id1 := id2 + temp1

    Herramientas generadoras de
    compiladores

    Esta es una lista de las herramientas más
    conocidas para la construcción de compiladores. Si conoce
    otro generador que no figure en esta lista, por favor hága
    saber.
    Se agradecerá informar sobre la desactualización de
    alguno de los enlaces.

    Nombre: Lex y Yacc 

    Descripción: los generadores más populares
    de analizadores léxicos y sintácticos
    LALR(1).

    Lenguaje: Pascal – C

    Download:
    Turbo Pascal y FPK

    Nombre: Flex y Bison 

    Descripción: versiones mejoradas (generan
    analizadores más rápidos) de Lex y Yacc.

    Lenguaje: C

    Download: Linux
    DOS

    Nombre: BTYacc (Back Tracking Yacc)

    Descripción: es una versión modificada de
    yacc que genera parsers con capacidad de backtracking
    automático.

    Lenguaje: C

    Download: DOS

    Nombre: BYacc (Berkeley Yacc)

    Descripción: es un generador de parsers LALR(1)
    de dominio
    público compatible con AT&T Yacc (el Yacc
    original).

    Lenguaje: C

    Download:

    Nombre: YAY (Yet Another YACC)

    Descripción: es un generador de analizadores
    sintácticos ascendentes similar a Yacc pero con una
    extensión sumamente importante: soporta gramáticas
    LALR(2).

    Lenguaje: C

    Download: DOS

    Nombre: ParseGenerator

    Descripción: es una IDE (Entorno Integrado de
    Desarrollo), bajo Windows32, para los generadores AYACC y 
    ALEX, clones de Yacc y Lex respectivamente.

    Lenguaje: C – C++

    Download: Win32

    Nombre: Eli 

    Descripción: ofrece soluciones a
    casi todas las tareas relacionadas con la implementación
    de un lenguaje.

    Lenguaje:

    Download: ELI

      Nombre: COCKTAIL

    Descripción: es un conjunto de generadores de
    programas para casi todas las fases de un compilador. LALR(1) –
    LL(1) – Generador de ASTs – Evaluador de Atributos – Herramienta
    de transformación de programas.

    Lenguaje: 

    Download: COCKTAIL

    Nombre: PCCTS 

    Descripción: es un conjunto de herramientas para
    la construcción de traductores y reconocedores de
    lenguajes. Comprende tres herramientas: ANTLR un generador de
    parsers LL(k), DLG un analizador de analizadores léxicos y
    SORCERER un generador de parsers para árboles
    que le permite al programador definir la estructura del
    árbol por medio de una gramática.

    Lenguaje:

    Download: PCCTS

    Nombre: Coco/R

    Descripción: es un generador de parsers
    descendentes.

    Lenguaje: 

    Download: COCO(R)

    Nombre: Depot4 

    Descripción: es un generador de parsers
    descendentes que soporta especificaciones al etilo de la
    traducción dirigida por la sintaxis.

    Lenguaje: 

    Download: Depot4

    Nombre: LLgen 

    Descripción: es una herramienta para generar
    parsers descendentes a partir de una gramática
    ELL(1).  La gramática puede ser ambigua o más
    general que una ELL(1).

    Lenguaje: 

    Download: LLGEN

    Nombre: PRECC

    Descripción: es un generador de compiladores para
    gramáticas dependientes del contexto con infinito
    lookahead.

    Lenguaje: 

    Download: PRECC

    Nombre: RDP

    Descripción: es un generador de parsers
    descedentes para gramáticas LL(1).

    Lenguaje: 

    Download: RDP

    Nombre: Visual Parse++

    Descripción:  provee una interfase visual
    que permite aprender y utilizar, de manera interactiva, la
    tecnología
    de parsing. Genera parsers en C, C++, VBasic y Java.

    Lenguaje: 

    Download: VISUALPARSE++

    Nombre: AnaGram

    Descripción:  es un generador de parsers
    LALR con resincronización automática en presencia
    de errores. Usualmente no necesita de un analizador
    léxico.

    Lenguaje: 

    Download: AnaGram

    Nombre: TCLL1

    Descripción: es un generador de parsers
    descendentes para gramáticas LL(1) y LL(k).

    Lenguaje: 

    Download: TCLL1

    Nombre: Elegant (recomendado por David
    Riemens)

    Descripción: es un lenguaje orientado a la
    construcción de compiladores desarrollado por 
    Phillips y puesto a dispocisión del público en
    1997.

    Lenguaje: 

    Download:
    Elegant

    Nombre: Cogencee (link recomendado por Peter
    Evans) 

    Descripción: generador de parsers descendentes en
    Delphi.

    Lenguaje: Delphi

    Download: Cogencee

    Nombre: ProGrammar (link recomendado por Norm
    Wilson)

    Descripción: un moderno generador de parsers
    OO.

    Lenguaje: 

    Download: ProGrammar

    Una lista más extensa herramientas puede
    encontrarse en Catalog
    of Compiler Construction
    Tools

    (c) 2000 Compiladores e Intérpretes

    http://www.ucse.edu.ar/fma/compiladores/

    Salvador V. Cavadini

     UNIDAD V
    INTERPRETES

    Principios de la
    interpretación.

    En lugar de producir un programa objeto como resultado
    de una traducción, un intérprete realiza las
    operaciones que implica el programa fuente. Por ejemplo un
    interprete podría construir un árbol, y
    después efectuar las operaciones de los nodos conforme
    recorre el árbol.

    Muchas veces los interpretes se utilizan para ejecutar
    lenguajes de órdenes, pues cada operador que se ejecuta en
    un lenguaje de este tipo suele ser una invocación de una
    rutina, como un editor o un compilador. Del mismo modo algunos
    lenguajes de alto nivel son interpretados, porque hay muchas
    cosas sobre los datos, como el tamaño y la forma de las
    matrices que
    no se pueden deducir en el momento de la
    compilación1.

    Intérprete: Es un traductor que realiza la
    operación de compilación paso a paso. Para
    cada sentencia que compone el texto de entrada, se realiza una
    traducción, ejecuta dicha sentencia y vuelve a iniciar el
    proceso con la sentencia siguiente. La principal ventaja del
    proceso de compilación frente al de interpretación
    es que los programas se ejecutan mucho más
    rápidamente una vez compilados; por el contrario, es
    más cómodo desarrollar un programa mediante un
    intérprete que mediante un compilador puesto que en el
    intérprete las fases de edición y ejecución
    están más integradas. La depuración de los
    programas suele ser más fácil en los
    intérpretes que en los compiladores puesto que el
    código fuente está presente durante la
    ejecución. Estas ventajas pueden incorporarse al
    compilador mediante la utilización de entornos de
    desarrollo y depuradores simbólicos en tiempo de
    ejecución2.

    Diferencia entre un interprete y
    compilador

    INTERPRETE: Es un programa que lee línea a
    línea un programa escrito en un lenguaje; en lenguaje
    fuente y lo va traduciendo a un código intermedio, para
    ejecutarlo.

    COMPILADOR: Es un programa que lee totalmente un
    programa escrito en un lenguaje; el lenguaje fuente, y lo traduce
    a un programa equivalente a otro lenguaje, lenguaje
    objeto.

     

     

     

     

     

    Autor:

    LAS MISMAS.COM

    Pérez Rivera Marlene

    Jiménez Márquez María Del
    Rosario

    Castillo García Brenda Berenice

    Gutiérrez Simon Flavia Marisol

    Crespo Loto Karina

    Correo electrónico:

    Girl_yahua [arroba] hotmail.com

    Rossjim21 [arroba] hotmail.com

    Brendiz81 [arroba] hotmail.com

     

    Nota al lector: es posible que esta página no contenga todos los componentes del trabajo original (pies de página, avanzadas formulas matemáticas, esquemas o tablas complejas, etc.). Recuerde que para ver el trabajo en su versión original completa, puede descargarlo desde el menú superior.

    Todos los documentos disponibles en este sitio expresan los puntos de vista de sus respectivos autores y no de Monografias.com. El objetivo de Monografias.com es poner el conocimiento a disposición de toda su comunidad. Queda bajo la responsabilidad de cada lector el eventual uso que se le de a esta información. Asimismo, es obligatoria la cita del autor del contenido y de Monografias.com como fuentes de información.

    Categorias
    Newsletter