Es un programa especial, parte del sistema operativo que tiene como propósito colocar en la memoria las instrucciones y datos de un programa o información codificada en lenguaje máquina, para que entonces la computadora pueda procesarla. Un cargador es un programa que realiza la función de carga, pero muchos cargadores también incluyen relocalización y ligado. Algunos sistemas tienen un ligador para realizar las operaciones de enlace, y un cargador separado para manejar la relocalización y la carga. Los procesos de ensamblado y carga están íntimamente relacionados. FUNCION DE UN CARGADOR Las funciones de un cargador son: Colocar un programa objeto en la memoria e iniciar su ejecución. Si tenemos un cargador que no necesita realizar las funciones de ligado y relocalización de programas, su operación es muy simple, pues todas las funciones se realizan en un solo paso. Se revisa el registro de encabezamiento para comprobar se ha presentado el programa correcto para la carga (entrando en la memoria disponible). A medida que se lee cada registro de texto, el código objeto que contiene pasa a la dirección de memoria indicada. Cuando se encuentra el registro de fin, el cargador salta a al dirección especificada para iniciar la ejecución del programa cargado. Un programa objeto contiene instrucciones traducidas y valores de datos del programa fuente, y específica direcciones en memoria donde se cargarán estos elementos. Las funciones de un cargador son relativamente sencillas y consisten en extraer información de algún medio exterior de la memoria (por ejemplo: CD Discos) y chocarlo en celdas sucesivas de la memoria a partir de una celda pre especificada. El cargador realiza la última etapa del proceso de traducción: cargar el programa en memoria donde puede ser ejecutado. Una opción típica del cargador permite la selección de fuentes alternativas de entrada. Otros mandatos permiten al usuario eliminar símbolos externos o secciones de control completas. También es posible cambiar referencias externas dentro del programa que se está cargando, La mayoría de los cargadores permiten al usuario especificar alternativas para búsqueda por medio de una proposición de tipo LIBRARY. TIPOS DE CARGADORES: • Cargadores iniciales.- Indican a la computadora la forma de poner, dentro de la memoria principal, unos datos que están guardados en un periférico de memoria externa (cinta, disco, etc.). Sirven para cargar en la memoria pequeños programas que inician el funcionamiento de una computadora. Algunas computadoras de carácter general no tienen en memoria ningún programa de forma permanente y cuando se desconectan pierden toda la información de su memoria interna. Al volverlos a conectar no son capaces de controlar ningún periférico (teclado, discos, etc.). Esto se hace así para que sea el usuario el que ponga los programas que le interese ejecutar. • Cargadores absolutos.- Como ya se menciono el programa cargador pone en memoria las instrucciones guardadas en sistemas externos. Independientemente de que sea un cargador inicial o no, si dichas instrucciones se almacenan siempre en ele mismo espacio de memoria (cada vez que se ejecuta el programa cargador), se dice que es un cargador absoluto. • Cargadores con reubicación.- En ocasiones, un mismo programa necesita ejecutarse en diferentes posiciones de memoria. Para esto la traducción debe estar realizada en forma adecuada, es decir, no utilizando referencias absolutas a direcciones de memoria, sino referencias relativas a una dirección especial llamada dirección de reubicación. El cálculo de las direcciones reubicables lo realiza el propio cargador a medida que va guardando las instrucciones en el espacio de memoria que le indique el usuario o el propio sistema operativo de la máquina. A los cargadores que permiten estas operaciones se les denominan cargadores con reubicación. • Cargadores ligadores.- Conocidos también por su término inglés Link editor o simplemente Linker, es muy común también referirse a él por la castellanización del nombre inglés, «lincador». A la acción de montar se le llama asimismo vulgarmente «lincar». Montar un programa consiste en añadir al programa objeto obtenido en la traducción las rutinas externas a las que hace referencia dicho programa. El ensamblador debe permitir dichas referencias y las rutinas deben estar a su vez en lenguaje máquina guardadas en algún elemento accesible por el montador. Generalmente, dichas rutinas se encuentran guardadas en un fichero especial al que suele denominarse librería, porque están almacenadas todas las rutinas externas susceptibles de ser utilizadas por los diferentes programas del usuario. Allí va el programa ligador cuando esta realizando el montaje de un programa a buscarlas y las adjunta al programa objeto. CARGADORES BOOTSTRAP. El programa cargador, una vez situado en la memoria del computador, cargará el programa de aplicación y los datos. Pero, previamente, se ha debido cargar el cargador en la memoria y esto se puede realizar por uno de los métodos siguientes: Entrada Manual: Mediante el teclado, el usuario teclea en la máquina el cargador bootstrap. Después de esto, el cargador se carga a sí mismo en la memoria del computador. A partir de este momento, es el cargador el encargado de cargar el programa de aplicación en la memoria. Entrada por ROM: Es posible tener las instrucciones de inicialización almacenadas permanentemente en alguna porción de la ROM, en lugar de introducirlas manualmente por teclado o por el 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. CARGADORES ABSOLUTOS. Este es un programa que carga cada instrucción del programa objeto en una posición fija y preestablecida. Por tanto, cada instrucción tiene una dirección absoluta. El cargador absoluto lee simplemente la línea de código objeto que contiene la dirección de inicio de las instrucciones y datos, y carga las palabras (o bytes) sucesivas en posiciones de memoria sucesivas. El cargador absoluto tiene un serio inconveniente cuando se utiliza en sistemas computadores grandes. Esto significa que los programas y datos se deben almacenar cada vez en posiciones de memoria distintas. Si se utilizan cargadores absolutos, el programa objeto se tendrá que modificar para que refleje la nueva posición de inicio de memoria. Esta es una actividad larga y sujeta a errores. En tales situaciones, se utilizan cargadores relocatables. Los cargadores absolutos están diseñados generalmente para verificar cada instrucción que leen. Si se detecta una instrucción ilegal, se interrumpe el proceso de carga. CARGADORES RELOCATABLES. Este cargador evita el principal inconveniente del cargador absoluto. El cargador relocatable es un programa más sofisticado, tiene las características del cargador absoluto, y además permite al usuario seleccionar y especificar las posiciones de memoria en las que se debe almacenar las palabras de instrucciones y datos. De esta forma, el mismo programa se puede cargar en distintas zonas de la memoria sin necesidad de reensamblarlo o recompilarlo. Durante el ensamblado o compilación del programa objeto, éste empieza con la dirección. Las sucesivas instrucciones quedan asignadas a posiciones de memoria consecutivas. No obstante, las direcciones no son absolutas, es decir, no representan las verdaderas posiciones de memoria en las que se está almacenando el programa. Se trata de direcciones relativas. El programador inserta la dirección se añade a cada una de las posiciones de memoria asignadas en el programa, obteniéndose Las direcciones reales de las instrucciones y datos del programa. El cargador relocatable ofrece algunas ventajas. EL PROCESO DE CARGA ABSOLUTA Los cargadores absolutos existen en sistemas de los que los compiladores generan código absoluto (no relocalizables).De esta forma se obliga a que el programa se obliga a cargar las mismas posiciones son relativamente pero no permiten tener multiprogramación. La carga absoluta necesita que el modulo de carga ocupe siempre la misma posición de memoria principal. Así pues, todas las referencias del modulo de carga para el cargador deben ser direcciones especificas o absolutas en memoria principal. La asignación de direcciones específica a la referencia de memoria de un programa puede ser realizada tanto por el programador en tiempo de compilación o ensamblaje. Con este método se tienen varias desventajas las cuales son: ¤ Todos los programadores tendrán que conocer la estrategia de asignación deseada para situar los módulos en memoria principal. ¤ Si se hace alguna modificación en el programa que se suponga inserciones o borrados en el cuerpo modulo tendrán que cambiarse las direcciones por consiguiente es expresar simbólicamente y que se resuelvan en el momento de la compilación o ensamblaje. Cuando se prepara el modulo para la entrada a un cargador absoluto, el ensamblador o el compilador convertirá todas esas diferencias a direcciones. Se denomina cargador absoluto porque carga el programa ejecutable en una posición fija. En algunas cargadores absolutos la dirección de carga esta denominada por un campo en el encabezado del archivo ejecutable .Aunque esta estrategia es un poco mas general que el empleo de una constante predefinida, la posición usada para el programa se sigue determinando al ensamblar y enlazar el programa. En esencia el cargador copia los segmentos de texto y datos de un archivo ejecutable a la memoria de la maquina. A continuación se presenta el pseudo código para un cargador sencillo En este código, el cargador comienza leyendo la porción de encabezado contiene la dirección de inicio , ósea la dirección de la primera instrucción que ese ejecuta la .Después de leer el encabezado el cargador entra a u lazo en el cual se copian a la memoria de la maquina los demás bytes del archivo ejecutable (los segmentos de texto y datos ).Por ultimo , el cargador devuelve el valor del campo de dirección inicial del encabezado. Supuestamente, este valor se usa como destino de una instrucción de ramificación (o de salto o subrutina) cuando se ejecuta el programa. Hay dos aspectos del programa cargador que requiera una mayor explicación: la variable dir_ byte el campo dir_ini. Comenzaremos por la variable dir_byte , que se declara como apuntadores a un carácter, ósea, es la dirección de un carácter. Es razonable suponer que la almacena un carácter usando un byte de memoria y que, por consiguiente, la variable dir_byte contiene la dirección de un byte de memoria .Inicialmente, esta variable se asigna igual a la constante DIR_CARGA. En cada interacción el 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 un valor de dir_byte. De esta manera, el contenido del archivo ejecutable se copia a posiciones consecutivas de la memoria de DIR_CARGA EL PROCESO DE CARGA RELOCALIZABLE En la relocalización dinámica se establece la correspondencia entre las direcciones usadas en el programa a y direcciones físicas cada vez que se utilizan durante la ejecución del programa. Las direcciones 1ógicas generadas por el ensamblador y el enlazador no se alteran durante la carga. Comenzaremos por ver un sencillo método en el cual el programa se carga en posiciones contiguas de la memoria; es decir, el programa no esta disperso por la memoria. En la figura 1.2 se presenta 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. AI leer este código, observe que la función de carga devuelve un entero sin signo en lugar de un apuntador. Esto refleja el hecho de que la dirección inicial es una dirección 1ógica y no una dirección física. Pseudo código para un cargador sencillo (relocalización dinámica)4.2 Cargadores
Cargador:
/***definir la estructura del registro de encabezado ***/
struct enc_ejec{
unsigned int dir_ini;
/* las otras partes del encabezado del archivo ejecutable */
};
/***prototipos para las funciones usadas por el cargador***/
struct enc_ejec leer_enc( FILE *);
char leer_byte ( FILE *);
/***--------el cargador ---------***/
char *carga (File *arch_ejec);
{
struct enc enc_ejec encabezado ;
char *dire_byte;
/* leer encabezado del archivo */*
encabezado = leer enc(arch_ejec);
/*copiar a la memoria los segmentos de texto y datos */
dir_byte = DIR_CARGA;
while(leof(arch_ejec)){
dir_byte=leer (arch_ejec);
dir_byte= dir_byte+1 ;
}
return (char*) encabezado dir_ini);
}
Struct enc_ejc{
Unsigned int dir_ini;
Unsigned int tamaño_texto, tamaño_datos, tamaño_bss;
/*otros campos del registro de encabezado*/
};
/***prototipo para las funciones usadas por el cargador***/
struct enc_leer_enc(FILE*);
char leer_byte(FILE*);
char*obtener_memoria(unsigned int);
void establecer_correspondencia(char*unsigned int);
/***el cargador***/
unsigned int*carga (FILE*arch_ejec)
{
struct enc_ejec encabezado;
char*dir-byte, *dir_carga;
unsigned int tamaño_prog;
encabezado=leer_rnc(arch_ejec);
/*determinar el tamaño del programa y asignar el espacio*/
tamaño_prog=encabezado.tamaño_texto + encabezado. Tamaño_datos+ encabezado.tamaño_bss;
dir_carga=obtener_memoria (tamaño_prg);
/*copiar los segmentos de texto y datos*/
dir_byte =dir_carga;
while(!eof(arch_ejec){
*dir_byte=leer_byte(arch_ejec);
dir_byte=dir_byte+1;
}
/*establecer la correspondencia de direcciones*/
establecer_correspondencia(dir_carga,tamaño_prog);
return ((char*)encabezado.dir_ini);
}