libro programación de sistemas

64
La informática es la ciencia que se encarga de la automatización del manejo de la información. La informática, por su rapidez de crecimiento y expansión, Ha venido transformando rápidamente las sociedades actuales. La computadora, a diferencia de otras herramientas que en general apoyan el esfuerzo físico de los Humanos, fue inventada para facilitar el trabajo intelectual. El lenguaje de programación es el medio de comunicación entre el Hombre y la máquina. Sistema de símbolos y reglas que permite la construcción de programas con los que la computadora puede operar así como resolver problemas de manera eficaz. Estos contienen un conjunto de instrucciones que nos permiten realizar operaciones de entrada / salida, calculo, manipulación de textos, lógica / comparación y almacenamiento / recuperación. La programación tiene como objetivo el tratamiento de la información correctamente, con lo que se espera que un programa de el resultado correcto y no uno erróneo. Así que cada aplicación debe funcionar según lo esperado en términos de programación, esta pretende que sus programas sean útiles y eficientes Un sistema es un conjunto de componentes que interaccionan entre sí para lograr un objetivo común. Las personas se comunican con el lenguaje, que es un sistema muy desarrollado formado por palabras y símbolos que tienen significado que tienen significado para el que Habla y para quienes lo escuchan, lo mismo es para las computadoras las cuales tienen sistemas y se comunican por medio de computadoras. La programación es el proceso de convertir las especificaciones a grandes rasgos de los sistemas en instrucciones de máquina que produzcan los resultados deseados. Por lo tanto la Programación de Sistemas se refiere a la creación de programas cuya finalidad es servir a otros programas (software) ejemplos; Ensambladores, Cargadores y Ligadores, Compiladores, intérpretes. El Software es un conjunto de programas, documentos, procedimientos, y rutinas asociados con la operación le un sistema de computo. Distinguiéndose de los componentes físicos llamados hardware. El hardware por sí solo no puede hacer nada, pues es necesario que exista el software. El software de manera general, podemos clasificarlo en: Software de sistema: en algunas ocasiones también denominado software de base, consiste en un software que sirve para controlar e interactuar con el sistema, proporcionando control sobre el hardware y dando soporte a otros programas. Software de aplicación: 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. ♦♦♦ Software de uso general: este ofrece la estructura para un gran número de aplicaciones empresariales, científicas y personales. La mayoría de software para uso general se vende como paquete; es decir, con software y documentación orientada a los usuarios (manuales de referencia, plantillas de teclado y demás).

Upload: jjmercedes

Post on 09-Aug-2015

267 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Libro Programación de Sistemas

La informática es la ciencia que se encarga de la automatización del manejo de la información. La

informática, por su rapidez de crecimiento y expansión, Ha venido transformando rápidamente las

sociedades actuales. La computadora, a diferencia de otras herramientas que en general apoyan el

esfuerzo físico de los Humanos, fue inventada para facilitar el trabajo intelectual.

El lenguaje de programación es el medio de comunicación entre el Hombre y la máquina. Sistema

de símbolos y reglas que permite la construcción de programas con los que la computadora puede

operar así como resolver problemas de manera eficaz. Estos contienen un conjunto de

instrucciones que nos permiten realizar operaciones de entrada / salida, calculo, manipulación de

textos, lógica / comparación y almacenamiento / recuperación. La programación tiene como

objetivo el tratamiento de la información correctamente, con lo que se espera que un programa

de el resultado correcto y no uno erróneo. Así que cada aplicación debe funcionar según lo

esperado en términos de programación, esta pretende que sus programas sean útiles y eficientes

Un sistema es un conjunto de componentes que interaccionan entre sí para lograr un objetivo

común. Las personas se comunican con el lenguaje, que es un sistema muy desarrollado formado

por palabras y símbolos que tienen significado que tienen significado para el que Habla y para

quienes lo escuchan, lo mismo es para las computadoras las cuales tienen sistemas y se comunican

por medio de computadoras.

La programación es el proceso de convertir las especificaciones a grandes rasgos de los sistemas

en instrucciones de máquina que produzcan los resultados deseados.

Por lo tanto la Programación de Sistemas se refiere a la creación de programas cuya finalidad es

servir a otros programas (software) ejemplos; Ensambladores, Cargadores y Ligadores,

Compiladores, intérpretes.

El Software es un conjunto de programas, documentos, procedimientos, y rutinas asociados con la

operación le un sistema de computo. Distinguiéndose de los componentes físicos llamados

hardware. El hardware por sí solo no puede hacer nada, pues es necesario que exista el software.

El software de manera general, podemos clasificarlo en:

❖ Software de sistema: en algunas ocasiones también denominado software de base, consiste en

un software que sirve para controlar e interactuar con el sistema, proporcionando control sobre el

hardware y dando soporte a otros programas.

❖ Software de aplicación: 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.

♦♦♦ Software de uso general: este ofrece la estructura para un gran número de aplicaciones

empresariales, científicas y personales. La mayoría de software para uso general se vende como

paquete; es decir, con software y documentación orientada a los usuarios (manuales de

referencia, plantillas de teclado y demás).

Page 2: Libro Programación de Sistemas

El trabajo de un programador de sistemas es seleccionar, modificar y mantener el complejo

software del sistema operativo. Por lo tanto, los programadores de sistemas desempeñan una

función de apoyo al mantener el ambiente de software del sistema operativo en el que trabajan

los programadores de aplicaciones y los operadores de las computadoras. También participan en

las decisiones relativas a reducciones o ampliaciones de hardware y/o software. Programación de

Sistemas Conceptos y Aplicaciones Se entiende por programación de sistemas el conjunto de

programas necesario para que una computadora de una imagen coherente y monolítica ante sus

usuarios. Es un área especializada dentro de las ciencias de la computación. Así, mediante la

programación de sistemas, no solo se manejan las computadoras por medio del lenguaje maquina

(0 y 1) sino por otros sistemas operativos, sin lo cual sería muy difícil la interacción con la maquina.

1. ESTRUCTURA DE LA COMPUTADORA

Objetivo: Entender con detalle los procesos lógicos que suceden en una computadora para que

pueda ejecutar un programa en lenguaje máquina de una plataforma que en particular se define al

iniciar el curso.

1-.Arquitectura de von Neumann

Cuando se describe una computadora se debe distinguir entre arquitectura y organización.

• La arquitectura de computadoras que se refiere a los atributos de un sistema que son visibles a

un programador, es decir aquellos atributos que tienen un impacto directo en la ejecución lógica

de un programa. Ejemplos de atributos arquitectónicos: conjunto de instrucciones, número de bits

usados para representar datos, mecanismos de entrada salida y técnicas de direccionamiento de

memoria. También suele definirse como la forma de seleccionar e interconectar componentes de

hardware para crear computadoras según los requerimientos de funcionalidad, rendimiento y

costo.

• La organización de computadoras que se refiere a las unidades funcionales y sus

interconexiones, que materializan especificaciones arquitectónicas. Ejemplos de atributos de

organización: son los detalles del hardware transparentes para el programador, tales como

señales de control, interfaces entre la computadora y los periféricos y la tecnología de memoria

utilizada. Por poner un ejemplo, una cuestión de arquitectura es si la computadora tendrá la

instrucción de multiplicar. Una cuestión de organización es si esa instrucción será implementada

por una unidad especializada en multiplicar o por un mecanismo que haga un uso iterativo de la

unidad de suma del sistema.

La unidad central de procesamiento, CPU (por sus siglas del inglés Central Processing Unit), o,

simplemente, el procesador, es el componente en una computadora digital que interpreta las

instrucciones y procesa los datos contenidos en los programas de computadora. La CPU

proporciona la característica fundamental de la computadora digital: la programabilidad, y es uno

de los componentes necesarios encontrados en las computadoras de cualquier tiempo, junto con

el almacenamiento primario y los dispositivos de entrada/salida. Desde mediados de los años

Page 3: Libro Programación de Sistemas

1970, los microprocesadores de un solo chip han reemplazado casi totalmente todos los tipos de

CPU, y hoy en día, el término "CPU" es aplicado usualmente a todos los microprocesadores

Las funciones básicas que una computadora puede llevar a cabo son: Procesamiento de datos,

Almacenamiento de datos, Transferencia de datos, Control

La computadora es una entidad que interactúa de alguna manera con su entorno externo. En

general, todas sus conexiones con el exterior pueden ser clasificadas como dispositivos periféricos

o líneas de comunicación. Hay cuatro componentes estructurales principales:

♦> Unidad de Procesamiento Central (CPU): controla el funcionamiento de la computadora y lleva

a cabo las funciones de procesamiento de datos. Frecuentemente se le llama procesador.

❖ Memoria Principal: es el dispositivo en el cual se almacenan datos.

❖ E/S: transfiere datos entre la computadora y el exterior.

❖ Sistema de /interconexión (Bus del sistema): es un mecanismo que proporciona la comunicación

entre la CPU, la memoria y E/S.

1.1.1 CPU

❖ Unidad de Control: controla el funcionamiento de la CPU y por tanto de la computadora.

❖Unidad Aritmética y Lógica (ALU): lleva a cabo las funciones de procesamiento de datos.

❖ Registros: proporciona almacenamiento interno para la CPU.

❖ interconexión interna de la CPU: son mecanismos que proporcionan comunicación entre la

unidad de control, ALU y registros.

La ENIAC (Electronic Numerical Integrator And Computer) fue la primera computadora electrónica

de uso general en el mundo. Uno de los inconvenientes más grandes de la ENIAC era que tenía que

ser programada manualmente mediante conmutadores y conectando y desconectando cables. El

proceso de programación podría ser más fácil si el programa se representará en una forma

adecuada para ser guardado en la memoria junto con los datos. Entonces, la computadora

conseguiría sus instrucciones leyéndolas de la memoria, y se podría hacer o modificar un

programa escribiendo en una zona de memoria. John von Neumann en imagen.

La idea central del modelo de computación propuesto por John Von Neumann es almacenar las

instrucciones del programa de una computadora en su propia memoria, logrando con ello que la

máquina siga los pasos definidos por su programa almacenado.

1.1.2 Memoria

Page 4: Libro Programación de Sistemas

La memoria se puede definir como los circuitos que permiten almacenar y recuperar la

información. En un sentido más amplio, puede referirse también a sistemas externos de

almacenamiento, como las unidades de disco o de cinta. Para nuestros propósitos, la memoria

será un conjunto de celdas (o casillas) con las siguientes características:

1. cada celda puede contener un valor numérico

John von Neumann (28 dic. 1903 - 8 feb. 1957) matemático húngaro-estadounidense, de

ascendencia judía, realizó contribuciones importantes en física cuántica, análisis funcional, teoría

de conjuntos, informática, economía, análisis numérico, hidrodinámica (de explosiones),

estadística y muchos otros campos de la matemática. Recibió su doctorado en matemáticas de la

Universidad de Budapest a los 23 años.

2. cada celda tiene la propiedad de ser direccionable, es decir, se puede distinguir una de otra por

medio de un número unívoco que es su dirección.

3. Las celdas de memoria están organizadas en forma de vector, que no es más que un conjunto

de celdas numerado secuencialmente.

Como se dijo, se puede hacer referencia a una celda por medio de su dirección. Se usará un

apuntador para dirigirse a alguna celda cualquiera.

Una memoria para efectuar una lectura se deposita en el bus de direcciones la dirección de la

palabra de memoria que se desea leer y entonces se activa la señal de lectura; después de cierto

tiempo (retardo), en el bus de datos aparecerá el contenido de la dirección buscada. Por otra

parte, para realizar una escritura se deposita en el bus de datos la información que se desea

escribir y en el bus de direcciones la dirección donde deseamos escribirla, entonces se activa la

señal de escritura (escritura), pasado el tiempo de retardo, la memoria escribirá la información en

la dirección deseada. Internamente la memoria tiene un registro de dirección (MAR, memory

address register), un registro buffer de memoria o registro de datos (MB, memory buffer, o MDR,

memory data register) y, un decodificador como se ve en la figura. Esta forma de estructurar la

memoria se llama organización lineal o de una dimensión. En la figura cada línea de palabra activa

todas las celdas de memoria que corresponden a la misma palabra.

El bus se puede definir como un conjunto de líneas conductoras de hardware utilizadas para la

transmisión de datos entre los componentes de un sistema informático. Un bus es en esencia una

ruta compartida que conecta diferentes partes del sistema, como el microprocesador, la

controladora de unidad de disco, la memoria y los puertos de entrada/salida (E/S), para permitir la

transmisión de información.

En el bus se encuentran dos pistas separadas, el bus de datos y el bus de direcciones (aquí está la

diferencia entre la Arquitectura de Neumann con la de Harvard). La CPU escribe la dirección de la

posición deseada de la memoria en el bus de direcciones accediendo a la memoria, teniendo cada

una de las líneas carácter binario. Es decir solo pueden representar 0 o 1 y de esta manera forman

conjuntamente el número de la posición dentro de la memoria (es decir: la dirección). Cuantas

Page 5: Libro Programación de Sistemas

más líneas haya disponibles, mayor es la dirección máxima y mayor es la memoria a la cual puede

dirigirse de esta forma (es decir si es un dispositivo programable de 1,2 o 3 bytes).

Esto que en le teoría parece tan fácil es bastante más complicado en la práctica, ya que aparte de

los bus de datos y de direcciones existen también casi dos docenas más de líneas de señal en la

comunicación entre la CPU y la memoria, a las cuales también se acude. Todas las tarjetas del bus

escuchan, y se tendrá que encontrar en primer lugar una tarjeta que mediante el envío de una

señal adecuada indique a la CPU que es responsable de la dirección que se ha introducido. Las

demás tarjetas se despreocupan del resto de la comunicación y quedan a la espera del próximo

ciclo. Ejemplo en INTEL:

Estructuras de interconexión

Existen dos organizaciones físicas de operaciones E/S que tienen que ver con los buses que son:

* Bus único: La primera gran diferencia entre estas dos tipos de estructuras es que el bus único no

permite un controlador DMA (todo se controla desde la CPU), mientras que el bus dedicado sí que

soporta este controlados

Bus dedicado: este trata a la memoria de manera distinta que a los periféricos (utiliza un bus

especial) al contrario que el bus único que los considera a ambos como posiciones de memoria

(incluso equipara las Operaciones E/S con las de lectura/escritura en memoria). Este bus especial

que utiliza el bus dedicado tiene 4 componentes fundamentales:

❖ Datos: Intercambio de información entre la CPU y los periféricos.

❖ Control: Lleva información referente al estado de los periféricos (petición de interrupciones).

❖ Direcciones: Identifica el periférico referido.

❖ Sincronización: Temporiza las señales de reloj.

La mayor ventaja del bus único es su simplicidad de estructura que le hace ser más económico,

pero no permite que se realice a la vez transferencia de información entre la memoria y el

procesador y entre los periféricos y el procesador. Por otro lado el bus dedicado es mucho más

flexible y permite transferencias simultáneas. Por contra su estructura es más compleja y por

tanto sus costes son mayores

1.2. Estructura lógica del procesador

La ALU contiene localidades de almacenamiento llamadas registros, definidos de la siguiente

manera:

Page 6: Libro Programación de Sistemas

❖ Registro Temporal de Memoria "Buffer" (MBR): Contiene una palabra que debe ser almacenada

en memoria, o recibe una palabra procedente de la memoria.

❖ Registro de Dirección de Memoria (MAR): Especifica la dirección de memoria de la palabra que

va a ser escrita o leída en MBR.

❖ Registro de /instrucción (IR): Contiene el código de operación de la instrucción que se va a

ejecutar.

❖ Registro Temporal de /instrucción (IBR): Almacena temporalmente la instrucción contenida en

la parte derecha de una palabra.

❖ Contador de Programa (PC): Contiene la dirección de la siguiente pareja de instrucciones que se

traerán de memoria.

❖ Acumulador (AC) Multiplicador Cociente (MQ): Se emplean para almacenar temporalmente

operandos y resultados de operaciones de la ALU.

Virtualmente todas las computadoras se han diseñado basándose en los conceptos desarrollados

por von Neumann. Tal diseño se conoce como Arquitectura de von Neumann y se basa en tres

conceptos clave:

❖ Los datos y las instrucciones se almacenan en una sola memoria de lectura - escritura.

❖ Los contenidos de esta memoria se direccionan indicando su posición, sin considerar el tipo de

dato contenido en la misma.

❖ La ejecución se produce siguiendo una secuencia de instrucción tras instrucción (a no ser que

dicha instrucción se modifique explícitamente).

Ciclo maquina

La función básica de una computadora es ejecutar programas, el cual está compuesto de un

conjunto de instrucciones almacenadas en memoria. La CPU es la encargada de ejecutar las

instrucciones específicas del programa. Para comprender esta función debe considerarse el detalle

del proceso de ejecución del programa.

Desde el punto de vista más simple, se considera el procesamiento de una instrucción en dos

etapas: la CPU lee (busca, trae; fetch en inglés) la instrucción de memoria y la ejecuta. La ejecución

del programa consiste en la repetición del proceso de traer y ejecutar la instrucción.

Page 7: Libro Programación de Sistemas

Buscar una instrucción es una operación común a todas las instrucciones, y consiste en la lectura

de la instrucción de una localidad de memoria. La ejecución de la instrucción puede suponer varias

operaciones y depende de la naturaleza de la instrucción.

El procesamiento de una instrucción se denomina ciclo de instrucción. Los dos pasos se denotan

como ciclo de búsqueda y ciclo de ejecución. La ejecución del programa se detiene sólo si la

computadora se desconecta, se produce algún error o se encuentra una instrucción que detiene la

computadora.

Al principio de cada ciclo de instrucción, la CPU busca o trae una instrucción de memoria. En una

CPU típica, se utiliza un registro llamado contador de programa (PC program counter) para

apuntar a la instrucción que debe traerse a continuación. A no ser que se indique otra cosa, la CPU

siempre incrementa el PC después de traer una instrucción para determinar de dónde traer la

siguiente instrucción de la secuencia (siguiente dirección de memoria).

La instrucción traída se almacena en un registro de la CPU conocido como registro de instrucción

(IR instruction register). La CPU interpreta la instrucción y realiza la acción requerida. En general,

ésta puede ser de cuatro tipos:

• CPU - Memoria: Deben transferirse datos desde la CPU a la memoria o viceversa.

• CPU - E/S: Deben transferirse datos a o desde el exterior mediante el módulo de E/S.

• Procesamiento de datos: La CPU realizará alguna operación aritmética o lógica con los datos.

• Control: Una instrucción puede especificar que la secuencia de ejecución se altere por lo que la

CPU debe poner el contador de programa al valor adecuado.

El ciclo de ejecución de una instrucción puede ocasionar más de una referencia a memoria, o en su

lugar, puede especificar una operación de E/S. Con estas consideraciones en mente, la figura 5

proporciona una visión más detallada el ciclo de instrucción. Para un ciclo de instrucción dado,

algunos estados pueden no darse y otros pueden visitarse más de una vez. Los estados del ciclo

maquina ocasionan intercambio entre la CPU y la memoria o módulo E/S.

Los circuitos micro programables son sistemas digitales, lo que significa que trabajan con dos

únicos niveles de tensión. Dichos niveles, por abstracción, se simbolizan con el cero, 0, y el uno, 1,

por eso el lenguaje de máquina sólo utiliza dichos signos. Esto permite el empleo de las teorías del

álgebra booleana y del sistema binario en el diseño de este tipo de circuitos y en su programación.

Una visión típica de la arquitectura de computadores como una serie de capas de abstracción:

hardware, firmware, ensamblador, kernel, sistema operativo y aplicaciones. Claude Elwood

Shannon, en su Analysis of Relay and Switching Circuits, y con sus experiencias en redes de

conmutación, sentó las bases para la aplicación del álgebra de Boole a las redes de conmutación.

Page 8: Libro Programación de Sistemas

Un lenguaje de programación de bajo nivel es el que proporciona poca o ninguna abstracción del

microprocesador de un ordenador. Consecuentemente es fácilmente trasladado a lenguaje de

máquina. La palabra "bajo" no implica que el lenguaje sea inferior a un lenguaje de alto nivel; se

refiere a la reducida abstracción entre el lenguaje y el hardware.

En general se utiliza este tipo de lenguaje para programar controladores (drivers). Se trabaja a

nivel de instrucciones, es decir, su programación es al más fino detalle. Está orientado a la

máquina.

❖ Primera generación El lenguaje de programación de primera generación (por sus siglas en

inglés, 1GL), es el lenguaje de código máquina. Es el único lenguaje que un microprocesador

entiende de forma nativa. El lenguaje máquina no puede ser escrito o leído usando un editor de

texto, y por lo tanto es raro que una persona lo use directamente.

♦ Segunda generación El lenguaje de programación de segunda generación (por sus siglas en

inglés, 2GL), es el lenguaje ensamblador. Se considera de segunda generación porque, aunque no

es lenguaje nativo del microprocesador, un programador de lenguaje ensamblador debe conocer

la arquitectura del microprocesador (como por ejemplo las particularidades de sus registros o su

conjunto de instrucciones).

Entonces recapitulemos:

Lenguajes

Las instrucciones deben darse en un lenguaje de programación, es decir, en una determinada

configuración de información digital binaria. En las primeras computadoras, la programación era

una tarea difícil y laboriosa ya que los conmutadores ON-OFF de las válvulas de vacío debían

configurarse a mano. Programar tareas tan sencillas como ordenar una lista de nombres requería

varios días de trabajo de equipos de programadores. Desde entonces se han inventado varios

lenguajes informáticos, algunos orientados hacia funciones específicas y otros centrados en la

facilidad de uso.

Lenguaje máquina

El lenguaje propio del ordenador, basado en el sistema binario, o código máquina, resulta difícil de

utilizar para las personas. El programador debe introducir todos y cada uno de los comandos y

datos en forma binaria, y una operación sencilla como comparar el contenido de un registro con

los datos situados en una ubicación del chip de memoria puede tener el siguiente formato:

11001010 00010111 11110101 00101011. La programación en lenguaje máquina es una tarea tan

tediosa y consume tanto tiempo que muy raras veces lo que se ahorra en la ejecución del

programa justifica los días o semanas que se han necesitado para escribir el mismo.

Lenguaje ensamblador

Page 9: Libro Programación de Sistemas

Al asignar un código mnemotécnico (por lo general de tres letras) a cada comando en ¡lenguaje

máquina, es posible escribir y depurar o eliminar los errores lógicos y de datos en los programas

escritos en lenguaje ensamblador, empleando para ello sólo una fracción del tiempo necesario

para programar en lenguaje máquina. En el lenguaje ensamblador, cada comando mnemotécnico

y sus operadores simbólicos equivalen a una instrucción de máquina. Un programa ensamblador

traduce el código fuente, una lista de códigos de operación mnemotécnicos y de operadores

simbólicos, a código objeto (es decir, a lenguaje máquina) y, a continuación, ejecuta el programa.

Sin embargo, el lenguaje ensamblador puede utilizarse con un solo tipo de chip de CPU o

microprocesador. Los programadores, que dedicaron tanto tiempo y esfuerzo al aprendizaje de la

programación de un ordenador, se veían obligados a aprender un nuevo estilo de programación

cada vez que trabajaban con otra máquina. Lo que se necesitaba era un método abreviado en el

que un enunciado simbólico pudiera representar una secuencia de numerosas instrucciones en

lenguaje máquina, y un método que permitiera que el mismo programa pudiera ejecutarse en

varios tipos de máquinas. Estas necesidades llevaron al desarrollo de lenguajes de alto nivel.

Intérpretes y compiladores

La traducción de una serie de instrucciones en lenguaje ensamblador (el código fuente) a un

código máquina (o código objeto) no es un proceso muy complicado y se realiza normalmente por

un programa especial llamado compilador. La traducción de un código fuente de alto nivel a un

código máquina también se realiza con un compilador, en este caso más complejo, o mediante un

intérprete. Un compilador crea una lista de instrucciones de código máquina, el código objeto,

basándose en un código fuente. El código objeto resultante es un programa rápido y listo para

funcionar, pero que puede hacer que falle el ordenador si no está bien diseñado. Los intérpretes,

por otro lado, son más lentos que los compiladores ya que no producen un código objeto, sino que

recorren el código fuente una línea cada vez. Cada línea se traduce a código máquina y se ejecuta.

Cuando la línea se lee por segunda vez, como en el caso de los programas en que se reutilizan

partes del código, debe compilarse de nuevo. Aunque este proceso es más lento, es menos

susceptible de provocar fallos en la computadora.

El uso de microprocesadores requiere el dominio de los sistemas numéricos decimal, hexadecimal

y binario.

Todo sistema numérico parte del 0 y tiene tantos dígitos como su sistema lo marque. Tomando en

cuenta esto, tenemos que el sistema binario empieza con 0 y contiene solo 2 (binario) dígitos por

lo tanto el siguiente dígito es 1. el sistema decimal igual empieza de 0 y termina en 9 (sumando así

10 dígitos) y así sucesivamente.

Page 10: Libro Programación de Sistemas

Es importante que considere que "micro" (la maquina) identifica el numero negativo con "bits de

estatus" que veremos en el siguiente punto (1.4), y que el símbolo negativo (-) es solo una

representación para el usuario final.

1.4.1 Conceptos de modelo de programación

La arquitectura de un microprocesador o de cualquier procesador de computadora, se define por

su conjunto de instrucciones y por el modo en como éstas acceden a los datos en memoria para su

procesamiento.

Las instrucciones que obedece un microprocesador están codificadas como dígitos binarios en su

sistema de memoria. Cada instrucción puede dividirse en uno o más campos de bits. Todas las

instrucciones tienen un campo de código de operación (COP), que define el propósito de la

instrucción. Además, la instrucción completa puede tener campos para operandos o direcciones

de memoria que especifican en donde están almacenados los datos. Lo anterior delimita el

concepto de "formato de instrucción".

Las instrucciones por su complejidad pueden ser sencillas o compuestas. Los microprocesadores

que ejecutan instrucciones sencillas son los llamados RISC (Reduced Instruction Set Computer),

como por ejemplo el PIC16C84 de MicroChip o el propio Sparc de SUN y el PPC604 de Motorola.

Por otra parte tenemos a los microprocesadores con instrucciones compuestas, los CISC ( Complex

Instruction Set Computer ), como el 6809 de Motorola, SIC/XE y la serie 80X86 de Intel. Existen

algunos procesadores híbridos muy eficientes como los famosos K6, K6-II y K6-III de AMD. En este

punto se ve de acuerdo al manual de referencia del dispositivo a tratar. Para nuestro curso el

microprocesador a ver sera el HC12.

El modelo de programación representa la estructura de manipulación de datos que soporta el

conjunto de instrucciones, usualmente compuesta por:

• Unidad aritmética y lógica Los registros de trabajo El registro de condiciones La memoria de

datos

El modelo de programación del HC12 se muestra en la gráfica siguiente:

A B Acumulador A y B

D 0 doble acumulador D

IX Registro indexado X

IY Registro indexado Y

SP Stack pointer

PC Contador de programa

Page 11: Libro Programación de Sistemas

El CPU tiene 2 registros de propósito general (A,B) que pueden ser concatenados a uno solo de 16

bits (D). Tiene 2 tipos de registros indexados (X,Y), el stack pointer, el contador de programa y los

códigos de condición de registros .

Las instrucciones por su operatividad pueden estudiarse en tres clases.

® De asignación y transferencia de datos (LDAA, LEAS, STAA, MOVB, etc. ). ® De aritmética y lógica

(ABA, ADCA, ADDD, SBA, DEC, ANDA, ... etc.). ® De control de programa (JSR, JMP, RTS, JSR,... etc.

).

Mientras que los registros son clasificados de acuerdo a su función:

® registro de datos

® registros de segmentos

® bandera de registro

® registros indexados

Modo de direccionamiento:

Por la manera en como las instrucciones acceden a los datos en memoria o en los registros, éstas

se pueden clasificar en los siguientes direccionamientos (para el HC12):

SIMPLES: Inherente, inmediato, directo, extendido, NO SIMPLES: relativo, indexado (diferentes

tipos), múltiples, otros.

El campo de operación de una instrucción especifica la operación que se debe realizar. Esta debe

ser ejecutada sobre algunos datos almacenados en registros del computador o en palabras de

memoria, es decir, sobre los operandos. El modo de direccionamiento especifica la forma de

interpretar la información contenida en cada campo de operando para localizar, en base a esta

información, el operando.

Al usuario que tiene poca experiencia, la variedad de modos de direccionamiento en una

computadora le Debe parecer excesivamente complicada. Sin embargo, la disponibilidad de

diferentes esquemas de direccionamiento le da al programador experimentado flexibilidad para

escribir programas que son más eficientes en cuanto a número de instrucciones y tiempo de

ejecución.

Es tal la importancia de los modos de direccionamiento que la potencia de una máquina se mide

tanto por su -repertorio de instrucciones como por la variedad de modos de direccionamiento que

es capaz de admitir.

Los modos de direccionamiento de un ordenador son las diferentes formas de transformación del

campo de aperando de la instrucción en la dirección del operando. En esta definición el término

Page 12: Libro Programación de Sistemas

dirección debe interpretarse en su sentido más general de localización del operando, en cualquier

lugar, y no en el sentido más estricto de dirección de memoria.

A la dirección obtenida de las transformaciones anteriores la llamaremos dirección efectiva. Esta

dirección, en el caso de tratarse de una dirección de memoria, es la que se cargará en el M.A.R. o

registro de dirección de memoria. La especificación del modo de direccionamiento puede ir en el

código de operación o en el campo de cada operando.

La CPU ofrece varios métodos para calcular direcciones de memoria. Los accesos a memoria se

pueden :categorizar como accesos para obtener la siguiente instrucción a ejecutarse, o para

obtener algún dato específico. En cuanto a conseguir la siguiente instrucción por ejecutarse, la

CPU utiliza la combinación de los registros CS e IP, los rúales dan la dirección deseada. Antes de

entrar en detalles sobre las diferentes modalidades de direccionamiento de la memoria para

obtener algún dato específico, vale la pena aclarar algunos conceptos acerca de lo que es un

segmento, así como de la manera que se forma una dirección.

Una instrucción es un código binario con un significado ya establecido de antemano. Para no tener

que memorizar estos códigos y facilitar de esta manera la tarea del programador, a cada

instrucción se le asigna una abreviatura que dé una idea de la acción que realiza. Así por ejemplo si

se pretende cargar un dato en el acumulador se emplea una instrucción cuyo nemónico es LDA

abreviatura de LoaD Accumulator.

Pero además hay que indicar en la instrucción cual es el dato o donde se encuentra el dato con el

que hay que operar. Así por ejemplo la instrucción LDA (Cargar el acumulador) da lugar a los nueve

códigos de operación que se indican en la tabla de su manual de referencia, que tienen como

denominador común que todas las instrucciones cargan en el acumulador un dato, pero difieren

en la forma de obtener ese dato. Por lo tanto el MODO DE DIRECCIONAMIENTO DETERMINA

COMO LA UNIDAD CENTRAL DE PROCESO (CPU) ACCEDE A LAS LOCALIDADES DE MEMORIA PARA

OPERAR

Los modos de direccionamiento son parte implícita del conjunto de instrucciones del dispositivo.

Ver apéndices del manual de referencia de dicho micro. Las instrucciones que usan más de un

modo de direccionamiento se verán como modos de direccionamiento múltiple.

CADA MODO DE DIRECCIONAMIENTO GENERA UNA DIRECCIÓN EFECTIVA DE 16 BITS QUE ES

USADA DURANTE PORCIÓN DE REFERENCIA DE LA INSTRUCCIÓN. LA DIRECCIÓN EFECTIVA NO

REQUIERE EJECUCIÓN DE CICLOS EXTRA

Los micros utilizan técnicas de direccionamiento con los siguientes fines:

Dar versatilidad de programación al usuario proporcionando facilidades tales como

índices, direccionamientos indirectos, etc., esta versatilidad nos servirá para manejar estructuras

de datos complejas como vectores, matrices, etc. Reducir el número de bits del campo de

operando.

Page 13: Libro Programación de Sistemas

Esto permite al usuario flexibilidad para escribir programas que son más eficientes en cuanto a

número de instrucciones y tiempo de ejecución. Es tal la importancia de los modos de

direccionamiento que la potencia de una máquina se mide tanto por su repertorio de

instrucciones como por la variedad de modos de direccionamiento que es capaz de admitir. Los

modos de direccionamiento de un micro son las diferentes formas de transformación del campo

de operando de la instrucción en la dirección del operando. En esta definición el término dirección

debe interpretarse en su sentido más general de localización del operando, en cualquier lugar, y

no en el sentido más estricto de dirección de memoria. A la dirección obtenida de las

transformaciones anteriores la llamaremos dirección efectiva. Esta dirección, en el caso de

tratarse de una dirección de memoria, es la que se cargará en el M.A.R. o registro de dirección de

memoria.

1.4.2 Direccionamientos simples. (Inherente, Inmediato, Directo y Extendido)

Inherente:

Instrucciones que usan este método de direccionamiento no tienen operando externos (solo el

mnemónico o instrucción), o si los tiene son registros, estos son registros internos del cpu. En

cualquier caso el cpu no accesa a ninguna localidad de memoria para completar la instrucción.

EJEMPLOS: NOP; esta instrucción, no tiene operando INX; esta instrucción tiene operando del CPU

Inmediato:

El símbolo de (#) es usado para indicar un operando en modo de direccionamiento inmediato. Un

error común de programación es el omitir accidentalmente el símbolo #. Esto causa que el

ensamblador malinterprete la expresión que sigue como una dirección.

Es decir: LDA #$55 significa un cargo al acumulador A del valor 55, mientras que LDA $55, que

significa que al acumulador A se le carga el valor del contenido de la dirección $0055. Sin el

símbolo #, la instrucción cambia.

Nota, que el símbolo de "#" es el identificador del modo de direccionamiento aplicado, el siguiente

símbolo, si es que lo tiene, identifica el sistema de numeración.

Para el usuario final (el programador en lenguaje ensamblador) las bases de numeración tienen

mucha importancia ya que la señal de salida se puede interpretar de acuerdo al dispositivo

utilizado.

Directo:

Este modo es llamado algunas veces "direccionamiento de PAGINA CERO" porque opera en un

rango de $0000 hasta $00FF.

En ambos casos la localidad de memoria $0055 (IVE 2 BYTES) es a la que accesa el CPU para poder

extraer el dato. El byte más significativo deberá ser 0.

Page 14: Libro Programación de Sistemas

Operacionalmente hablando mientras que en el modo de direccionamiento inmediato el valor del

operador modifica el estado del dato (operación), en el modo de direccionamiento directo, es la

búsqueda de una localidad de memoria representada por 1 byte.

Extendido:

En este modo, los 16 bits de memoria son ocupados, es decir la localidad de memoria accesada en

ambos casos es de 0100, o sea 2 bytes.

Este modo de direccionamiento es utilizado exclusivamente por las instrucciones de salto

condicional (branch). La dirección de memoria a la que se transfiere el control del programa se

obtiene sumando el valor del contador de programa al segundo byte de la instrucción,

denominado "offset". Este offset es un número en complemento a-2, con lo que se

pueden efectuar saltos de hasta 127 posiciones hacia adelante o 128 hacia atrás.

Para este modo de direccionamiento es importante utilizar la variable CONLOCT, que es el

contador de localidades, por lo tanto para los modos de direccionamiento relativo (8, 9 y 16), se

verán ejemplos en el capítulo 2.

L.4.4 Direccionamiento Relativo de 16 bits.

Este al igual que el anterior corresponde a las instrucciones (mnemónicos) de salto condicional

(control de programa), con la diferencia de rango -32k a +32k lo que da 2 bytes completos de

desplazamiento.

1.4.5 Direccionamiento Indexado.

En este, los registros internos indexados son el segundo operador, lo que hace que: El operando se

encuentra en memoria.

Registro índice: se modifica a menudo en la ejecución del programa

Al igual que todos y cada uno de los modos de direccionamiento cada estructura, representa una

acción diferente. Para llevar a cabo la traducción correcta se presenta la siguiente figura, que es

una tabla de modos de direccionamiento indexado (formas fuente)

Para saber que formula se utilizara, debemos determinar:

1. que la línea de programa está utilizando modo de direccionamiento indexado

2. la forma fuente del modo de indexado (n,r)

Page 15: Libro Programación de Sistemas

3. formula aplicar, de acuerdo al rango. Se tienen 6 formulas

Chequemos por puntos:

El operando se encuentra en memoria.

La instrucción contiene una dirección que se emplea para leer en memoria una dirección

intermedia que será la verdadera dirección del objeto buscado ver punto anterior

1.4.7 Otros direccionamientos. 1.4.7.1 Relativo de 9

Este al igual que los anteriores corresponde a las instrucciones (mnemónicos) de salto condicional

(control de programa), con la diferencia de rango -/+ 1 byte y con el siguiente formato. Que igual

que los relativos anteriores se verán a detalle en el siguiente modulo.

1.4.7.2 Múltiples

2 ENSAMBLADORES

Objetivo: Entender y manejar los diferentes esquemas de ensamblado. Diseñar un ensamblador de

dos pasos.

2.1 Relación Arquitectura de máquinas y ensamblador

La evolución de los sistemas comienza con un ensamblador, se sigue con los CARGADORES que es

el modulo 3 para nuestro caso de estudio, MACROPROCESADORES que es el modulo 4,

COMPILADORES y SISTEMAS OPERATIVOS.

Al inicio de los tiempos, el programador tenía que interpretar el fundamento de la instrucción, se

escribían una serie de unos y ceros (lenguaje maquina) y se grababan en la memoria del

dispositivo, entonces el dispositivo interpretaba como esto como una instrucción. Los

programadores encontraban esta tarea (leer o escribir en la memoria) muy lenta, así que se

introdujo el concepto de MNEMONICO, que sustituye al conjunto de UNOS y CEROS, y al conjunto

de estos mnemónicos LENGUAJE ENSAMBLADOR. La entrada de dicho programa se le llama

PROGRAMA FUENTE y a la salida PROGRAMA OBJETO (que es la traducción de dichas instrucciones

a lenguaje maquina.

Los ensambladores son programas que procesan los enunciados del programa origen en lenguaje

ensamblador y los traducen en archivos en lenguaje máquina que son ejecutados por un

microprocesador o un micro controlador, estos permiten que los programas origen se escriban y

se editen en una computadora para generar un código ejecutable en otra computadora. El archivo

en lenguaje objeto ejecutable resultante se carga(CARGADOR) y se ejecuta en el sistema destino.

Page 16: Libro Programación de Sistemas

Lenguaje ensamblador es el lenguaje simbólico que se utiliza para codificar los programas origen

que se procesan por el ensamblador es llamado lenguaje ensamblador. Este lenguaje es una

colección de símbolos mnemónicos que representan: operaciones (mnemónicos de instrucciones

para la máquina o de directrices para el ensamblador), nombres simbólicos, operadores y símbolos

especiales. El lenguaje ensamblador proporciona códigos de operación de los mnemónicos para

todas las instrucciones de la máquina contenidas en la lista de instrucciones.

Los fabricantes de microprocesadores y micro controladores ofrecen una gran variedad de

herramientas de soporte para los diseñadores, tales programas se incluyen con los sistemas de

desarrollo. Los programas almacenados en ROM ofrecen un medio de comunicación con la PC, los

cuales descargan el programa de aplicación del usuario en memoria RAM, para luego ser

interpretado por el micro, la versatilidad, que ofrecen estos sistemas disminuye la posibilidad de

error de los diseñadores. EL micro recibe las instrucciones de una memoria interna o externa en

forma de 1 o 0, a esto se le denomina instrucción de código de máquina, la cual controla las

operaciones que realiza el micro. Para el usuario le queda escribir el programa en una serie de

instrucciones propias llamados mnemónicos, que describe una instrucción de código de máquina

también conocido como código operativo. El programa escrito en mnemónicos es ensamblado en

un ambiente o software que se ejecuta en una PC. Introduciendo así un listado en código

hexadecimal llamado código fuente, que es en realidad el listado de instrucciones de código de

máquina o códigos operativos. El ensamblador es propio del fabricante.

Los depuradores son sistemas en los que nos permiten evaluar un programa en tiempo real, es

decir, sobre el micro, teniendo interacción en un ambiente gráfico sobre una pe, también reciben

el nombre de emuladores (hardware y software). Los simuladores son ambientes totalmente de

programación (software) que nos permiten evaluar programas los cuales se pueden visualizar el

comportamiento o estado de "acumuladores, registros de memoria del programa, contenido de

memoria, etc. Un mnemónico es una instrucción en bajo nivel, el cual está escrito de manera de

abreviación del idioma ingles. Ejemplo: nop (not operation), Idaa (load accumulator a), rola (rotate

left accumulator) etc. Una pseudo-instruccion es una instrucción al ensamblador (no al micro), por

lo tanto esta no tiene código objeto (hexadecimal) algunas de las pseudo-instrucciones más usadas

son: equ, org, end, etc.

Un ensamblador es un programa que traduce las instrucciones a lenguaje maquina, estos deben

ser escritos conforme a las especificaciones del ensamblador. Un programa consiste en

declaraciones (llamadas linea código) linea por linea. Su sintaxis es la siguiente: nombre del

campo, operación del campo, operando del campo, sintaxis del campo, ejemplo:

® Campo de Etiquetas: Una etiqueta puede aparecer por si sola en una línea. El ensamblador

interpreta esto como "establece el valor de la etiqueta igual al valor actual del contador de

programa ( PC )". El campo de etiquetas aparece como el primer campo dentro de un enunciado

origen. El campo de etiquetas puede adoptar cualquiera de las siguientes formas:

o Un asterisco ( * ) como el primer carácter en el campo de etiquetas indica que el resto del

enunciado origen es un comentario. Los comentarios son ignorados por el ensamblador e

Page 17: Libro Programación de Sistemas

impresos en el listado origen solamente como información de programación, o Un espacio de

carácter en blanco (TAB o espacio) como primer carácter indica que el campo de etiquetas se

encuentra vacío. La línea no tiene una etiqueta y no es un comentario, o Un símbolo como primer

carácter indica que la línea tiene etiqueta. Estos símbolos son las letras mayúsculas y minúsculas (

a - z ), los dígitos ( 0 - 9 ) y caracteres especiales como punto (.), signo de pesos ( $ ) y subrayado ().

Estos símbolos consisten de uno a quince caracteres, el primero de los cuales debe ser alfabético o

un carácter especial punto o subrayado. Todos los caracteres son significantes y las mayúsculas y

minúsculas son distintas. Etc. ® Campo de Operaciones: El campo de operaciones aparece después

del campo de etiquetas y debe de estar precedido por al menos un espacio en blanco.

o El campo de operaciones debe de contener el mnemónico de un código de operación legal o

una directriz del ensamblador.

o En este campo, los caracteres en mayúsculas son convertidos en minúsculas antes de ser

revisados como un mnemónico legal, o Debido a esto " nop "," NOP " y " NoP 11 son reconocidos

como el mismo mnemónico. o Los símbolos que aparecen en este campo pueden ser de uno de

dos tipos. ® Código de Operación: Estos símbolos corresponden directamente a instrucciones de

máquina. El código de operación incluye a cualquier nombre e registro asociado con la instrucción.

o Estos nombres de registros no deben de estar separados del código de operación por ningún

espacio en blanco.

o De esta forma, " clra " significa " limpia (poner en ceros) el acumulador ( A ) ", pero 11 Ir a "

significa " limpia la localidad de memoria identificada por la etiqueta a ". ® Directiva /

Pseudoinstruccion: Estos son códigos de operación especiales conocidos por el ensamblador, los

cuales más bien controlan el proceso de ensamblado en vez de ser traducidos a instrucciones

máquina. ® Campo de Operandos: La interpretación del campo de operandos depende del

contenido del campo de operaciones.

o El campo de operandos, si se requiere, debe de seguir al campo de operaciones y debe de estar

precedido por al menos un espacio en blanco.

o El campo de operandos puede contener un símbolo, una expresión o una combinación de

símbolos y expresiones separados por comas, o El campo de operandos de una instrucción

máquina es utilizada para especificar el modo de

direccionamiento de la instrucción, así como el operando de la instrucción, o La siguiente tabla

resume los diferentes formatos del campo de operandos para la familia HC11. ® Símbolos: Cada

símbolo se encuentra asociado con un valor entero de 16 bits, el cual es utilizado en lugar del

símbolo durante la evaluación de la expresión.

o El asterisco (*) utilizado en una expresión como símbolo representa el valor actual del contador

de localidades (el primer byte de una instrucción de varios bytes ). ® Constantes: Las constantes

representan cantidades de información que no varían en su valor durante la ejecución del

programa.

Page 18: Libro Programación de Sistemas

o Las constantes pueden ser presentadas al ensamblador en uno de cinco posibles formatos:

decimal,

hexadecimal, binario, octal o ASCII, o El programador le indica al ensamblador el formato del

número con los siguientes prefijos:

■ Las constantes sin prefijo son interpretadas como decimal.

o El ensamblador convierte todas las constantes a código máquina binario y son desplegadas en

el listado del ensamblado como valores hexadecimales. ® Campo de Comentarios : El último

campo de un enunciado origen del ensamblador es el campo de comentarios.

o Este campo es opcional y solamente es impreso en el listado origen con propósitos de

documentación.

o El campo de comentarios es separado del campo de los operandos (o del campo de

operaciones sino se requiere operando) por al menos un espacio en blanco, o El campo de

comentarios puede contener cualquier carácter imprimible ASCII.

Esto se cumple dependiendo del mnemónico y del direccionamiento (como se muestra en los

ejemplos de arriba).

Una vez que hemos visto la evolución de los lenguajes, cabe preguntarse: ¿En estos tiempos

"modernos", é quiero el Lenguaje Ensamblador? , he aquí algunas ventajas y desventajas

Ventajas:

• velocidad:

El proceso de traducción que realizan los intérpretes, implica un proceso de cómputo adicional al

que el programador quiere realizar. Por ello, nos encontraremos con que un intérprete es siempre

más lento que realizar la misma acción en Lenguaje Ensamblador, simplemente porque tiene el

costo adicional de estar traduciendo el programa, cada vez que lo ejecutamos. De ahí nacieron los

compiladores, que son mucho más rápidos que los intérpretes, pues hacen la traducción una vez y

dejan el código objeto, que ya es Lenguaje de D máquina, y se puede ejecutar muy rápidamente.

Aunque el proceso de traducción es más complejo y costoso que el de ensamblar un programa,

normalmente podemos despreciarlo, contra las ventajas de codificar el programa más

rápidamente. Sin embargo, la mayor parte de las veces, el código generado por un compilador es

menos eficiente que el código equivalente que un programador escribiría. La razón es que el

compilador no tiene tanta inteligencia, y requiere ser capaz de crear código genérico, que sirva

tanto para un programa como para otro; en cambio, un programador humano puede aprovechar

las características específicas del problema, reduciendo la generalidad pero al mismo tiempo, no

desperdicia ninguna instrucción, no hace ningún proceso que no sea necesario.

Page 19: Libro Programación de Sistemas

• Eficiencia en el tamaño:

Por las mismas razones que vimos en el aspecto de velocidad, los compiladores e intérpretes

generan más código máquina del necesario; por ello, el programa ejecutable crece. Así, cuando es

importante reducir el tamaño del ejecutable, mejorando el uso de la memoria y teniendo también

beneficios en velocidad, puede convenir usar el lenguaje Ensamblador. Entre los programas que es

crítico el uso mínimo de memoria, tenemos a los virus y manejadores de dispositivos (drivers).

Muchos de ellos, por supuesto, están escritos en lenguaje Ensamblador.

• Flexibilidad:

Las razones anteriores son cuestión de grado: podemos hacer las cosas en otro lenguaje, pero

queremos hacerlas más eficientemente. Pero todos los lenguajes de alto nivel tienen limitantes en

el control; al hacer abstracciones, limitan su propia capacidad. Es decir, existen tareas que la

máquina puede hacer, pero que un lenguaje de alto nivel no permite. Por ejemplo, en Visual Basic

no es posible cambiar la resolución del monitor a medio programa; es una limitante, impuesta por

la abstracción del GUI windows. En cambio, en ensablador es sumamente sencillo, pues tenemos

el acceso directo al hardware del monitor.

Desventajas:

• Tiempo de programación:

Al ser de bajo nivel, el Lenguaje Ensamblador requiere más instrucciones para realizar el mismo

proceso, en comparación con un lenguaje de alto nivel. Por otro lado, requiere de más cuidado por

parte del programador, pues es propenso a que los errores de lógica se reflejen más fuertemente

en la ejecución. Por todo esto, es más lento el desarrollo de programas comparables en Lenguaje

Ensamblador que en un lenguaje de alto nivel, pues el programador goza de una menor

abstracción.

• Programas fuentes grandes:

Por las mismas razones que aumenta el tiempo, crecen los programas fuentes; simplemente,

requerimos más instrucciones primitivas para describir procesos equivalentes. Esto es una

desventaja porque dificulta el mantenimiento de los programas, y nuevamente reduce la

productividad de los programadores.

• Peligro de afectar recursos inesperadamente:

Tenemos la ventaja de que todo lo que se puede hacer en la máquina, se puede hacer con el

Lenguaje Ensamblador (flexibilidad). El problema es que todo error que podamos cometer, o todo

riesgo que podamos tener, podemos tenerlo también en este Lenguaje. En ciertos casos extremos,

puede llegarse a sobrescribir información del CMOS de la máquina.

• Falta de portabilidad:

Page 20: Libro Programación de Sistemas

Como ya se mencionó, existe un lenguaje ensamblador para cada máquina; por ello,

evidentemente no es una selección apropiada de lenguaje cuando deseamos codificar en una

máquina y luego llevar los programas a otros sistemas operativos o modelos de computadoras. Si

bien esto es un problema general a todos los lenguajes, es mucho más notorio en ensamblador: yo

puedo reutilizar un 90% o más del código que desarrollo en "C", en una PC, al llevarlo a una

RS/6000 con UNIX, y lo mismo si después lo llevo a una Macintosh, siempre y cuando esté bien

hecho y siga los estándares de "C", y los principios de la programación estructurada. En cambio, si

escribimos el programa en Ensamblador de la PC, por bien que lo desarrollemos y muchos

estándares que sigamos, tendremos prácticamente que reescribir el 100 % del código al llevarlo a

UNIX, y otra vez lo mismo al llevarlo a Mac.

2.1.1 Características Dependientes de la Maquina.

El ensamblador de dos pasos puede ser muy eficiente para la administración de la memoria que

ocupa durante su ejecución, pues e! primero y segundo paso no tiene necesidad de estar cargados

en memoria al mismo tiempo pues : las tareas respectivas en lo fundamental son distintas. Cuyas

características son las siguientes:

• Dependientes de la máquina

• Independientes de la máquina

Son características dependientes del procesador, desde luego el conjunto de instrucciones, los

modos de direccionamiento, la generación de código y sin faltar la interfaz con la plataforma en la

cual corre el ensamblador, un aspecto importante que no se nos debe pasar por alto, es que los

ensambladores pueden tener una clasificación en virtud de su generación de código.

® COP: código de operación, pues si bien el código 8605 significa para el HC12 cargar al

Acumulador A un 5, para el HC08 de la misma familia de Motorola es otra cosa muy diferente (el

código correspondiente para dicha acción es 9605

® MODO DE DIRECCIONAMIENTO: aunque existen "E" modos de direccionamientos, no todos

son aplicables a los micros.

® MNEMONICO: las instrucciones aunque en concepto podrían ser las mismas, se enuncian de

diferente manera, es decir:

® REGISTROS INTERNOS:

como parte de la arquitectura de cada micro y así podríamos seguir enumerando encontrando las

características que hacen exclusivo al micro.

2.1.2 Características Independientes de la maquina.

Page 21: Libro Programación de Sistemas

Las características independientes de la máquina son aquellas relacionadas más bien con el tipo de

implementación del programa y sus estructuras de datos que con la máquina objeto.

® DIRECTIVAS: también existen las llamadas DIRECTIVAS o PSEUDOINSTRUCCIONES, las cuales

especifican acciones auxiliares que se llevan a cabo por el ensamblador. ® PERIFÉRICOS: todo

dispositivo que será controlado por el micro

® ARCHIVOS AUXILIARES: *.LST, *.OBJ, *.S19, *.TABSIM, etc., dependiendo del algoritmo con que

se trabaje.... De igual manera podríamos seguir numerando características globales para los micros

2.2 Modalidades de ensamblado

Al considerar que un segmento es un área especial en un programa que inicia en un límite de un

párrafo, esto es, en una localidad de regularmente divisible entre 16, o 10 hexadecimal. Aunque

un segmento puede estar ubicado casi en cualquier lugar de la memoria y, en modo real, puede

ser hasta de 64K, solo necesita tanto espacio como el programa requiera para su ejecución.

Un segmento en modo real puede ser de hasta 64K. Se puede tener cualquier número de

segmentos; para direccionar un segmento en particular basta cambiar la dirección en el registro

del segmento apropiado. Los tres segmentos principales son los segmentos de código, de datos y

de la pila.

❖ Segmento de código:

El segmento de código (CS) contiene las instrucciones de máquina que son ejecutadas por lo

común la primera instrucción ejecutable esta en el inicio del segmento, y el sistema operativo

enlaza a esa localidad para iniciar la ejecución del programa. Como su nombre indica, el registro

del CS direcciona el segmento de código. Si su área de código requiere más de 64K, su programa

puede necesitar definir más de un segmento de código.

❖ Segmento de datos:

El segmento de datos (DS) contiene datos, constantes y áreas de trabajo definidos por el

programa. El registro DS direcciona el segmento de datos. Si su área de datos requiere más de 64K,

su programa puede necesitar definir más de un segmento de datos.

❖ Segmento de pila:

En términos sencillos, la pila contiene los datos y direcciones que usted necesita guardar

temporalmente o para uso de sus "llamadas" subrutinas. El registro de segmento de la pila (SS)

direcciona el segmento de la pila.

❖ Limites de los segmentos:

Page 22: Libro Programación de Sistemas

Los registros de segmentos contienen la dirección inicial de cada segmento. La siguiente figura

presenta un esquema de los registros CS, DS y SS; los registros y segmentos no necesariamente

están en el orden mostrado. Otros registros de segmentos son el ES (segmento extra) y, en los

procesadores 80386 y posteriores, los registros FS y GS, que contienen usos especializados.

Un segmento inicia en un límite de párrafo, que es una dirección por lo común divisible entre el 16

decimal o 10 hexadecimal. Ejemplo: un segmento de datos inicia en la localidad de memoria

045F0H. Ya que en este y todos los demás casos el ultimo dígito hexadecimal de la derecha es

cero, los diseñadores de computadora decidieron que sería innecesario almacenar el dígito cero

en el registro del segmento. Así, 045F0H se almacena como 045F, con el cero de la extrema

derecha sobrentendido. En donde sea apropiado, el texto indica al cero de la derecha con

corchetes, como 045F [0].

Desplazamiento:

En un programa, todas las localidades de memoria están referidas a una dirección inicial de

segmento. La distancia en bytes desde la dirección del segmento se define como el

desplazamiento (offset). Un desplazamiento de dos bytes (16 bits) puede estar en el rango de

0000H hasta FFFFH, o bien, desde cero hasta 65, 535. Así el primer byte del segmento de código

tiene un desplazamiento 00, el segundo byte tiene un desplazamiento 01, etc. hasta el

desplazamiento 65, 535. Para referir cualquier dirección de memoria en un segmento, el

procesador combina la dirección del segmento en un registro de segmento con un valor de

desplazamiento. En el ejemplo siguiente, el registro DS contiene la dirección de segmento del

segmento de datos en 045F[0]H y una instrucción hace referencia a una localidad con un

desplazamiento de 0032H bytes dentro del segmento de datos.

Por lo tanto, la localidad real de memoria del byte referido por la instrucción es 04622H; Dirección

del segmento DS: 045F0H Desplazamiento: +0032H Dirección real: 04622H.

Note que un programa tiene uno o más segmentos, los cuales pueden iniciar casi en cualquier

lugar de memoria, variar en tamaño y estar en cualquier orden.

Como hemos visto un ensamblador es un programa de sistema que acepta un programa de

lenguaje simbólico (texto usualmente) y produce un lenguaje de código objeto o de lenguaje

máquina. El programa de entrada es llamado programa fuente y está guardado comúnmente en

un archivo de texto; la salida es la traducción del "fuente" en un archivo de código objeto, que

puede ser ejecutable por el microprocesador.

El ensamblador puede generar código objeto en un sólo paso o en varios. La principal limitación

del ensamblador de un paso es que no puede resolver referencias delanteras ( por ejemplo ...

saltos hacia adelante con referencias simbólicas ). Por ese motivo en el presente curso se prefiere

implementar un ensamblador de dos pasos, pues pueden resolverse referencias adelantadas...

además de un mejor manejo de los símbolos.

Page 23: Libro Programación de Sistemas

En definitiva, el ensamblador empleado dependerá de que en las instrucciones se emplee uno o

varios operando, de que existan uno o varios tipos de direccionamiento, etc. La potencia de un

ensamblador se mide por las pseudo instrucciones que contenga. Aunque todos los

ensambladores realizan básicamente las mismas tareas, podemos clasificarlos de acuerdo a

características.

® Ensambladores básicos: Son de muy bajo nivel, y su tarea consiste básicamente en ofrecer

nombres simbólicos a las distintas instrucciones, parámetros y cosas tales como los modos de

direccionamiento. Además, reconoce una serie de directivas (o meta instrucciones) que indican

ciertos parámetros de funcionamiento del ensamblador.

® Ensambladores modulares, o macro ensambladores. Descendientes de los ensambladores

básicos, fueron muy populares en las décadas de los 50 y los 60, antes de la generalización de los

lenguajes de alto nivel. Hacen todo lo que puede hacer un ensamblador, y además proporcionan

una serie de directivas para definir e invocar macroinstrucciones (o simplemente, macros).

® Ensambladores modulares 32-bits o de alto nivel. Son ensambladores que aparecieron como

respuesta a una nueva arquitectura de procesadores de 32 bits, muchos de ellos teniendo

compatibilidad hacia atrás pudiendo trabajar con programas con estructuras de 16 bits. Además

de realizar la misma tarea que los anteriores, permitiendo también el uso de macros, permiten

utilizar estructuras de programación más complejas propias de los lenguajes de alto nivel.

® 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. 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.

® 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

Page 24: Libro Programación de Sistemas

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.

® 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.

® Macro Ensamblador IBM Está integrado por un ensamblador y un macroensamblador. En gran

medida su funcionamiento y forma de invocarlo es sumamente similar al de Microsoft. Su forma

de uso consiste en generar un archivo fuente en código ASCII, se procede a generar un programa

objeto que es ligado y se genera un programa .EXE. Opcionalmente puede recurrirse a la utilería

EXE2BIN de MS-DOS para transformarlo a .COM. Es capaz de generar un listado con información

del proceso de ensamble y referencias cruzadas.

® Macro Ensamblador de Microsoft Dependiendo de la versión, este ensamblador es capaz de

soportar el juego de instrucciones de distintos tipos de microprocesadores Intel de la serie

80xx/80x86. En su versión 4.0 este soporta desde el 8086 al 80286 y los coprocesadores 8087 y

80287. Requiere 128KB de memoria y sistema operativo MS-DOS v2.0 o superior. Trabaja con un

archivo de código fuente creado a partir de un editor y grabado en formato ASCII. Este archivo es

usado para el proceso de ensamble y generación de código objeto. Posteriormente, y con un

ligador, es creado el código ejecutable en formato .EXE.

® Turbo Editassm.- Este es desarrollado por Speddware, Inc., y consiste de un ambiente integrado

que incluye un editor y utilerías para el proceso de ensamble y depuración. Es capaz de realizar el

ensamble línea a línea, conforme se introducen los mnemónicos, y permite revisar listas de

referencias cruzadas y contenido de los registros. Este ensamblador trabaja con tablas en

memoria, por lo que la generación del código ejecutable no implica la invocación explícita del

ligador por parte del programador. Adicionalmente permite la generación de listados de mensajes

e información de cada etapa del proceso y la capacidad de creación de archivos de código objeto.

® Turbo Assembler.- De Borland Intl., es muy superior al Turbo Editassm. Trabaja de la misma

forma, pero proporciona una interfaz mucho más fácil de usar y un mayor conjunto de utilerías y

servicios.

® 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

Page 25: Libro Programación de Sistemas

símbolo y se pueda traducir de forma correcta. Estos ensambladores son sencillos, baratos y

ocupan poco espacio, pero tiene el inconveniente indicado de no resolver referencias adelantadas.

® 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.

La tabla de símbolos es un conjunto de pares ordenados ( Si , Ti ) en los que el primer elemento Si

es un símbolo y el segundo Ti el valor asociado, es decir la traducción correspondiente.

Se puede considerar una tabla de símbolos posibles, en un conjunto T , de los códigos de

operación y direcciones binarias. En general, en las tablas de símbolos llevan un número fijo de

caracteres, que se completan con espacios en blanco si es necesario. Como es natural, las técnicas

de construcción y consultas de tablas tienen que ser diferentes en cada caso.

2.3 Técnicas de ensamblado

Como se vio en la sección anterior, existen ensambladores que realizan su tarea en una o más

fases o pasos. El proceso de ensamble de un paso consiste en leer una línea de programa fuente y

traducirla a lenguaje máquina cuando se trata de una instrucción, o se ejecuta si es una

pseudoinstrucción (directiva). La tabla de símbolos se va construyendo a medida que se avanza en

la lectura de las líneas del programa fuente.

Para que el ensamble de un paso funciones, todos los símbolos deben estar definidos antes de

emplearse. Esto debido a que, para traducir correctamente cada instrucción, se debe conocer la

dirección de cada uno de los símbolos que intervienen en ella. En otras palabras, no pueden

quedar referencias pendientes porque ya no habrá otra oportunidad de resolverlas. Tampoco

podrán hacerse saltos hacia líneas posteriores. No es posible saltar hacia una línea cuya etiqueta

todavía no ha sido definida.

Para resolver el problema que presenta el proceso de ensamble de un paso, se utiliza el proceso

de ensamble de dos pasos o fases. En la primera fase, se lee el programa fuente y se construye la

tabla de símbolos.

En la segunda fase, se vuelve a leer el programa fuente y se traduce totalmente ya que se conoce

la totalidad de los símbolos utilizados (incluyendo las etiquetas) y las posiciones de memoria que

se les han asignado. Como ya se conocen las direcciones de las etiquetas utilizadas, pueden

realizarse saltos hacia adelante.

Se pueden hacer varios tipos de ensambladores, con las anteriores características básicas, según el

tipo de máquina y de la potencia del lenguaje ensamblador deseado. En definitiva, el ensamblador

empleado dependerá de que en las instrucciones se emplee uno o varios operandos, de que

Page 26: Libro Programación de Sistemas

existan uno o varios tipos de direccionamiento, etc. La potencia de un ensamblador se mide por

las pseudo instrucciones que contenga.

Aunque todos los ensambladores realizan básicamente las mismas tareas, podemos clasificarlos de

acuerdo a sus características.

Los lenguajes de alto nivel fueron diseñados para eliminar las particularidades de una

computadora específica, mientras que un lenguaje ensamblador está diseñado para una

computadora específica, o, de manera más correcta, para una familia especifica de

microprocesadores.

Para el aprendizaje de lenguaje ensamblador no es necesario conocimiento previo de un lenguaje

de programación, aunque tenerlo puede ayudarle a comprender algunos conceptos de

programación más rápido, no es necesario conocimiento previo de electrónica o circuitería.

Empecemos a dar una descripción general de las funciones de los 2 pasos del ensamblador simple

propuesto.

2,3.1 Ensamblador de un paso.

La evolución de la programación ha ido variando la estructura de los ensambladores haciéndolos

cada vez más complejos. Los más sencillos son los llamados en inglés load-and-go, que se puede

traducir por ensambladores sobre la marcha, ya que aceptan un programa en forma simbólica; y

en cuanto entra, lo ensambla en binario en la memoria, generalmente, mediante una exploración

(sean) del programa fuente. En este caso se obtienen los ensambladores de un paso. Los

ensambladores de un paso pueden ser de dos tipos diferentes, según que la salida generada esté

en binario o en simbólico-binario.

® Los ensambladores que generan una salida en binario, llamados en la ingles de tipo load and go,

suelen ser utilizados para programas pequeños (que son frecuentemente modificados) o para

máquinas pequeñas sin memorias auxiliares, en los cuales el hecho de leer dos veces el programa

por cinta de papel o por máquina de escribir supondría una gran pérdida de tiempo. El principal

problema de estos ensambladores es la necesidad de usar los símbolos antes de definirlos. Se

utiliza, por ello, una técnica parecida a la del editor de encadenamiento: Si a un símbolo se le

menciona, pero no está definido, se le introduce en una tabla que almacena todas las presencias

del símbolo. En el momento en que se define, se vuelve atrás y se rellenan todas las referencias

con el valor correspondiente. El resto de la técnica es análoga a la de los ensambladores de dos

pasos.

® En los ensambladores que producen una salida simbólico-binaria, suele requerirle que todos los

nombres de datos se definan en cabeza, por lo que sólo queda el problema de símbolos no

definidos para las instrucciones de bifurcación. El resto es análogo a los del tipo load and go,

aunque la salida no es procesable directamente, sino que necesita un cargador. La mayor

dificultad de este tipo de ensambladores aparece cuando hay operandos cuyos símbolos son

expresiones aritméticas, en las que todavía no se han definido sus símbolos constituyentes. En las

Page 27: Libro Programación de Sistemas

bifurcaciones hacia adelante debe dejar una indicación de que el cargador ha de completar estas

instrucciones. Se crea una tabla de referencia hacia adelante.

2.3.2 Ensamblador de dos o más pasos.

Las ventajas de dividir un programa en subprogramas son grandes. A parte de poder trabajar con

unidades independientes, cuando hay que cambiar o corregir un programa basta con reprogramar

y ensamblar de nuevo los subprogramas o rutinas afectados por el cambio. Este método aumenta

la eficacia del ensamblador, ya que el tiempo de proceso de las referencias cruzadas o parámetros

de ensamblaje es prácticamente proporcional al cuadrado del número de instrucciones del

programa; por consiguiente, al dividir el programa en partes, se consigue una reducción

Importante en el tiempo de ensamblaje. A los ensambladores que pueden realizar la incorporación

automática de subrutinas de bibliotecas y el enlazamiento de las diversas partes de un programa

se les denomina ensambladores de rutinas o de subprogramas. Este tipo de ensambladores suele

trabajar en dos pasos, es decir, haciendo dos exploraciones del programa fuente: En el primer

paso, construyen la tabla de símbolos y acumulan todas las definiciones de símbolos que se

encuentran en la rutina para efectuar la traducción en el segundo paso. Las rutinas ensambladas

se suelen almacenar en un medio externo (cinta magnética, discos, tarjetas, etc.).

2.3.2.1 Primer paso (crear tabla de símbolos)

Durante el primer paso, la principal tarea del ensamblador es extraer del programa fuente todas

las definiciones de símbolos y crear las correspondientes tablas. Para ello, como ya se ha visto,

procede a analizar las cadenas de entrada para convertirlas en un conjunto de campos y buscarlos

o añadirlos a la tabla correspondiente. En esta fase se suele efectuar un análisis sintáctico de las

sentencias del programa fuente, con el fin de poder detectar posibles errores. Este análisis lo

realiza una subrutina cuya estructura es muy variable, puesto que las sentencias de entrada, que

dependen del lenguaje de que se trate, tienen muy diversas estructuras: formato y longitud fijos,

formato variable y longitud fija o formato y longitud variable, aparte de que el número de

operandos y expresiones permitidas varían desde un mínimo de dos campos a cuatro o cinco por

término medio.

Algoritmo para el primer paso:

En el caso de la pseudo-instrucción se bifurca a la subrutina correspondiente para efectuar las

acciones de control que sean adecuadas a cada caso; en particular, cuando se detecta la de fin de

programa, el efecto es inicializar la rutina de post-análisis, completar las tablas de símbolos y dar

paso a la segunda fase.

La definición de los símbolos depende del tipo de instrucción en la que aparezcan. La más sencilla

se manifiesta cuando se define por una etiqueta, pues automáticamente el contador de

direcciones refleja la dirección relativa del símbolo. En las tablas se almacena el símbolo, el valor -

si se puede determinar en ese momento- y un identificador de tipo del símbolo cuya utilidad se

comprenderá a estudiar el fin del paso 1.

Page 28: Libro Programación de Sistemas

El primer paso de un ensamblador tiene por misión principal la del análisis de las sentencias o

instrucciones. Un esquema de las etapas del primer paso es el siguiente:

S Leer sentencia o instrucción. Analizar sentencia o instrucción.

S Tratamiento de etiquetas.

S Buscar en tabla de símbolos (si no está, pasar al siguiente paso).

S Insertar en tabla de símbolos.

S Tratamiento de código de operación.

S Buscar en tabla de código de operación y actualizar campo de dirección.

S Escribir código de operación.

S Buscar en tabla de pseudo- instrucciones y hacer el tratamiento de la pseudo-instrucción.

S Análisis del operando (en caso de la creación de un código intermedio).

S Almacenar en tabla de símbolos.

S Buscar en tabla de símbolos.

S Sustituir por dirección en tabla de símbolos.

Al finalizar el paso uno, entra en juego una subrutina post analizadora que, según el tipo de

indicador asociado e cada símbolo en las tablas, completa los valores. Así, si este indicador era de

definición por etiqueta, respeta el .valor almacenado; si era definición por pseudo-instrucción,

evalúa las correspondientes cadenas de equivalencia; o si era de indefinición, le da una dirección

que haya quedado libre de acuerdo con la estrategia del ensamblador, siempre que no se trate de

una variable externa.

En resumen el primer paso se asignan direcciones a todas las proposiciones del programa, se

guardan los valores direcciones) asignados a todas las etiquetas para usarse en el paso 2 y se

realizan algún procesamiento de las instrucciones para el ensamblador. (Esto incluye el

procesamiento que-afecta a la asignación de direcciones, como la determinación de la longitud de

las áreas de datos definidas por BYTE, RESP , etc.)

2,3.2.2 Segundo paso (formato de salida)

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

Page 29: Libro Programación de Sistemas

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.

El objetivo de este paso es obtener una visión semi-compilada (simbólica-binaria del programa o

rutina que se está ensamblando), además de las tablas de uso para el cargador y la información

necesaria para la localización de as variables.

Para ello vuelve a leer el programa fuente, bien de un medio exterior (cinta de papel, tarjetas) o, lo

más usual, de una cinta o disco magnético. Al leer una instrucción, ignora la etiqueta que ya fue

completamente procesada en el primer paso. El código de operación es traducido de acuerdo con

la tabla correspondiente o se genera la bifurcación a la subrutina correspondiente, sí se trataba de

un código de pseudo-instrucción. Determina si las cantidades y direcciones se encuentran en

modo absoluto, localizable o todavía indeterminada (variables externas), efectuando los cálculos o

evaluaciones necesarios y generando los valores binarios correspondientes, con indicación para la

posterior localización si fuese necesaria.

La salida de esta fase y, por consiguiente, del ensamblaje depende del editor de encadenamiento,

aunque un formato típico es el siguiente:

S Nombre de la rutina, subprograma o programa.

S Sección binaria con el programa en forma semicompilada y con la información necesaria para la

localización.

S Tabla de definición, con los símbolos globales definidos en la rutina.

S Tabla de uso, que detalla el uso de los símbolos globales.

Esta última tabla es muy compleja, puesto que registra todas las apariciones de los símbolos

externos, al depender de las posibilidades del ensamblador correspondiente. Si se permite la

multiplicación de estos símbolos globales, hay que generar también una tabla de uso para el

producto. Las tablas de uso son necesarias para la fase siguiente del encadenamiento de las

diversas rutinas.

En el caso más sencillo -que es cuando se canalizan todas las variables globales a través de un área

común se almacena en la tabla, para cada símbolo, el lugar o lugares de la rutina en que ha sido

usada. Cuando el valor del símbolo es determinado, el editor de encadenamiento puede colocarlo

en sus lugares correctos.

Al acabar el ensamblaje -o simultáneamente a él en otros casos- se produce un listado con el

programa fuente, incluidos: Los comentarios, el programa objeto, las tablas de símbolos con sus

valores y los errores detectados con sus diagnósticos. El formato y características particulares de

este listado dependen del lenguaje utilizado.

SEGUNDO PASO

Page 30: Libro Programación de Sistemas

V Lectura del programa de memoria secundaria.

S Tratamiento de sentencias o instrucciones. En el primer paso sólo se analizaban las sentencias

para ver si eran correctas.

Tratamiento del código de operación (SEGUNDO PASO). En el primer paso el código de operación

se trataba Simplemente para ver si era correcto o no.

S Buscaren tabla de código de operación. Obtener código de máquina y su longitud.

S Actualizar contador de direcciones.

S Buscar tabla de pseudo-instrucción (si es símbolo). Tratar la pseudoinstrucción.

S Tratamiento del operando.

S Buscaren tabla de símbolo (si es símbolo). Obtener la dirección.

S Obtener valor (si no es símbolo se obtiene la dirección directamente).

S Escribir código objeto

2.4 Gestión de memoria en el ensamblador

La gestión de memoria se refiere a como un ensamblador puede manejar los ficheros objeto

obtenidos del archivo fuente hacia la maquina que habrá de ejecutarlo, ya sea que el procesador

al que controla pertenezca al mismo equipo en donde fue diseñado (ensamblador nativo) o que

maneje la memoria del procesador de algún otro equipo (ensamblador cruzado).

® Un proceso necesita memoria para ejecutar programas

o Código del programa

o Datos estáticos y dinámicos ® El Gestor de Memoria pretende optimizar el uso de la

o memoria principal disponible

o Sistema operativo residente

o Memoria principal disponible para ejecutar procesos ® El rendimiento global del sistema

mejora si se pueden ejecutar varios procesos concurrentemente. ® El método a utilizar depende

principalmente del hardware disponible.

ENSAMBLADORES NATIVOS O RESIDENTES

El ensamblador residente se ejecuta sobre una maquina que contiene el mismo procesador que el

destinatario de! código ensamblado. Un ensamblador residente ofrece al programador la ventaja

de utilizar una única máquina para crear, probar, y depurar código, los ensambladores residentes

Page 31: Libro Programación de Sistemas

sobre los primeros microprocesadores fueron algo lentos y restrictivos en características debido al

alto costo de memoria y la lentitud del microprocesador, con la disponibilidad de memoria de bajo

costo(y consecuentemente grandes memorias disponibles en la mayor parte de los sistemas) y la

posibilidad del procesador de direccionar directamente grandes cantidades de memoria, así como

de realizar funciones más rápidas, los ensambladores residentes proporcionan ahora una variedad

de características y velocidad de ensamblaje que anteriormente solo se encontraban en

ensambladores cruzados sobre grandes computadores y microcomputadores.

En el Ensamblador Nativo, como otros ensambladores, permite que el resto del ensamblador

reparta solamente en instrucciones de máquina simbólicas (en nuestro caso, son más como

"instrucciones de máquina procesales"). Las mnemónicas elegidas están cerca de las mnemónicas

estándares de SPARC; la única diferencia es que los procedimientos del ensamblador requieren la

especificación de si el segundo operando sea un registro o un inmediato. Las optimizaciones

además de crear el código automático para las instrucciones y de resolver blancos de la rama y

otras expresiones, el ensamblador nativo realiza una cantidad limitada de optimización.

Actualmente, llena el rama retrasa ranuras usando un algoritmo simple: si la blanco del rama es

una instrucción que puede entrar en retrasa la ranura, después inserta la instrucción de la blanco

en retrasa la ranura e incremente el rama compensado por 4.Uno más sofisticado retrasa

algoritmo que llena de la ranura es deseable, porque el algoritmo antedicho no disminuye tamaño

de código -- solamente hace un rama tomado levemente más rápido. Un algoritmo mejor

trabajaría por lo menos en bloques básicos e intentaría mover instrucciones a través de ramas, en

la ranura que sigue la rama, siempre que sea posible. No sería duro poner esto en ejecución

eficientemente. El ensamblador nativo podría también realizar la instrucción programar, pero eso

es poco probable pagar apagado mucho hasta que conseguimos librados de la mayoría del tipo

dinámico cheques.

ENSAMBLADORES CRUZADOS

Un ensamblador cruzado es el polo opuesto del ensamblador nativo. El ensamblador cruzado es

aquel que se ejecuta sobre un computador con un procesador diferente de aquel para el que se

ensambla el código. -OS ensambladores cruzados permiten a un programador desarrollar

programas para diferentes sistemas sobre un computador. Sin embargo, excepto en el caso de

minicomputadores y grandes computadores que pueden ofrecer un simulador de

microprocesador destinatario real, no se puede normalmente probar y depurar el código creado

por un ensamblador cruzado sin ejecutarse sobre una maquina real que utilice este procesador. En

cualquier caso, siempre se debe utilizar la sintaxis correcta, esto es, códigos OP, operandos, y así

sucesivamente, para el microprocesador para el que el ensamblador cruzado está diseñado.

De hecho, la cosa más interesante sobre los Ensambladores cruzados son los motivos para de su

existencia, entre las principales se encuentran:

*Los primeros miniordenadores eran lentos y tenían dispositivos aún más lentos. Esto tuvo sentido

al ensamblar un programa sobre una unidad central, donde tanto el redactor como el

Page 32: Libro Programación de Sistemas

ensamblador cruzado podrían usar cintas magnéticas o discos, y luego transferir el archivo objeto,

sobre la cinta de papel, al miniordenador para la ejecución.

*Algunos de aquellos primeros miniordenadores fueron diseñados para pequeños programas de

uso. Ellos tenían pequeñas memorias o conjuntos de instrucción limitados que hicieron poco

práctico para controlar un ensamblador. Para tales ordenadores, CA era una solución práctica.

Los problemas principales en la puesta en práctica del Ensamblador Cruzado son:

•Si el ensamblador cruzado es de un paso, no puede cargar el programa objeto directamente en la

memoria del ordenador objetivo. Esto tiene que cargarlo en la memoria del ordenador de la

fuente, resolver todas las referencias avanzadas, y generar un archivo objeto absoluto. El archivo

objeto tarde o temprano es descargado al ordenador objetivo.

•la diferencia en el tamaño de palabra entre los ordenadores de la fuente y objetivo presenta un

problema ya que Ensamblador cruzado tiene que generar instrucciones y constantes para el

ordenador objetivo, pero esto sólo puede usar instalaciones disponibles sobre el ordenador de la

fuente. El resultado puede ser un empleo extenso de instrucciones que manipulando bits para

funcionar sobre las partes de palabras.

El ensamblador cruzado carece de la ayuda para las instrucciones del coprocesador de

matemáticas, las constantes de la secuencia, y las macros. Se apoyan los directorios siguientes del

ensamblador: END, ORG, EQU, SET, REG, DC. (constante definida), BCD (bloque constante

definido), y DS (almacenaje definido).

META ENSAMBLADOR

También conocido como ensamblador universal, es un ensamblador que puede ensamblar código

de un Diferente número de computadoras. Un ensamblador convencional que solo puede manejar

código fuente y objeto de una computadora, está técnica a la misma computadora. En contraste,

un meta ensamblador trabajando en una computadora "K" quizás sería capaz Te ensamblar código

Te las computadoras "K","L","M" Y algunas más. Por esto, un meta ensamblador es por lo tanto,

un ensamblador cruzado.

Hay dos tipos de meta ensamblador:

•Restringido este solo puede ensamblar código de un número limitado de computadores,

normalmente los miembros De una familia de computadoras. La información sobre conjunto de

instrucciones es construirla en el meta ensamblador y entonces sólo falta darle el nombre De un

ordenador, seguido por el archivo De origen.

•General en principio, manejar código de cada computadora. Esto no tiene ninguna instrucción, y

tiene que ser entregado, con cada archivo De origen, una descripción completa De instrucciones

De objeto y la fuente.

Y hay dos maneras de diseñar un meta ensamblador:

Page 33: Libro Programación de Sistemas

•Generativo (puede ser restringido o general) se le Da el nombre De cualquier ordenador De una

descripción de un conjunto de instrucciones, y genera un ensamblador dedicado. Este

ensamblador es controlado normalmente, traduciendo archivos De origen en los archivos De

objeto.

•Adaptable Si sigue una generación restringida un meta ensamblador se forma De varios

ensambladores su único trabajo es decidir cual ensamblador se necesita y generar una copia de el.

Un ensamblador general adaptarlo, es un programa general, disponible para adaptarse en sus

salidas para diferentes situaciones, y es potencialmente útil.

El principal problema en usarlo como un meta ensamblador es diseñar la entrada. La entrada

debería incluir una descripción del conjunto de instrucciones de la computadora objetivo, pero no

debería ser tan largo ni muy complejo. Una característica interesante de meta ensambladores, es

que ellos pueden ensamblar programas para muchas computadoras pero los programas fuentes

deben conformarse con la sintaxis de los meta ensambladores. En otras palabras, en uno puede

tomar simplemente un programa escrito en un ensamblador existente y ensamblarlo en un meta

ensamblador sin hacerle cambios. El meta ensamblador Y puede ensamblar programas para una

computadora X (y otras computadoras). Un programa fuente que corre en X puede no ser válido

para Y, desde que Y puede requerir la fuente para estar en un formato correcto y para contener

comandos especiales.

2.4.1 Jerarquía de memorias

Recordando el ciclo maquina

1. Se busca la instrucción en memoria principal

2. Se decodifica la instrucción y se buscan en memoria los operandos

3. Se ejecuta la instrucción

4. Se almacena el resultado en memoria principal

♦ código absoluto

♦ la asignación no se puede cambiar nunca

♦ Ejemplo: programas .COM en MS-DOS

asignación de direcciones en tiempo de carga

♦ código generado por el montador o el cargador

♦ la asignación se hace en el momento de lanzar el programa

♦ código reubicable

Page 34: Libro Programación de Sistemas

CPU

2.4.4 Asignación de dirección en tiempo de ejecución

- el código no tiene direcciones definitivas incluso después de la carga

♦ la asignación se resuelve en cada acceso a memoria

♦ permite mover el programa durante la ejecución

♦ necesita hardware especial

2.4.5 Espacios de memoria lógicos y físicos

® Dirección lógica

o La generada por la CPU durante la ejecución del programa

• Llamada también dirección virtual ®

Dirección física

o La usada realmente en el Registro de Direcciones de Memoria

Carga dinámica

® Se trata de no perder tiempo cargando código que luego no se ejecuta

® Al empezar solo se carga el programa principal.

® Las subrutinas no se cargan hasta que son llamadas.

® Solo hace falta tener una tabla de rutinas cargadas y una forma especial de llamarlas

® No hace falta un SO especial, solo un cargador reubicable.

® El espacio en memoria está reservado para el proceso, pero no se utiliza siempre.

Enlace dinámico

® Se trata de no reservar espacio para las subrutinas hasta el momento de la ejecución. ® Cada

llamada lleva asociada un código para localizar la dirección de la rutina en memoria, o Ese código

se sustituye por la dirección de la rutina una vez cargada.

Page 35: Libro Programación de Sistemas

® Consume menos memoria y menos disco.

o Solo hay una copia de la biblioteca en memoria

o El código del programa no incluye el de las bibliotecas

® Se pueden tener varias versiones de la misma biblioteca o Bibliotecas Compartidas

® Necesita que el SO compruebe que no se vulnera la protección de memoria.

Solapamientos (overlays)

® Técnica que permite ejecutar un programa que sea mayor que la memoria principal disponible. ®

Se basa en mantener en memoria solo las instrucciones y Tatos que se necesita en cada momento.

® No hace falta soporte Tel SO.

o Hace falta programar el traductor y el montador ® Hace falta un programador experto

o para agrupar instrucciones y datos en conjuntos adecuados ® Solo se usa con hardware

limitado (micros 86, 286).

o En otros casos, técnicas automáticas de memoria virtual

Un ensamblador en dos pasos

2,5 Diseño y programación del ensamblador de dos pasos

Un algoritmo es una serie de pasos lógicos para realizar una acción, programa o tarea ya que es el

primer paso para realizar un programa. Los algoritmos se pueden expresar por fórmulas,

diagramas de flujo, y pseudocódigos. Los algoritmos tienen ciertas características que son:

S Preciso: Esto quiere decir que debe indicar el orden en cada paso.

V Definido: Es decir, si se sigue dos veces, obtiene el mismo resultado cada vez.

S Finito: Que tiene fin, o sea un número definido de pasos.

Analizando en detalle el proceso de compilación, se divide en dos grandes fases, una de Análisis y

la otra de Síntesis.

Fase de Análisis:

® En el llamado análisis lexicográfico o léxico, el compilador revisa y controla que las "palabras"

estén bien escritas y pertenezcan a algún tipo de token (cadena) definido dentro del lenguaje,

como por ejemplo que sea algún tipo de palabra reservada, o si es el nombre de una variable que

Page 36: Libro Programación de Sistemas

este escrita de acuerdo a las pautas de definición del lenguaje. En esta etapa se crea la tabla de

símbolos, la cual contiene las variables y el tipo de dato al que pertenece, las constantes literales,

el nombre de funciones y los argumentos que reciben etc.

® En el análisis sintáctico como su nombre lo indica se encarga de revisar que los tokens estén

ubicados y agrupados de acuerdo a la definición del lenguaje. Dicho de otra manera, que los

tokens pertenezcan a frases gramaticales validas, que el compilador utiliza para sintetizar la salida.

Por lo general las frases gramaticales son representadas por estructuras jerárquicas, por medio de

árboles de análisis sintáctico. En esta etapa se completa la tabla de símbolos con la dimensión de

los identificadores y los atributos necesarios etc.

® El análisis semántico se encarga de revisar que cada agrupación o conjunto de token tenga

sentido, y no sea un absurdo. En esta etapa se reúne la información sobre los tipos para la fase

posterior, en esta etapa se utiliza la estructura jerárquica de la etapa anterior y así poder

determinar los operadores, y operandos de expresiones y preposiciones.

Fase de Síntesis:

® Etapa de generación de código intermedio, aunque algunos compiladores no la tienen, es bueno

saber de su existencia, en esta etapa se lleva el código del programa fuente a un código interno

para poder trabajar mas fácilmente sobre él. Esta representación interna debe tener dos

propiedades, primero debe ser fácil de representar y segundo debe ser fácil de traducir al código

objeto.

® En la etapa de optimización de código, se busca obtener el código más corto y rápido posible,

utilizando distintos algoritmos de optimización.

® Etapa de generación de código, se lleva el código intermedio final a código maquina o código

objeto, que por lo general consiste en un código maquina relocalizable o código ensamblador. Se

selecciona las posiciones de memoria para los datos (variables) y se traduce cada una de las

instrucciones intermedias a una secuencia de instrucciones de maquina puro.

® La tabla de símbolos no es una etapa del proceso de compilación, sino que una tarea, una

función que debe realizar el proceso de compilación. En ella se almacenan los identificadores que

aparecen en el código fuente puro, como así también los atributos de los mismos, su tipo, su

ámbito y en el caso de los procedimientos el número de argumentos el tipo del mismo etc. En

otras palabras una tabla de símbolos es una estructura de datos, que contiene un registro por cada

identificado y sus atributos. La tabla de símbolo es accedida tanto para escritura como parar

lectura por todas las etapas. Detector de errores o manejador de errores, al igual que la tabla de

símbolos no es una etapa del proceso de compilación, si no que es una función, muy importante,

pues al ocurrir un error esta función debe tratar de alguna forma el error para así seguir con el

proceso de compilación (la mayoría de errores son detectados en las etapas de análisis léxico,

análisis sintáctico, análisis semántico).

Algoritmo de programación del paso 1

Page 37: Libro Programación de Sistemas

Se puede dar una descripción general de las funciones de los 2 pasos del ensamblador simple

propuesto. 1 (define los símbolos):

1. Asignar direcciones a todas las proposiciones del programa.

2. Guardar los valores (direcciones) asignados a todas las etiquetas para usarse en el paso 2.

3. Realizar algún procesamiento de las instrucciones para el ensamblador. (Esto incluye el

procesamiento que afecta a la asignación de direcciones, como la determinación de la longitud de

las áreas de datos definidas por BYTE, RESP , etc.)

2.5.2 Algoritmo de programación del paso 2

Paso 2 (ensambla instrucciones y genera el programa objeto):

1. Ensamblar instrucciones (traducción de los códigos de operación y examen de las direcciones).

2. Generar los valores de datos definidos por BYTE, P ORD, etc.

3. Realizar el procedimiento no realizado en el paso 1 de las instrucciones del ensamblador.

4. Escribir el programa objeto y el listado de ensamblado.

Generar S19

2.5.3 Formato de Archivo objeto.

Un archivo de salida de Motorola es un archivo tipo ASCII, Motorola maneja 3 tipos:

® S19 para direccionamiento de 16 bits ® S2 para direccionamiento de 24 bits ® S3 para

direccionamiento de 32 bits

Estos archivos son una opcional tabla de información, con datos específicos para ser cargados en

memoria: Modulo de registro este es opcional, contiene el nombre del modulo.

Registro de símbolos en caso de ser necesario un símbolo re-calculable.

Registro de encabezado SO

Registro de dato

SI (2 bytes) dato

S2 (3 bytes) dato

Page 38: Libro Programación de Sistemas

S3 (4 bytes) dato ® Registro de término

S7 archivo de 32 bits de dirección

S8 archivo de 24 bits de dirección

S9 archivo de 16 bits de dirección

Recordemos que este es solo un formato para el cargador del simulador, para facilitar la vida del

programador, lo único exacto y sin varianza deberá ser el COP resultante. Para nuestro caso del

HC12 de Motorola el formato de salida será un S19 con las siguientes características:

3 CARGADOR - LIGADOR

Objetivo: Entender el funcionamiento de los esquemas más importantes de la carga y liga de

módulos objeto.

3.1 Clases de cargador

En informática, un cargador es la parte de un sistema operativo que es responsable de cargar

programas en memoria desde los ejecutables (por ejemplo, archivos ejecutables). El cargador es

usualmente una parte del núcleo del sistema operativo y es cargado al iniciar el sistema y

permanece en memoria hasta que el sistema es reiniciado o apagado. Algunos sistemas operativos

que tienen un núcleo paginable pueden tener el cargador en una parte paginable de la memoria,

entonces a veces el cargador intercambia de memoria (swapping).

Todos los sistemas operativos que soportan la carga de programas tienen cargadores. Algunos

sistemas operativos empotrados de computadoras altamente especializadas corren un único

programa y no existen capacidades de carga de programas, por lo tanto no usan cargadores.

Ejemplos de estos sistemas embebidos se encuentran en equipos de audio para automóviles. En

los sistemas Unix, el cargador es el manejador para la llamada del sistema execve(). Algunas

computadoras necesitan cargadores relocalizables, los cuales ajustan direcciones de memoria

(punteros) en un ejecutable para compensar las variaciones en la cual la memoria disponible de la

aplicación empieza.

Las computadoras que necesitan de los cargadores relocalizables son aquellos en los cuales los

punteros son direcciones absolutas en vez de compensaciones de direcciones base del programa.

Un ejemplo muy conocido está en los mainframes IMB Sistema 360 y sus descendientes,

incluyendo la serie de los sistemas Z9. Los ligadores dinámicos son otro tipo de cargador que carga

y liga librerías dinámicas (como dll's).

Muchos cargadores permiten al usuario especificar opciones que modificar el procesamiento

estándar descrito. Muchos cargadores tienen un lenguaje especial de mandatos que se utiliza para

especificar opciones. Algunas veces existe un archivo independiente de entrada al cargador que

contiene esas proposiciones de control. En ocasiones esas mismas proposicio3nes también

pueden estar intercaladas en el flujo primario de entrada entre los programas objeto. En ciertos

Page 39: Libro Programación de Sistemas

sistemas el programador puede incluso introducir proposiciones de control del cargador en el

programa fuente, y el ensamblador o el compilador retienen esos mandatos como parte del

programa objeto.

Una opción típica del cargador permite la selección de fuentes alternativas de entrada, por

ejemplo el mandato INCLUDE, puede indicar al cargador que lea el programa objeto designado en

una biblioteca y que lo trate como si fuera parte de la entrada primaria del cargador. Otros

mandatos permiten al usuario eliminar símbolos externos o secciones de control completas.

CARGADOR LIGADOR

Un cargador es un programa del sistema que realiza la accción de carga. Algunos sistemas tienen

un ligador para realizar las operaciones de enlace, y un cargador separado para manejar la

relocalización y la carga. 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 o una cinta magnética. El cargador consiste en un juego de

instrucciones que permiten al dispositivo de entrada (teclado o unidad distinta) asignar la

dirección de inicio de la memoria y asegurar que el computador leerá el programa y lo largará byte

a byte. La ligadura de tales recursos puede ser de naturaleza estática o dinámica. Esto nos lleva al

siguiente proceso:

carga: lleva el programa objeto a la memoria para su ejecución

relocalización: modifica el programa objeto de forma que puede cargarse en una dirección

diferente de la localidad especificada originalmente

ligado: combina 2 o más programas

objeto independientes y proporciona la información necesaria para realizar referencias entre ellos.

El ligador realiza la operación de enlazar programas objetos independientes. Los editores de ligado

pueden efectuar varias funciones ultimas además de la simple preparación de un programa objeto

para su ejecución estos también se pueden utilizar para construir paquetes de subrutinas u otras

secciones de control que suelen utilizar juntas. Estos pueden ser útiles al tratar con bibliotecas de

subrutinas que manejan lenguajes de programación de alto nivel. Comparados con los cargadores

de ligadores los editores de ligado en general tienden a ofrecer mayor flexibilidad y control con el

correspondiente incremento en complejidad y sobrecarga. La tarea primaria del enlazador es

resolver referencias externas lleva acabo la siguiente etapa del proceso de traducción enlazado los

módulos ensambladores y los acervos para formar un programa completo. En algunos sistemas el

cargador simplemente copia el programa ejecutable a las posiciones de memorias apropiadas.

Sus funciones:

Page 40: Libro Programación de Sistemas

- Enlazar código intermedio compilado independiente en un solo modulo de cara resolviendo las

diferencias entre Tokens. Incorporada las denominadas rutinas de librería en caso de solicitarlas el

propio programa.

- reunir procedimientos traducidos por separado y enlazarlos para que se ejecuten como una

unidad llamada programa binario ejecutable.

Ahora si mostrar algunos tipos de cargadores..

Arranque Bootstrap Cargadores iníciales

Con la maquina vacía e inactiva, no hay necesidad recolección de programación, tan solo se puede

especificar la dirección especifica del programa que se carga en primer lugar. En la mayoría de los

casos este programa es el sistema operativo, que ocupa un lugar en la memoria. Esto significa para

realizar las funciones. 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 hacer una buena solución del problema. Ofrece

algunas ventajas sobre los otros tipos de ligado. Proporciona la posibilidad de cargare las rutinas

solo cuando y si se necesitan. Si las subrutinas son grandes o tiene muchas referencias externas se

pueden conseguir ahorros considerables de tiempo y espacio de memoria.

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 bootstrap, 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.

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

Page 41: Libro Programación de Sistemas

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 ligadores (linker)

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 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.

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 está realizando el montaje de un programa a buscarlas y las adjunta al programa objeto.

Diferencia fundamental entre un editor de ligado y un cargador ligador:

Un cargador tiene como función principal la de subir un programa objeto que se encuentra en

almacenamiento secundario a la memoria para que pueda ser ejecutado; durante el proceso de

carga, si el programa que se va a ejecutar requiere o tiene definidas algunas referencias externas

que pueden ser partes de programas o programas en si, entonces es cuando entra el proceso de

liga. El proceso de carga puede ser absoluto o relocalizable . el proceso de liga puede ser estático o

dinámico.

Primero, 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.

Page 42: Libro Programación de Sistemas

3.1.1 Ligado dinámico

El ligado dinámico, consiste en enlazar en tiempo de ejecución los módulos que contienen a las

subrutinas, este 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.

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.

Tablas y lógica de un cargador ligador:

o Ahora ya se puede presentar un algoritmo de un cargador ligador (y relocalizador), se utilizan

registros de modificación para que las funciones de relocalizacion y ligado se realicen por medio

de este mecanismo.

o El algoritmo de un cargador-ligador es mucho más complicado que el del cargador absoluto, la

entrada de este cargador consta de un conjunto de programas objeto o secciones de control que

se van a ligar. Una sección puede (y es común que lo haga) hacer una referencia externa a un

símbolo cuya definición aparece más adelante en este flujo de entrada. En este caso, la operación

de ligado requerida no se puede realizar hasta haber asignado una dirección al símbolo externo

implicado.

o La principal estructura de datos necesaria para el cargador ligador es una tabla de símbolos

externos TABSE (análoga TABSIM), se usa para almacenar el nombre y la dirección de los símbolos

externos en el conjunto se secciones de control que se está cargando, la tabla también suele

indicar en qué sección de control se define el símbolo, entre otras variables importantes podemos

Page 43: Libro Programación de Sistemas

encontrar a DIRPROG (dirección y carga del programa) que es la dirección inicial de la memoria

donde se va a cargar el programa ligado, y DIRSC (dirección de la sección de control) que contiene

la dirección inicial asignada a la sección de control que está examinando el cargador.

3.1.2 Ejemplo de cargador CYBER

Los programas CYBER suelen contener mucho mas valores relocalizables que los programas de

VAX o del sistema /370. Una palabra de CYBER puede contener más de una instrucción, por lo que

no es posible usar un solo bit de relocalización por palabra. A causa de que en CYBER sólo las

instrucciones de 30 bits pueden contener direcciones de memoria, existen cinco posibles de

valores relocalizables dentro de una palabra.

1. Sin relocalización

2. Valor relocalizable solo en la mitad superior de la palabra

3. Valor relocalizable solo en la mitad inferior de la palabra

4. valores relocalizables en las mitades superior e inferior de la palabra

5. valor relocalizable en la mitad de los 30 bits de la palabra cuando se usa la técnica de la máscara

de bits, hay un campo de 4 bits asociado a cada palabra de código objeto.

Esos 4 bits se utilizan para codificar las posibles antes listadas, y también para especificar si la

dirección base del programa se suma o resta a cada valor relocalizable. El cargador de CYBER

puede utilizar programas de superposiciones de un tipo más restringido que el descrito. Una

estructura de superposiciones está limitada a un máximo de 3 niveles. Cada segmento está

identificado por un par ordenado de enteros, y un segmento solamente puede tener un punto de

entrada.

Cada segmento, excepto el raíz, debe cargarse por medio de una solicitud explícita; no existe la

carga automática de segmentos. El programa de aplicación puede solicitar la carga de un

segmento por medio de una llamada de servicio al sistema operativo. Como alternativa, en el

segmento raíz puede haber un pequeño cargador residente para manejar el proceso de

superposición.

Hay también una opción más poderosa que las superposiciones: la segmentación. Un programa

segmentado también usa una estructura de árbol; sin embargo, puede haber más de 3 niveles, y

cada segmento puede tener varios puntos de entrada.

3.1.3 Ejemplo de editor de ligado 370

El formato de los programas objeto manejado por el editor de ligado del sistema /370 es muy

parecido al analizado para SIC/XE. La técnica de referencia a un número, se usa para mejorar la

eficiencia. El programa de salida del editor de ligado se llama módulo de carga, y puede cargarse

Page 44: Libro Programación de Sistemas

en la memoria para su ejecución, y suele contener suficiente información para permitir que el

editor de ligado los reprocese.

El usuario tiene la posibilidad de especificar que un módulo de carga sea "no editable", en cuyo

caso puede omitirse gran parte de la información de control, para producir un módulo de carga

más pequeño.

El editor de ligado del sistema 370 puede realizar todas las funciones estándar analizadas, las

secciones de control pueden ser eliminadas, reemplazadas o reordenadas.

3.1.4 Ejemplo de editor de ligado VAX

Es un editor de ligado que realiza las mismas funciones básicas alcanzadas con anterioridad. La

acción del ligador en la creación de las secciones de imagen está controlada por el ensamblador o

compilador por medio de una secuencia de mandatos que forman parte del programa objeto. El

ligador usa una pila interna como almacenamiento de trabajo. Los mandatos del programa objeto

pueden especificar el apilamiento de valores a partir de diversas fuentes, guardar valores de la pila

en la imagen que se está creando y realizar operaciones con valores de pila. El lenguaje de

mandatos ofrece una gran diversidad de posibilidades: hay más de 50 códigos de mandatos

posibles.

El ligador VAX realiza las funciones usuales de ligado y relocalización. Además hace parte del

trabajo que en otros sistemas realizan el ensamblador o compilador. No utiliza programas de

superposiciones, debido en parte a la gran memoria virtual que dispone VAX. Los diseñadores del

sistema consideraron que el tamaño de esta memoria virtual, junto con los algoritmos para la

administración de la memoria, hacían innecesaria la utilización de las superposiciones.

3.2 Relación Cargador- Sistema Operativo

Un sistema operativo es un programa que actúa como intermediario entre el usuario y el

hardware de un computador y su propósito es proporcionar un entorno en el cual el usuario que

pueda ejecutar programas. El objetivo principal de un sistema operativo es, entonces, lograr que el

sistema de computación se use de manera cómoda, y el objetivo secundario es que el hardware

del computador se emplee de manera eficiente. Un sistema operativo es una parte importante de

casi cualquier sistema de computación. Un sistema de computación puede dividirse en cuatro

componentes: el hardware, el sistema operativo, los programas de aplicación y los usuarios. El

Principal objetivo de un sistema operativo es proporcionar una interfaz entre el equipo y los

programas. Para lograr este objetivo, el sistema operativo debe administrar los recursos del

sistema de cómputo, de manera tal que su utilización sea lo más sencilla y eficiente posible.

Ahora, recordando que un cargador s 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 "'unción de carga, pero muchos cargadores también incluyen

relocalización y ligado. Algunos sistemas tienen un ligador para realizar las operaciones de enlace y

un cargador separado para manejar la relocalización y la carga.

Page 45: Libro Programación de Sistemas

Un programa montado sin errores se puede ejecutar; antes de eso, el programa está en un fichero

de almacenamiento secundario, como lo hace? El núcleo del sistema operativo trae el programa a

memoria y empieza a ejecutarlo. Para empezar el programa, el sistema operativo realiza los

siguientes pasos:

> Lee la cabecera del fichero ejecutable para determinar el tamaño de los segmentos de texto y

datos.

> Crea un espacio de direcciones nuevo para el programa. Este espacio de direcciones es

suficientemente grande para albergar los segmentos de texto y de datos, junto con el segmento

de pila.

> Copia instrucciones y datos del fichero ejecutable en el nuevo espacio de direcciones.

> Copia los argumentos pasados al programa en la pila.

> Inicia los registros de la maquina, por lo general todos los registros se ponen a cero, pero al

puntero de la pila hay que asignarle la dirección de la primera posición libre de la pila.

> Salta a la rutina de inicio que copia los argumentos del programa de la pila a registros y llama a la

rutina main del programa, si la rutina main retorna, la rutina de inicio termina el programa con la

llamada al sistema de salida.

El hardware (unidad central de proceso (CPU), memoria y dispositivos de entrada y salida (E/S))

proporciona los recursos de computación básica básicos. Los programas de aplicación

(compiladores, sistemas de bases de datos, juegos de vídeo y programas para negocios) definen la

forma en que estos recursos se emplean para resolver los problemas de computación de los

usuarios. Puede haber distintos usuarios (personas, máquinas, otros computadores) que intentan

resolver problemas diferentes; por consiguiente, es posible que haya diferentes programas de

aplicación. El sistema operativo controla y coordina el uso del hardware entre los diversos

programas de aplicación de los distintos usuarios. Los sistemas operativos son ante todo

administradores de recursos; el principal recurso que administran es el hardware del computador:

los procesadores, los medios de almacenamiento, los dispositivos de entrada/salida, los

dispositivos de comunicación y los datos. Los sistemas operativos realizan muchas funciones,

como proporcionar la interfaz con el usuario, permitir que los usuarios compartan entre sí el

hardware y los datos, evitar que los usuarios interfieran recíprocamente, planificar la distribución

de los recursos, facilitar la entrada y salida, recuperarse de los errores, contabilizar el uso de los

recursos, facilitar las operaciones en paralelo, organizar los datos para lograr un acceso rápido y

seguro, y manejar las comunicaciones en red. No existe una definición universal aceptada de qué

forma parte de un sistema operativo y qué no. Una perspectiva sencilla considera como tal todo lo

que envía un vendedor cuando se ordena la adquisición del "sistema operativo". Sin embargo, los

requisitos de memoria y las características incluidas varían en forma considerable de un sistema a

otro. Algunos requieren menos de un megabyte de espacio e incluso carecen de un editor de

pantalla, mientras que otros necesitan cientos de megabytes de espacio e incluyen revisores

Page 46: Libro Programación de Sistemas

ortográficos y sistemas de ventanas. Una definición más común es que el sistema operativo es el

programa que se ejecuta todo el tiempo en el computador (conocido usualmente como núcleo),

siendo programas de aplicación todos los demás. La segunda definición es la más común y es la

que utilizamos en general.

La necesidad de un cargador relocalizador es una consecuencia de la rápida evolución de las

computadoras, más poderosas y con más memoria, de tal manera que puede alojar no uno sino

varios programas y entonces el sistema operativo ( según la política de gestión de procesos )

puede hacer que se ejecuten varias tareas. Pero desde luego primero se tiene que cargar el

sistema operativo, por lo tanto necesitamos un cargador que desde el inicio o arranque de la

computadora, aloje memoria para el S.O. Tal cargador es el llamado "Cargador de Arranque" o

Bootstrap, el cual comúnmente es un cargador absoluto. Ese cargador aloja memoria para el

cargador relativo del sistema operativo y una parte de éste, el conmutador de tareas ... finalmente

se carga todo el sistema operativo y el control de carga se pasa al cargador relativo incluido en

éste.

El arrancador Bootstrap, se encuentra en una memoria de sólo lectura (ROM), la cual tiene

decodificadas direcciones fijas, lo que define al cargador absoluto. En dicha memoria ROM, se

encuentran además otras rutinas pertinentes al arranque en frío de la computadora

Aquí sería bueno que ud, explicara qué pasa en otras plataformas?... UNIX, MAC, etc....

3.3 Funciones del editor de enlace

La mayor parte de los programas se componen de más de un procedimiento. Los compiladores y

ensambladores suelen traducir un procedimiento a la vez y guardan en memoria secundaria el

resultado de esta Traducción. Antes de que pueda ejecutarse el programa, todos los

procedimientos traducidos deben recuperarse y darse correctamente. Si no se dispone de

memoria virtual, el programa enlazado debe cargarse explícitamente en ■memoria.

Los programas que realizan estas funciones reciben varios nombres, como cargador (loader),

cargador montado (linking loader) y editor de enlaces (linkage editor). La traducción completa de

un programa fuente se efectúa en dos pasos:

• Compilación o ensamblaje de los procedimientos fuente

• Encadenamiento (linking) o montaje de los módulos objeto.

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.

Page 47: Libro Programación de Sistemas

• La generación de un módulo ejecutable a partir de una colección de procedimientos traducidos

independientemente requiere un ligador.

• El ensamblador asiste al ligador suministrándole una tabla de símbolos o rótulos y referencias no

resueltas.

La tarea principal del enlazador es resolver las referencias externas, o sea establecer la

correspondencia entre símbolos definidos en un archivo objeto y su empleo en otro archivo de la

misma naturaleza. El enlazador debe combinar varios archivos objeto con su acervo respectivo de

datos en un solo archivo ejecutable.

Existen algunos pasos necesarios para ejecutar el editor de enlace, los que finalmente dependen

de las directrices de importación-exportación de objetos:

1. Probar directrices, el micro tiene 2 sentencias en el lenguaje ensamblador: directivas e

instrucciones

2. Referencias externas, crear tabla de símbolos: Establecer la correspondencia entre símbolos

definidos en un archivo objeto y su empleo en otro archivo de la misma naturaleza. El enlazador

debe combinar varios archivos objeto con su acervo respectivo de datos en un archivo ejecutable.

3. Abrir archivos objeto y formatear datos

4. Combinar archivos objeto

5. Enlazar código intermedio compilado

6. Incorpora rutinas de librerías en caso de solicitarlas el propio programa.

7. Su función es reducir procedimientos traducidos por separado y enlazarlos para que se ejecuten

como una unidad llamada programa binario ejecutable

Los editores de ligado en general tienden a ofrecer una gran flexibilidad y control con el

correspondiente incremento de complejidad y sobrecarga.

3.3.1 Ligadura de una subrutina

El editor de ligado primero se ensambla o compila el programa fuente, produciendo un programa

objeto (que puede contener varias secciones de control diferentes). Un cargador ligador realiza

todas las operaciones de ligado y relocalización, incluyendo búsqueda automática en bibliotecas.

El enlace de una subrutina es la estructura con que se comparte la información del involucrado. El

involucrado proporciona la dirección como parte del enlace de subrutina.

Las subrutinas se encuentran guardadas en algún elemento accesible por el que se suele

denominarse librería porque ahí están almacenados todas las rutinas externas susceptibles de ser

utilizadas por los diferentes programas del usuario ahí va el programa ligado cuando está

Page 48: Libro Programación de Sistemas

realizando el montaje de un programa al buscarlas y las adjunta al programa objeto a este proceso

se le llama ligadura de rutinas y subrutinas.

3.3.2 Razones de porque dividir un programa en subprogramas

® Vincular entre lenguajes; es decir combinar el poder computacional de un lenguaje de alto nivel

con el eficiente procesamiento del lenguaje ensamblador. ® Facilitar el desarrollo de proyectos

largos en los cuales equipos diferentes proceden sus módulos separadamente.

® Incrustar partes de un programa durante su ejecución a causa del gran tamaño del programa

Cuando se utilizan subrutinas en unos programas, el código ejecutable de cada una de ellas debe

encontrarse en memoria al tiempo de ejecución. Para esto antes de cargar un programa debe

ligarse su código objeto de cada una de las subrutinas involucradas por el obtenido así por un

programa ejecutable que tiene tanto el código del modulo involucrado como el código de los

módulos involucrados.

3.4 Problema de ligas de objetos y métodos de solución

Uno de los objetivos alternativos del cargador es pegar o unir otros recursos al código objeto para

que éste realice por completo sus funciones específicas desde el intérprete de órdenes del sistema

operativo. Estos recursos pueden ser bloques de memoria de datos o de código, dispositivos de

entrada y salida, inclusive otros archivos ejecutables, y esta ligadura puede ser de forma estática o

dinámica.

En el proceso de ligado que lleva a cabo el cargador se combinan 2 o más programas objeto

independientes y proporciona la información necesaria para realizar referencias entre ellos y de

esta manera puedan interactuar

La problemática que suele presentarse en el cargador es que se haga una referencia a un símbolo

de un módulo externo cuya definición aparece más adelante en el flujo de entrada. En tal caso, la

operación de ligado no se puede hacer hasta haber asignado una dirección al símbolo externo

implicado en la liga

A este problema se le llama: problema de liga de referencias adelantadas externas y su para su

solución es necesario considerar tres pasos descritos a continuación:

Combinación de bloques de memoria de código y de datos: Esto significa que en la memoria

estarán intercalados bloques tanto de datos como de código lo que implica que entre el código

estarán estén implícitos los datos necesarios para realizar las tareas específicas.

Construcción de una tabla de Símbolos (Acervo): A lo que nos referimos con esto es, que será

necesario contar con una tabla que contenga todos los símbolos requeridos para la ejecución de

un programa de manera que se sepa de antemano lo que puede solicitarse por parte del código.

Page 49: Libro Programación de Sistemas

Lista de partes exportables públicas y privadas incluyendo su desplazamiento: Con esto nos

referimos a que se realizará una lista en la que se especifiquen que partes de un módulo podrán

exportarse y que partes son públicas y privadas incluido el desplazamiento que se les hará para la

ejecución de programa.

El enlazado permite al programador y al propio sistema operativo dividir un programa en varios

archivos llamados módulos, que pueden ensamblarse por separado y enlazarse en una ocasión

posterior, el enlace puede ser de naturaleza estática o dinámica. El enlace estático da como

resultado, un archivo ejecutable con todos los símbolos y módulos respectivos incluidos en dicho

archivo. Por otra parte sistemas operativos como el, win 95/nt, y el OS/2 se puede preferir una liga

dinámica, solo mientras se está en ejecución el programa ejecutable, así los módulos que están

invocados en el tiempo de ejecución, denotan la librería de enlace dinámico o DLL.

3.4.1 Cargador dinámico

Un cargador dinámico es útil cuando no es posible asignar en memoria un programa completo.

Utiliza los dispositivos del sistema operativo para cargar subprogramas en el momento en que se

llaman por primera vez. Al retardar el proceso de ligado de esta forma, se puede lograr flexibilidad

adicional, aunque, este enfoque suele implicar más operaciones que el cargador ligador. Se trata

de esquema que pospone la función de ligado hasta el momento de la ejecución: una subrutina se

carga y liga al resto del programa al llamarla por primera vez.

El programa contiene subrutinas que corrigen o diagnostican errores en los datos de entrada

durante la ejecución. Si esos errores son poco comunes, las rutinas de corrección y diagnóstico

pueden no ser utilizadas durante la mayoría de las ejecuciones del programa. Sin embargo, si el

programa estuviera totalmente ligado antes de la ejecución, habría que cargar y ligar esas rutinas

cada vez que se ejecuta el programa.

El ligado dinámico proporciona la posibilidad de cargar las rutinas sólo cuando se necesiten. Si las

subrutinas son grandes o tienen muchas referencias externas, se pueden conseguir ahorros

considerables de tiempo y espacio de memoria. De forma similar, supóngase que en cualquier

ejecución un programa usa solo pocas de una gran cantidad de subrutinas posibles, pero el

número exacto de rutinas necesarias no puede predecirse hasta que el programa examine la

entrada. Esta situación podría presentarse, por ejemplo, con un programa que permita al usuario

llamar interactivamente a cualquiera de las subrutinas de una gran biblioteca matemática y

estadística.

El usuario podría suministrar la entrada de datos desde un terminal de tiempo compartido, y los

resultados podrían exhibirse en el terminal. En este caso, podrían ser necesarias todas las

subrutinas de la biblioteca, pero en cualquier sesión de terminal sólo se usarían unas cuantas.

Las rutinas que se carguen dinámicamente deben llamarse por medio de una solicitud de 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.

Page 50: Libro Programación de Sistemas

El programa hace una solicitud de servicio de carga y llamada al sistema operativo. El parámetro

de esta solicitud es el nombre simbólico de la rutina llamada (fig. a). El sistema operativo examina

sus tablas internas para determinar si la rutina ya se ha cargado o no; en caso necesario, la rutina

se carga desde la biblioteca de usuario o desde el sistema especificado (fig. b).

Entonces el control pasa del sistema operativo a la rutina llamada (fig. c). Cuando se completa el

procesamiento de la subrutina llamada, vuelve a quien la llamó (es decir, a la rutina del sistema

operativo que maneja la solicitud de servicio de carga y llamada). Entonces el sistema operativo

devuelve el control al programa que hizo la solicitud (fig. d). Es importante devolver el control de

esta forma, para que el sistema operativo sepa cuándo la rutina llamada terminó su ejecución.

Una vez terminada la subrutina, puede ser C dinámico

Algunas veces es conveniente retener la rutina en la memoria para algún uso posterior, siempre y

cuando no se necesite el espacio de almacenamiento para otro proceso. Si una subrutina sigue en

la memoria, una segunda llamada a ella puede no necesitar otra operación de carga. El control

puede pasarse del cargador dinámico a la rutina llamada.

Cuando se utiliza ligado dinámico, la asociación de una dirección real y el nombre simbólico de la

rutina llamada no se hace hasta que se ejecuta la proposición de llamada.

Otra forma de escribir esto es decir que el ligamiento del nombre a una dirección real se retrasa

del tiempo de carga al tiempo de ejecución. Como ya se había expuesto, este ligamiento retardado

da como resultado una mayor flexibilidad, y también requiere mayor sobrecarga, ya que el sistema

operativo debe intervenir en el proceso de llamada.

3.5 Diseño y programación de un Cargador Algoritmo de cargador

1. colocar un programa objeto en la memoria

2. Iniciar su ejecución.

3. 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.

4. Se revisa el registro de encabezamiento para comprobar si se ha presentado el programa

correcto para la carga (entrando en la memoria disponible).

5. A medida que lee cada registro de texto, el código objeto que contiene pasa a dirección de la

memoria indicada.

6. Cuando se encuentra el registro de fin, el cargador salta a la dirección especificada para iniciar la

ejecución del programa cargado.

3.5.1 Cargador absoluto (ejemplo)

Page 51: Libro Programación de Sistemas

Hay dos aspectos del programa cargador que requieren una mayor explicación: la variable dir byte

y el campo dirini. El proceso de carga absoluta del siguiente cargador es: La variable dir_byte que

se declara como apuntador a un carácter o sea es la dirección de un carácter. Es razonable

suponer que se almacena un carácter usando un byte de -memoria y que, por consiguiente, la

variable dirbyte contiene la dirección de un byte de memoria. Inicialmente, esta .variable se asigna

igual a la constante DIR_CARGA.En cada iteración del lazo while, a la posición de memoria

identificada por dir_byte se le asigna el siguiente byte del archivo ejecutable; después se

incrementa en uno el valor de dirbyte. De esta manera, el contenido del archivo ejecutable se

copia a posiciones consecutivas de la memoria a cárter de DIRCARGA.

3.5.2 Cargador re localizable (ejemplo)

Para analizar el proceso de relocalización introduciremos dos términos: el espacio lógico de

direcciones y el espacio físico de direcciones. Un espacio lógico de direcciones representa el

espacio desde la perspectiva del programa, los únicos objetos que necesitan direcciones son

aquellos a los cuales hace referencia el programa. E I ensamblador y el enlazador usan el espacio

lógico de direcciones para completar sus etapas del proceso de traducción. El espacio físico de

direcciones representa la perspectiva de la memoria en la maquina. Cada posición de memoria

tiene una dirección. El cargador completa el proceso de traducción estableciendo la

correspondencia de las direcciones del programa entre el espacio lógico de direcciones y el

espacio físico.

Se pueden emplear dos técnicas para asegurar que la ejecución del programa sea correcta

después de moverlos: la relocalización estática y la relocalización dinámica. El termino estática en

relocalización estática se refiere al hecho de que los programas solo se pueden refocilara antes de

iniciar su ejecución.

Cuando se usa la relocalizacion dinámica los programas se pueden relocalizar en cualquier

momento incluso después de haber iniciado su ejecución, a esto se debe el nombre de

relocalizacion dinámica

Para la relocalizacion estática se requiere que el enlazador proporcione información de

relocalizacion adicional en el archivo ejecutable esta información de relocalizacion consiste en una

lista de parches que indican al cargador cuales son las posiciones del programa que tienen que

modificarse al mover el programa. La relocalizacion dinámica es más rápida y flexible que la

estática, pero requiere hardware de correspondencia de direcciones. Si no se proporciona este

tipo de hardware, será necesario emplear la relocalizacion estática.

La relocalizacion dinámica 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 en

posiciones contiguas de la memoria. En la fig. de la parte de abajo representa un cargador sencillo

Page 52: Libro Programación de Sistemas

que puede usarse con la relocalizacion dinámica. En este caso el cargador lee el 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 del programa a una rutina llamada

establecer_corespondencia. Al leer este código, observe que la función de cargar devuelve un

entero sin signo en lugar de un apuntador. Esto refleja el hecho de que la dirección inicial es un

dirección lógica y no una dirección física.

* establecer la correspondencia de direcciones */ establecer_correspondencia (dir_carga,

tamaño_prog); return((char*) encabezado.dirini); }

Relocalizacion.

Los cargadores que permiten la relocalización de programas se denominan cargadores

relocalizadores o cargadores relativos. Existen dos métodos para la relocalización. El primer

método utiliza un registro de modificación para describir cada parte del código que se ha de

cambiar al relocalizar el programa. La necesidad de relocalizar los programas es una consecuencia

directa del cambio a computadoras más grandes y potente. La forma de efectuar la relocalización

en un cargador también depende de las características de la máquina.

4 MACROPROCESADORES

Objetivo: Entender el funcionamiento de las diversas modalidades del macro procesamiento.

Con el fin de evitar al programador la tediosa repetición de partes idénticas de un programa, los

ensambladores y compiladores cuentan con macro procesadores que permiten definir una

abreviatura para representar una parte de un programa y utilizar esa abreviatura cuantas veces

sea necesario. Para utilizar una macro, primero hay que declararla. En la declaración se establece

el nombre que se le dará a la macro y el conjunto de instrucciones que representará.

El programador escribirá el nombre de la macro en cada uno de los lugares donde se requiera la

aplicación de las instrucciones por ella representadas. La declaración se realiza una sola vez, pero

la utilización o invocación a la macro (macrollamada) puede hacerse cuantas veces sea necesario.

La utilización de macros posibilita la reducción del tamaño del código fuente, aunque el código

objeto tiende a ser mayor que cuando se utilizan funciones.

Es tan común el empleo de macroinstrucciones se les considera como una extensión de los

lenguajes. De manera similar se considera al procesador de macroinstrucciones o

macroprocesador como una extensión del ensamblador o compilador utilizado. El

macroprocesador se encarga, en una primera pasada, de registrar todas las declaraciones de

macros y de rastrear el programa fuente para detectar todas las macrollamadas. En cada lugar

donde encuentre una macrollamada, el macroprocesador hará la sustitución por las instrucciones

Page 53: Libro Programación de Sistemas

correspondientes. A este proceso de sustitución se le denomina expansión de la macro. El

macroprocesador elabora dos tablas para el manejo de las macros:

Una tabla de macronombres que consiste de los nombres de las macros y un índice que le permite

localizar la definición de la macro en otra tabla llamada tabla de macrodefiniciones.

Como su nombre lo indica, la tabla de macrodefiniciones contiene las definiciones de todas las

macros a utilizar en el programa. En ocasiones es conveniente agrupar macros, de acuerdo a las

tareas que realizan, y almacenarlas en archivos que se constituyen en bibliotecas de macros. De

esta manera, cuando se requiera la utilización de alguna macro en particular, se incluye en el

programa fuente el archivo de la biblioteca de macros correspondiente.

Macroinstrucción es una pseudo operación o un conjunto de instrucciones a la cual se le asigna un

nombre para ser llamada y después utilizar su código. Estas permiten escribir una versión

abreviada de un programa. Dejando que el macroprocesador maneje los detalles internos, su

característica principal es sustitución de líneas de codigo por una referencia. Ejemplo:

En este ejemplo el nombre de la macro es DELAY, cuando se encuentra en un programa DELAY, el

ensamblador toma el cuerpo de esta macro del macro procesador y lo pasa al código fuente donde

encontró DELAY. La estructura de una macroinstrucción es la siguiente:

La tabla de nombres de macros es donde se almacenan las referencias de las macroinstrucciones,

la de códigos es donde se almacenan los códigos de cada macro y la de argumentos los

parámetros de cada macro.

Usos su uso más común es en el lenguaje ensamblador, debido a la complejidad de los

mnemónicos, pero la macro también puede ser un guión o puede tener un uso en aplicaciones

finales (Word, Excel) o para perfilar compiladores como visualbasic.

Rutina vs macro

Una rutina es un procedimiento (en este caso un conjunto de código) que es usado cada vez que

se le llame. Una rutina al ser llamada dentro de un programa hace que el código principal y se

dirija a ejecutar el código de la rutina, en cambio cuando se llama a una macro, el ensamblador

llama al código de la macro y lo implanta donde fue llamado, aumentando así el código fuente y

por consiguiente el objeto.

La idea aquí es que se incorpore un procesador de macros en su ensamblador de dos pasos.

Considere que su ensamblador es de dos pasos, por lo tanto ya tiene un procedimiento de

inserción y búsqueda de símbolos en la famosa estructura de datos llamada "tabla de símbolos".

Le sugiero que la tabla de símbolos sea creada por adelantado y con un cuarto campo en sus

registros, este campo adicional es en realidad una liga a una lista de elementos ( una lista

vinculada ), que contiene la información de las tres tablas empleadas por el reconocedor de

Page 54: Libro Programación de Sistemas

macros, el cual es un procedimiento muy sencillo de implantar al inicio del ensamblador. Acto

seguido, implemente las funciones básicas de un procesador de macros en el propio ensamblador.

De esta manera al escribir el código de su ensamblador se ahorrará mucho trabajo y tiempo.

4.1 importancia teórica de macro-expresiones y usos de un macro-procesador

Un macroinstrucción (abreviado frecuentemente como macro), no es más que una conveniencia

notacional para el programador. Una macro representa un grupo de proposiciones utilizadas

comúnmente en el lenguaje de programación fuente, para el caso, ensamblador. El procesador de

macros reemplaza cada macroinstrucción con el grupo correspondiente de proposiciones del

lenguaje fuente, lo que se denomina expansión de macros. Por todo lo anterior, las

macroinstrucciones permiten al programador escribir una versión abreviada de un programa,

dejando que el procesador de macros maneje los detalles internos. Las funciones básicas de un

procesador de macros son:

> Sustitución de líneas de código por una referencia simbólica.

> Calcular las direcciones efectivas de las referencias.

> Expansión de las referencias en un archivo intermedio.

El procesador de macros, como puede verse, no intenta ningún análisis ni traducción a código

objeto del programa fuente, más bien parece que el procesador hace que aumente el tamaño de

éste. Esto es un elemento clave para el programador, pues el uso indiscriminado de macros puede

hacer que el tamaño del código objeto sea enorme y poco práctico, al contrario de las llamadas a

subrutinas.

Claro que también se paga un precio alto por el empleo de las llamadas, pues se pierde tiempo

importante en la gestión de la pila, donde usualmente se pasan los parámetros. El

macroprocesador requiere tres estructuras de datos para su exitosa operación.

> La tabla de nombres de macros (TABNOM).

> La tabla de código de macros (TABDEF).

> La tabla de argumentos (TABARG).

Ahí se guarda toda la información pertinente a las macros, mientras el ensamblador analiza la

expansión y hace la traducción a código objeto. A veces hay confusión entre macros y subrutinas.

Subrutinas son rutinas comunes en el programa se accede a ellas haciendo llamados a estas, son

normalmente usadas para rutinas más complejas donde el retorno de llamada tolerada. Macros es

comúnmente usado para rutinas más simples o donde la velocidad de en código de linea es

requerida. Para poder utilizar una macro esta debe ser definida dentro del programa fuente. La

macrodefinicion consta de 3 partes estas son:

Page 55: Libro Programación de Sistemas

> la macro cabecera que especifica el macro nombre y su lista de parámetro

> el macro cuerpo que es la parte que es insertada actualmente dentro el programa de fuente

> el macro terminator

la cabecera se tiene de la siguiente forma:

ñame MACRO <parameter list>

El nombre del campo contiene un símbolo único que el usado para identificar la macro. Siempre

que el símbolo es encontrado en el programa fuente, se insertara la macro en el programa fuente

donde se apunta. El campo MACRO del encabezado de la macro contiene la llave de esta y esta le

dice al ensamblador donde comienza la definición de la misma.

El campo <parameter list> lista de 0 a 16 parámetros que serán usados en el cuerpo de la macro y

que son definidos por el tiempo del ensamblador, Los símbolos usados en la lista de parámetros

solo son usados por el ensamblador durante el tiempo de carga de la macro. El macro cuerpo

puede contener instrucciones, directivas, declaraciones de ensamble condicional o de control.

Ejemplos:

MULT_BY_16 MACRO (no parameters)

DIRECTADD MACRO DESTINATION,SOURCE (two parameters)

Tenemos 2 definiciones de terminación de macros: ENDM y EXITM, toda definición de macro debe

tener un ENDM para notificar al ensamblador que la definición de macro ha terminado, EXITM es

alternativa para usos de final de macros que son usadas con ensambles condicionales, cuando

EXITM es encontrado en un programa las declaraciones de ENDM son ignoradas.

Esta sección se trata de varias situaciones que surgen en el uso de macros y como a manejarlas.

Primero la macro definición es listada, entonces el programa fuente invoca la macro y finalmente

como la macro era expandida por el ensamblador. El uso más común de los procesadores de

macros es en la programación de lenguaje ensamblador. Para ilustrar los conceptos del uso de las

macros, se van a emplear ejemplos de la máquina SIC/XE, NeMiSyS y 80x86 con el TASM 2.0. Si

podemos aceptar que una macro también puede ser un guión, entonces las macros también

tienen su uso en aplicaciones finales ... por ejemplo EXCEL, P ORD ... etc. por mencionar algunos.

Pero también existen guiones para perfilar compiladores como DELPHI y como VISUALBASIC. A

continuación unos ejemplos.

Se definen 4 operadores especiales para el uso de macros:

% Cuando aparece este símbolo en la lista de parámetros el valor es pasado al cuerpo del

macro en vez del símbolo mismo.

Page 56: Libro Programación de Sistemas

c Cuando este símbolo precede a un carácter este es tomado como una literal y pasa al

cuerpo de la macro sin ! . este es útil cuando es necesario delimitar el cuerpo del macro. Por

ejemplo en la lista de parámetro siguiente, el parámetro segundo pasa a la macro seria una COMA

(,): GENERARJNST 75,!„STK_VALOR.

& Los símbolos de ambos lados se concatenan y el símbolo es removido.

»1 Cuando estos símbolos son usados, el comentario precedente NO será grabado y por lo

tanto NO será invocado en una macro.

4.1.1 Conceptos clave

Expansión:

Cuando el ensamblador se encuentra con una cabecera de MACRO, lo que hace es almacenarla

con su cuerpo correspondiente en una tabla. Posteriormente, cuando en el programa se utilice la

cabecera o el nombre de esa MACRO, el ensamblador accederá a la tabla mencionada y sustituirá,

en el programa, ese nombre de MACRO por el cuerpo de la misma. A la operación de búsqueda en

la tabla de macros se le conoce como "Llamada a la MACRO", y a la sustitución del nombre de la

MACRO por el cuerpo de la misma se denomina "Expansión de la MACRO". En otras palabras, El

ensamblador sustituye cada vez que aparezca la macro. No es como los procedimientos, que se

"llaman" pero no repiten el código.

Una macro puede llamar a otra o a sí misma:

Es posible una expansión de macros recursiva, siempre y cuando aseguremos una posición

definida de los símbolos que se van a emplear dentro de la macro. Por ejemplo para el SIC/XE,

dicha tarea es un poco difícil, aunque si se programa el expansor de macros como una máquina de

pila es posible la implementación. Un tipo recursivo es aquel cuyos valores son compuestos de

valores del mismo tipo. Es aquel que está definido en términos del mismo.

Recursividad:

La ventaja de la directiva LOCAL:

En general, el conjunto de valores de un tipo recursivo T, puede ser definido por un conjunto de

ecuaciones recursivas de la forma: T=..T.. El conjunto de ecuaciones recursivas puede tener

muchas soluciones. Si una macro es recursiva, es decir, si se llama a sí misma, deberá pasarse a sí

misma un parámetro que se modificará en cada expansión, y la macro deberá probar el parámetro

y terminar la recursión cuando llegue a cierto valor. En caso contrario, el ensamblador podría

ingresar en un ciclo infinito. Si esto sucede, el usuario deberá suspender explícitamente el

ensamblador.

Por otra parte está la solución de Intel, la cual nos dice que los símbolos internos de las macros los

deberemos marcar como "LOCAL", para que la reubicación de los mismos sea factible en la

segunda pasada del ensamblador. Directiva que le indica al ensamblador que dentro de la macro

Page 57: Libro Programación de Sistemas

van a existir una serie de etiquetas que deben de ser identificadas de una forma especial al realizar

la expansión de la macro y siempre considerando la relación que existe con la tabla de símbolos.

Con ello se evita las definiciones múltiples de estas etiquetas. El formato es el siguiente: LOCAL

etiquetas (separadas por comas), Esta directiva debe situarse, en el caso de que exista después de

la cabecera de la macro.

Etiquetas en macros: se tienen 2 alternativas para especificar etiquetas en el cuerpo de una

macro: una etiqueta puede ser un parámetro o puede ser generada dentro del cuerpo de la

macro.

4.2 Microprocesadores con argumentos y Microprocesadores recursivos

Las macros de la página anterior, más o menos tienen la misma pauta. El prototipo de una macro

comienza con la palabra clave MACRO, el nombre de la macro y opcionalmente una línea con

argumentos, que son los parámetros de la macro. En el caso de las macros de Intel, con el TASM

2.0 o el MASM de IBM, primero se empieza con el nombre de la macro y después con la palabra

clave MACRO. También se cuenta con línea de argumentos.

Es posible una expansión de macros recursiva, siempre y cuando aseguremos una posición

definida de los símbolos que se van a emplear dentro de la macro. Por ejemplo para el SIC/XE,

dicha tarea es un poco difícil, aunque si se programa el expansor de macros como una máquina de

pila es posible la implementación. Por otra parte está la solución de Intel, la cual nos dice que los

símbolos internos de las macros los deberemos marcar como "LOCAL", para que la reubicación de

los mismos se factible en la segunda pasada del ensamblador.

• TIPOS RECURSIVOS EN GENERAL: Un tipo recursivo es aquel cuyos valores son compuestos de

valores del mismo tipo. Es aquel que está definido en términos de el mismo. En general, el

conjunto de valores de un tipo recursivo T, puede ser definido por un conjunto de ecuaciones

recursivas de la forma: T=..T.. El conjunto de ecuaciones recursivas puede tener muchas

soluciones. STRING Una String es una secuencia de caracteres. Las strings son soportadas por

todos los lenguajes de programación moderna. Pero no se tiene consenso en su clasificación: Una

string puede ser primitiva o compuesta? Qué tipo de operación debe tener? Una string como un

tipo primitivo, con valores que son strings de cualquier longitud. Ejem. ML. Una string como una

array de caracteres: Pascal y Ada. Una string como una lista de caracteres: Miranda y Prolog.

4.3 Incorporación del procesador de macros al ensamblador

La idea aquí es que se incorpore un procesador de macros en su ensamblador de dos pasos.

Tomando en cuenta que el ensamblador es de dos pasos, por lo tanto ya tiene un procedimiento

de inserción y búsqueda de símbolos en la famosa estructura de datos llamada "tabla de

símbolos", se sugiere que la tabla de símbolos sea creada por adelantado y con un cuarto campo

en sus registros, este campo adicional es en realidad una liga a una lista de elementos ( una lista

vinculada ), que contiene la información de las tres tablas empleadas por el reconocedor de

Page 58: Libro Programación de Sistemas

macros, el cual es un procedimiento muy sencillo de implantar al inicio del ensamblador. Acto

seguido, implemente las funciones básicas de un procesador de macros en el propio ensamblador.

Ventajas:

• grupos pequeños Repetidos de instrucciones reemplazadas por 1 macro

• Errores en macros son fijos solo una vez, en la Duplicación

• Por definición el esfuerzo es reducido

• En efecto, instrucciones de nivel más alto nuevo puede ser creado

• Programa es hecho más fácil, error menos boca abajo

• Generalmente más rápido en ejecución que subrutinas

Desventajas

• En programas grandes, tamaño de código de producto mayor que procedimientos Cuando usar

macros:

• Para reemplazar grupos pequeños de instrucciones no merecedor de subrutinas

• Para crear un conjunto de instrucción más alta para aplicaciones especificas

• Para crear compatibilidad con otros ordenadores

• Para reemplazar porciones de código que es repetido a menudo por todo

Macros es expandido cuando el programa es reunido. Este medio que cada suceso del macro

nombre (aparte desde la definición) es reemplazado por las declaraciones en la macro definición.

Un ejemplo demostrara este.

5 GLOSARIO

Instrucción o sentencia

Línea o líneas de un programa donde se da la orden de realización de un operación o conjunto de

operaciones particulares. Además del término general, distinguiremos dos tipos de instrucciones.

Instrucción privilegiada

Es aquella que para ser ejecutada necesita que el programa o usuario tengan ciertos privilegios.

Page 59: Libro Programación de Sistemas

Macroinstrucción

Instrucción en el lenguaje fuente que es reemplazada por una secuencia definida de instrucciones

en el mismo lenguaje fuente, todas las macroinstrucciones son expandidas por el compilador o

ensamblador al conjunto de instrucciones que representan.

Código maquina

Representación de instrucciones y datos de un programa ejecutables directamente por una

computadora.

Programa

•Secuencia de instrucciones que representan la resolución de un algoritmo y que pueden ser

ensambladas, compiladas o interpretadas con el fin de obtener un programa ejecutable en código

máquina para realizar un trabajo útil para el usuario

Módulo

Unidad de programa que puede ser compilada y unida a otros módulos para formar un programa

completo, también lo podemos definir como una parte separable de un programa. Los programas

o módulos , según el proceso de conversión a código máquina, pueden ser Programa Fuente y

Programa Objeto o Programa Ejecutable.

Programa Fuente

Programa escrito en ensamblador o lenguaje de alto nivel (FORTRAN, COBOL, PASCAL, C, etc) que

debe ser ensamblado, compilado o interpretado antes de ejecutarse en la computadora.

Normalmente son editados por el usuario o programador por medio de un editor.

Módulo Objeto

Page 60: Libro Programación de Sistemas

Es un módulo fuente ensamblado o compilado que está listo para ser unido a otros para formar un

programa ejecutable. Si se trata de todo un programa (un solo módulo) se denomina programa

objeto.

Programa Ejecutable

Programa construido por el editor de enlace o montador (linker) a partir de uno o más módulos

objeto y de rutinas de librería. Este programa puede ser cargado en memoria y ejecutado. En el

proceso de traducción o conversión de un programa fuente a ejecutable entran en juego unos

archivos cuya composición es un conjunto de módulos que puede-ser reclamados por los distintos

elementos a traducir, denominados librerías. Pueden ser tres clases: Librería de Programas,

Librería Objeto, Librerías del Sistema.

Librería de Programas

Archivo que contiene una colección organizada de programas

Librería Objeto

Archivo compuesto de una colección de rutinas que pueden ser solicitadas e incorporadas por los

distintos programas al hacer referencia a las mismas.

Librería del Sistema

Colección controlada de software perteneciente al sistema y que puede ser incorporado a un

programa de igual forma que una rutina de librería objeto.

Ensamblador

En la traducción de un programa fuente a código máquina se utilizan diversos programas que

forman parte del sistema operativo. Estos programas traductores pueden ser: Ensamblador,

Ensamblador Cruzado, Compilador, Compilador cruzado, Intérprete. Programa Utilizado para

traducir un programa escrito en lenguaje ensamblador a lenguaje de máquina de tal forma que la

traducción se realiza convirtiendo cada sentencia fuente en una instrucción de máquina. En la

traducción se sustituyen las direcciones simbólicas por direcciones absolutas.

Ensamblador Cruzado

Page 61: Libro Programación de Sistemas

Programa traductor de lenguaje ensamblador a lenguaje de máquina que se ejecuta en una

computadora y traduce para ejecutar en otro distinto.

Compilador

Programa traductor de un lenguaje de alto nivel a su código de máquina absoluto o reubicable

equivalente. La traducción se realiza de tal forma que una sentencia fuente se convierte en varias

instrucciones máquina, efectuando además un control previo de errores de todo el programa. Si

existen errores, la traducción se interrumpe.

Compilador Cruzado

Programa traductor de lenguaje de alto nivel a lenguaje de máquina que se ejecuta en una

computadora, generando el código para ser ejecutado en otra distinta.

Interprete

Programa traductor de lenguaje de alto nivel a código máquina, de tal forma que una sentencia

fuente se convierte en varias instrucciones máquina y tras la traducción de cada! una de ellas se

ejecutan sin esperar a traducir la siguiente.

Editor

Los sistemas operativos para la construcción de programas suelen además contar con las

siguientes utilidades o utilitarios: Editor, Editor de Enlace, Cargador, Depuradora Este es un

programa que permite escribir o corregir archivos de texto, generalmente programas fuente.

Editor de enlace

También denominado montador, es un programa para crear un código ejecutable a partir) de uno

o más módulos objeto resolviendo las referencias existentes entre los mismos y asignando

direcciones definitivas a los elementos reubicables. también extraen las rutinas necesarias de las

librerías para incluirlas en el programa ejecutable final.

Cargador

Es una rutina que lee un programa ejecutable y lo almacena en la memoria principal antes ;de su

ejecución.

Depurador

Page 62: Libro Programación de Sistemas

Es un programa de ayuda que permite ejecutar un programa fuente paso a paso investigando la

imagen del mismo, que se va creando en la memoria con el fin de analizarlo: y corregir posibles

errores.

Ejecución

Proceso de llevar a efecto las instrucciones de un programa ejecutable previamente cargado en la

memoria principal.

Proceso

Se utiliza este término para hacer referencia a un programa en ejecución.

6 ANEXOS

6.1 CÓDIGO ASCII

El código ASCII (acrónimo inglés de American Standard Code for Information Interchange —

Código Estadounidense Estándar para el Intercambio de información), pronunciado generalmente

[áski], es un código de caracteres basado en el alfabeto latino tal como se usa en inglés moderno y

en otras lenguas occidentales. Fue creado en 1963 por el Comité Estadounidense de Estándares

(ASA, conocido desde 1969 como el Instituto Estadounidense de Estándares Nacionales, o ANSÍ)

como una refundición o evolución de los conjuntos de códigos utilizados entonces en telegrafía.

Más tarde, en 1967, se incluyeron las minúsculas, y se redefinieron algunos códigos de control

para formar el código conocido como US-ASCII.

Casi todos los sistemas informáticos actuales utilizan el código ASCII o una extensión compatible

para representar textos y para el control de dispositivos que manejan texto.

El código ASCII define una relación entre caracteres específicos y secuencias de bits; además de

reservar unos cuantos códigos de control para el procesador de textos, y no define ningún

mecanismo para describir la estructura o la apariencia del texto en un documento; estos asuntos

están especificados por otros lenguajes como los lenguajes de etiquetas.

6.2 SECCIONES DEL MANUAL DE REFERENCIA DEL HC12

6.2.1 MODELO DE PROGRAMACIÓN

El modelo de programación de cualquier dispositivo lo obtenemos del mismo proveedor, quien

nos lo hace saber por medio de su manual de referencia.

Page 63: Libro Programación de Sistemas

Jerarquía de memoria

En una computadora hay una jerarquía de memorias atendiendo al tiempo de acceso y a la

capacidad que normalmente son factores contrapuestos por razones económicas y en muchos

casos también físicas. Comenzando desde el procesador al exterior, es decir en orden creciente de

tiempo de acceso y capacidad, se puede establecer la siguiente jerarquía:

Registros de procesador: Estos registros interaccionan continuamente con la CPU (porque forman

parte de ella). Los registros tienen un tiempo de acceso muy pequeño y una capacidad mínima,

normalmente igual a la palabra del procesador (1 a 8 bytes).

❖ Registros intermedios: Constituyen un paso intermedio entre el procesador y la memoria,

tienen un tiempo de acceso muy breve y muy poca capacidad.

❖ Memorias caché: Son memorias de pequeña capacidad. Normalmente una pequeña fracción de

la memoria principal, y pequeño tiempo de acceso. Dentro de la memoria caché puede haber, a su

vez, dos niveles denominados caché on chip, memoria caché dentro del circuito integrado, y caché

on board, memoria caché en la placa de circuito impreso pero fuera del circuito integrado,

evidentemente, por razones físicas, la primera es mucho más rápida que la segunda. Existe

también una técnica, denominada Arquitectura Harvard, en cierto modo contrapuesta a la idea de

Von Newmann, que utiliza memorias caché separadas para código y datos. Esto tiene algunas

ventajas como se verá en este capítulo.

❖ Memoria central o principal: En este nivel residen los programas y los datos. La CPU lee y

escribe datos en él aunque con menos frecuencia que en los niveles anteriores. Tiene un tiempo

de acceso relativamente rápido y gran capacidad.

❖ Extensiones de memoria central: Son memorias de la misma naturaleza que la memoria central

que amplían su capacidad de forma modular. El tiempo de similar, a lo sumo un poco mayor, al de

la memoria central y su capacidad puede ser algunas veces mayor.

❖ Memorias de masas o auxiliares: Son memorias que residen en dispositivos externos al

ordenador, en ellas se archivan programas y datos para su uso posterior, también se usan estas

memorias para apoyo de la memoria central en caso de que ésta sea insuficiente (memoria

virtual). Estas memorias suelen tener gran capacidad pero pueden llegar a tener un tiempo de

acceso muy lento. Dentro de ellas también se pueden establecer varios niveles de jerarquía.

Clasificación de memorias semiconductoras de acceso aleatorio

Las memorias se clasifican, por la tecnología empleada y, además según la forma en que se puede

modificar su contenido, A este respecto, las memorias se clasifican en dos grandes grupos:

Page 64: Libro Programación de Sistemas

• Memorias RAM: Son memorias en las que se puede leer y escribir, si bien su nombre (Random

access memory) no representa correctamente este hecho. Por su tecnología pueden ser de ferritas

(ya en desuso) o electrónicas. Dentro de éstas últimas hay memorias estáticas (SRAM, static RAM),

cuya célula de memoria está basada en un biestable, y memorias dinámicas (DRAM, dinamic RAM,

en las que la célula de memoria es un pequeño condensador cuya carga representa la información

almacenada. Las memorias dinámicas necesitan circuitos adicionales de refresco ya que los

condensadores tienen muy poca capacidad y, a través de las fugas, la información puede perderse,

por otra parte, son de lectura destructiva.

• Memorias ROM (Read Only Memory): Son memorias en las que sólo se puede leer. Pueden ser:

o ROM programadas por máscara, cuya información se graba en fábrica y no se puede modificar,

o PROM, o ROM programable una sola vez.

• EPROM (erasable PROM) o RPROM (reprogramable ROM), cuyo contenido puede borrarse

mediante rayos ultravioletas para regrabarlas.

• EAROM (electrically alterable ROM) o EEROM (electrically erasable ROM), que son

memorias que está en la frontera entre las RAM y las ROM ya que su contenido puede

regrabarse por medios eléctricos, estas se diferencian de las RAM en que no son volátiles.

En ocasiones a este tipo de memorias también se las denomina NYRAM (no volátil RAM), o

Memoria FLASH, denominada así por la velocidad con la que puede reprogramarse,

utilizan tecnología de borrado eléctrico al igual que las EEPROM. Las memorias flash

pueden borrarse enteras en unos cuantos segundos, mucho más rápido que las EPROM.

Básicamente las memorias ROM se basan en una matriz de diodos cuya unión se puede destruir

aplicando sobre ella una sobretensión (usualmente comprendida ente -12.5 y -40 v.). De fábrica la

memoria sale con 1's en todas sus nosiciones, para grabarla se rompen las uniones en que se

quieran poner 0's. Esta forma de realizar la grabación se denomina técnica de los fusibles.