Está en la página 1de 83

Revisión 2011

INTRODUCCIÓN A LA PROGRAMACIÓN DE
SISTEMAS
Software de Sistemas | Varios Autores
INTRODUCCIÓN A LA 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.

2
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

Índice
1. ESTRUCTURA DE LA COMPUTADORA........................................................................................ 4
2. ENSAMBLADORES................................................................................................................ 20
3. CARGADOR – LIGADOR............................................................................................................ 49
4. MACROPROCESADORES. ......................................................................................................... 68
5. GLOSARIO. ............................................................................................................................... 76
6. ANEXOS. .................................................................................................................................. 80

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

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

3
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.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,
es uno de los componentes necesarios encontrados en las computadoras

4
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

de cualquier tiempo, junto con el almacenamiento primario y los


dispositivos de entrada/salida. Desde mediados de los años 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.

5
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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

6
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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 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:

o Bus único: La primera gran diferencia entre estas dos tipos de


estructuras es que el bus único no permite un controlador DMA

7
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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


que soporta este controlados
o 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:
 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.

8
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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

9
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

10
INTRODUCCIÓN A LA 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

11
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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
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á

12
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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

13
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 será 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

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

14
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

15
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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
mnemó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

16
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

nos servirá para manejar estructuras de datos complejas como vectores,


matrices, etc. Reducir el número de bits del campo de operando.

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.

17
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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

18
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

1.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).
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 Bits.

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.

19
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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

20
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 (rótate 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 línea
código) línea por línea. Su sintaxis es la siguiente: nombre del campo,
operación del campo, operando del campo, sintaxis del campo, ejemplo:

21
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

 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 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.
o 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.
o 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”.

22
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

o 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.
o 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.
o 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).
o Constantes: Las constantes representan cantidades de
información que no varían en su valor durante la ejecución
del programa.
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
binaria y son desplegadas en el listado del ensamblado como
valores hexadecimales.
o 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.

23
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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", qué quiero del 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.

• 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

24
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 ensamblador 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

25
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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:
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 el
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.
o 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.

26
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

o MODO DE DIRECCIONAMIENTO: aunque existen "E" modos de


direccionamientos, no todos son aplicables a los micros.
o MNEMONICO: las instrucciones aunque en concepto podrían ser las
mismas, se enuncian de diferente manera.
o 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.

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.
o DIRECTIVAS: también existen las llamadas DIRECTIVAS o
PSEUDOINSTRUCCIONES, las cuales especifican acciones auxiliares
que se llevan a cabo por el ensamblador.
o PERIFÉRICOS: todo dispositivo que será controlado por el micro
o 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

27
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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:


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,

28
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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

29
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

30
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

31
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

32
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

33
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

34
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

35
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.
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:
o Leer sentencia o instrucción. Analizar sentencia o instrucción.
o Tratamiento de etiquetas.
o Buscar en tabla de símbolos (si no está, pasar al siguiente paso).
o Insertar en tabla de símbolos.
o Tratamiento de código de operación.
o Buscar en tabla de código de operación y actualizar campo de
dirección.
o Escribir código de operación.
o Buscar en tabla de pseudo- instrucciones y hacer el tratamiento de
la pseudo-instrucción.
o Análisis del operando (en caso de la creación de un código
intermedio).
o Almacenar en tabla de símbolos.
o Buscar en tabla de símbolos.
o 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,

36
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

37
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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:
o Nombre de la rutina, subprograma o programa.
o Sección binaria con el programa en forma semicompilada y con la
información necesaria para la localización.
o Tabla de definición, con los símbolos globales definidos en la rutina.
o 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 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.
Lectura del programa de memoria secundaria.
o Tratamiento de sentencias o instrucciones. En el primer paso sólo se
analizaban las sentencias para ver si eran correctas.
o 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.
o Buscaren tabla de código de operación. Obtener código de máquina
y su longitud.
o Actualizar contador de direcciones.

38
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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


pseudoinstrucción.
o Tratamiento del operando.
o Buscaren tabla de símbolo (si es símbolo). Obtener la dirección.
o Obtener valor (si no es símbolo se obtiene la dirección
directamente).
o 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).

o Un proceso necesita memoria para ejecutar programas o Código del


programa o Datos estáticos y dinámicos.
o 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.
o El rendimiento global del sistema mejora si se pueden ejecutar
varios procesos concurrentemente.
o 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 del 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 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

39
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 la 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

40
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

41
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 de ensamblar código de 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 la 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 una meta ensamblador:


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

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 metaensamblador es diseñar la


entrada. La entrada debería incluir una descripción del conjunto de

42
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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
metaensamblador sin hacerle cambios. El metaensamblador 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.

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.

43
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.
o Llamada también dirección virtual.
• Dirección física
o La usada realmente en el Registro de Direcciones de Memoria.
• Carga dinámica
o Se trata de no perder tiempo cargando código que luego no se
ejecuta.
o Al empezar solo se carga el programa principal.
o Las subrutinas no se cargan hasta que son llamadas.
o Solo hace falta tener una tabla de rutinas cargadas y una forma
especial de llamarlas
o No hace falta un SO especial, solo un cargador reubicable.
o El espacio en memoria está reservado para el proceso, pero no
se utiliza siempre.
• Enlace dinámico
o Se trata de no reservar espacio para las subrutinas hasta el
momento de la ejecución.
o 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.
o 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
o Se pueden tener varias versiones de la misma biblioteca o
Bibliotecas Compartidas
o Necesita que el SO compruebe que no se vulnera la protección
de memoria.
• Solapamientos (overlays)
o Técnica que permite ejecutar un programa que sea mayor que la
memoria principal disponible.
o Se basa en mantener en memoria solo las instrucciones y Tatos
que se necesita en cada momento.
o No hace falta soporte Tel SO.
o Hace falta programar el traductor y el montador ® Hace falta un
programador experto

44
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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:


• Preciso: Esto quiere decir que debe indicar el orden en cada paso.
• Definido: Es decir, si se sigue dos veces, obtiene el mismo resultado
cada vez.
• 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 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

45
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 más 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

46
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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

47
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 término
Registro de dato S7 archivo de 32 bits de dirección
SI (2 bytes) dato S8 archivo de 24 bits de dirección
S2 (3 bytes) dato S9 archivo de 16 bits de dirección
S3 (4 bytes) dato
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:

48
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 execue(). 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.

49
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

Algunas veces existe un archivo independiente de entrada al cargador que


contiene esas proposiciones de control. En ocasiones esas mismas
proposiciones también pueden estar intercaladas en el flujo primario de
entrada entre los programas objeto. En ciertos 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

50
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 son:


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

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

51
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

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.

52
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 sí, 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.

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

53
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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:


• Ahora ya se puede presentar un algoritmo de un cargador ligador y
relocalizador, se utilizan registros de modificación para que las
funciones de relocalización y ligado se realicen por medio de este
mecanismo.

• 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

54
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

ligado requerida no se puede realizar hasta haber asignado una


dirección al símbolo externo implicado.

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

55
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

Cada segmento, excepto la 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 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

56
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

Un programa montado sin errores se puede ejecutar; antes de eso, el


programa está en un fichero de almacenamiento secundario, ¿como lo

57
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 archivo 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

58
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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
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 usted, explicara ¿qué pasa en otras plataformas? UNIX, MAC,
etc.

59
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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

60
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

61
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

62
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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.

63
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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

Entonces el control pasa del sistema operativo a la rutina llamada. 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. Es importante devolver el control

64
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

65
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

3.5.1 Cargador absoluto (ejemplo)


Hay dos aspectos del programa cargador que requieren una mayor
explicación: la variable dirbyte 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 relocalización 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 relocalización dinámica.

66
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

Para la relocalización estática se requiere que el enlazador proporcione


información de relocalización adicional en el archivo ejecutable esta
información de relocalización 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 relocalización 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 relocalización estática.

La relocalización 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 que puede usarse con la
relocalización 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 correspondencia. 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 una dirección
lógica y no una dirección física.

Relocalización.
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.

67
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 macro procesador como una extensión del
ensamblador o compilador utilizado. El macro procesador se encarga, en
una primera pasada, de registrar todas las declaraciones de macros y de
rastrear el programa fuente para detectar todas las macro llamadas. En
cada lugar donde encuentre una macro llamada, el macro procesador hará
la sustitución por las instrucciones correspondientes. A este proceso de
sustitución se le denomina expansión de la macro. El macro procesador
elabora dos tablas para el manejo de las macros:

Una tabla de macro nombres 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 macro definiciones.

Como su nombre lo indica, la tabla de macro definiciones contiene las


definiciones de todas las macros a utilizar en el programa. En ocasiones es

68
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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 macro procesador maneje los detalles internos, su
característica principal es sustitución de líneas de código 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 visual basic.

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.

69
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

70
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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:
• 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 terminador.

La cabecera se tiene de la siguiente forma:


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

71
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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, WORD... 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.

“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 (,):
GENERAR INST 75, STK_VALOR. & Los símbolos de ambos lados se
concatenan y el símbolo es removido.

72
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

73
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

74
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

• 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 del 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.
Ejemplo. 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 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.

75
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

Desventajas:
• En programas grandes, el tamaño de código de producto es mayor que
el de los 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.

5. GLOSARIO.

Cargador
Es una rutina que lee un programa ejecutable y lo almacena en la
memoria principal antes de su ejecución.

Código maquina
Representación de instrucciones y datos de un programa ejecutables
directamente por una computadora.

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.

76
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

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.

Ejecución
Proceso de llevar a efecto las instrucciones de un programa ejecutable
previamente cargado en la memoria principal.

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
Programa traductor de lenguaje ensamblador a lenguaje de máquina que
se ejecuta en una computadora y traduce para ejecutar en otro distinto.

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.

77
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

Instrucción privilegiada
Es aquella que para ser ejecutada necesita que el programa o usuario
tengan ciertos privilegios.

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.

Librería de Programas
Archivo que contiene una colección organizada de programas.

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.

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.

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.

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.

Módulo Objeto
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.

78
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

Proceso
Se utiliza este término para hacer referencia a un programa en ejecución.

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.

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.

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.

79
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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.

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

80
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

81
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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:

• 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, PROM, o ROM programable una
sola vez.
o EPROM (erasable PROM) o RPROM (reprogramable ROM), cuyo
contenido puede borrarse mediante rayos ultravioletas para
regrabarlas.
o 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.

82
INTRODUCCIÓN A LA PROGRAMACIÓN DE SISTEMAS

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

83

También podría gustarte