lunes, 16 de abril de 2007

Cómo crear un Sistema Operativo (1)

E. E. del Valle

El texto que leerán a continuación está basado en mis lecturas de libros del ’80, en noches enteras de desvelo, en ensayos prácticos de lo que aquí se habla, en mi propia experiencia como terequero del ordenador.

Estos modestos conocimientos pueden, por su puesto, ser ampliados y así le parece, le agradecería que me ayudara a entender más sobre esta maraña de la que aquí hablo.

Empecemos por la estructura de la memoria.

La memoria se estructura por segmentos, es decir páginas de 64Kb. Las cuales son direccionadas con 4 dígitos de hexadecimales (ver Anexo I). Estas páginas se seleccionan a su vez con otros cuatro dígitos… de la siguiente forma:

0000h:000Ah

Esta dirección hace referencia en el Segmento 0000h (el primero de memoria) al byte 000Ah, el décimo byte del segmento. El procesador lo que hace es seleccionar un segmento y trabajar dentro de él. La memoria de la máquina por defecto (sin que le instalemos las tarjetas) tiene 640Kb de RAM y en un lugar (donde decida el creador del equipo, que puede ser antes o después de esta RAM) Es colocado un programa ROM, que está en un chip de la Motherboard, junto a otros pequeños fragmentos de código ejecutable.

Ahhh! Una nota, los primeros bytes de memoria son 255 interrupciones, a estás nos dirigimos cuando queremos obtener o enviar alguna información al mundo exterior. Desde la interrupción 00h hasta la 20h son interrupciones de la BIOS, contiene saltos a esos fragmentos de código ejecutable que se contienen en el chip ROM, este conjunto de programitas se llama BIOS(Basic Input Output System, Sistema Básico de Entrada y Salida). Estos programitas lo colocó ahí el creador de la computadora, con el fin de que nuestros programas se las entendieran con el Hardware: básico, como el monitor, el teclado, discos. Sus funciones son muy primitivas y sencillas como: poner un carácter en pantalla, leer un sector del disco, o esperar una tecla del teclado… no mucho más.

Qué es un Sistema Operativo?

Este concepto es muy particular mío, no aparece en ningún libro…

Un SO es un programa que ayuda a otros a funcionar de forma adecuada y rápida, gestionándoles los recursos necesarios para que estos funciones de forma apropiada. Nadie usa realmente un SO. Sólo los programas lo usan.

Para crear un SO (Sistema Operativo) lo primero que haremos será estudiar cómo funciona un sencillo SO como DOS.

Cómo es cargado MS-DOS?

Cuando la computadora es reiniciada o encendida la ejecución de instrucciones en memoria comienza en una posición de memoria donde se encuentra el programa de arranque ROM o en una posición donde hay un salto a él. Esto es válido para las arquitecturas x86 y no tiene nada que ver con el DOS.

El programa de arranque, después de asegurarse de que el hardware es el correcto y contabilizar toda la RAM instalada y todas esas basuras que vemos en pantalla cuando se inicia la máquina, carga del primer sector del disco (sector de arranque) que es un programa y le transfiere el control.

Este programa lo que hace es ver si en el disco hay alguna copia del DOS. Esto lo hace leyendo el directorio raíz y viendo si en él se encuentra el ficheros IO.SYS, si no es encontrado este fichero el programa muestra el mensaje: Disco incorrecto, presione una tecla para intentarlo de nuevo. Muchos de nosotros conocemos ese mensaje y quien nos lo envía no es la BIOS, como muchos piensan, sino el programa de arranque del disco que tenemos puesto en ese instante.

Cuando el fichero del DOS es encontrado, este es cargado en memoria y se le transfiere el control. Este programa está dividido en dos partes importantes la primera es la BIOS del DOS, esta BIOS es muy diferente a la del fabricante del equipo; esta, se basa en la del fabricante, e instala sus interrupciones a partir de la interrupción 20h, que es donde comienzan las interrupciones de los programas residentes.

Esta BIOS tiene funciones muy complejas como crear un archivo en el disco tal, en tal directorio(o carpeta para los Windowseros), saber la fecha y hora en que se modificó cierto archivo, mandar cadenas completas de caracteres a pantalla… etc….

La otra parte del fichero IO.SYS es el SYSINIT, el es un programa que cuenta cuanta memoria hay en el sistema y reposiciona el IO.SYS en una dirección alta de la RAM, entonces mueve el núcleo (kernel) del DOS (fichero MSDOS.SYS) a su ubicación final en la RAM, sobre más allá del SYSINIT.

Finalmente el SYSINIT transfiere el control al núcleo, este inicializa las tablas que necesita para su trabajo interno y establece sus áreas de trabajo, y activa las interrupciones desde la 20h hasta la 2Fh para el uso de los demás programas. También examina la tabla del disco, para conocer cuantos bytes hay por sector de asignación. Establece un sector para el buffer del disco (un buffer es un área de memoria que es usada de forma intermedia para transmitir datos, así se asegura un flujo estable de estos). Y carga el programa que procesa los comandos del DOS (el shell, cómo se le llama en Inglés). Este es contenido en el archivo (COMMAND.COM). Este es el procesador de comandos por defectos. Pero tú pedes crear uno propio, creando un programa en consola, poniéndolo en el disco desde el que vas a usar el DOS y agregando, por ejemplo si tu shell se llama JUANITO.EXE, en el archivo CONFIG.SYS “shell=JUANITO.EXE”.

Dónde meter las manos para hacer que la máquina levante con un programa propio?

Bien… luego de lo antes dicho, la respuesta a la pregunta que se plantea es muy sencilla.

Como el programa de arranque grabado en todas las unidades formateadas por MS-DOS, lo primero que llama es el IO.SYS, lo que tenemos que hacer es a nuestro programa ponerle ese nombre, y ponerlo en el directorio raíz, sustituyendo al original IO.SYS (del que le recomiendo hagan una salva). Aclaro: nuestro programa tiene que ser para consola, nunca uno visual…

Pero, por qué cuando iniciamos la computadora no se muestra nada y se queda colgada…? Porque el problema es que los lenguajes que compilan para consola lo hacen utilizando las facilidades que les da el DOS con la interrupción 21h y los demás servicios que presta.

Por ello nuestro programa tiene que estar basado en las interrupciones que nos brinda la ROM-BIOS. Pero como no conozco ningún lenguaje de alto nivel que pueda resolver el problema la única vía es programar en ensamblador. Hacer nuestro programa en ensamblador, usando las pobres funciones de la BIOS.

Este programa nuestro puede instalar sus propias interrupciones, para ofrecer servicios como lo hace el DOS, u otro SO.

Es aquí donde entra Cylix, un compilador que estoy desarrollando desde hace unas semanas en Delphi, con el objetivo de programar en un leguaje de alto nivel, pero con la ventaja de un código puro, sin utilizar el DOS.

Cylix, será un lenguaje muy parecido a C, pero con algunas deficiencias con respecto a este. Cuando lo termine, en su versión 1.0, lo distribuiré de forma libre para que todos ustedes puedan usarlo y mejorarlo si lo desean.

Cualquier duda sobre lo que aquí expongo pueden consultarla conmigo, a través del amigo Alien…

Por un nuevo mundo donde la libertad sea real…!

Anexo I - Sistemas Numéricos

Comencemos por los sistemas de numeración que más utilizaremos al programar. El básico va a ser el sistema hexadecimal, aunque debemos de explicar antes el binario, el sistema de numeración que utiliza el ordenador.

Los números que conocemos están escritos en base 10. Esto significa que tenemos, desde el 0 hasta el 9, diez símbolos para representar cada cifra. Es decir, cada cifra ir  de 0 a 9, y al superar el valor "9", cambiar  a 0 y sumar  uno a su cifra de la izquierda:  9+1: 10.

El sistema binario utiliza tan sólo dos símbolos, el "0" y el "1". Imaginemos que tenemos el número binario "0". Al sumarle una unidad, este número binario cambiar  a "1". Sin embargo, si volvemos a añadirle otra unidad, a este número en formato binario ser  el "10" ( aumenta la

cifra a la izquierda, que era 0, y la anterior toma el valor mínimo ).

Sumemos ahora otra unidad: el aspecto del número ser  "11" ( tres en  decimal ). Y podríamos seguir:

Binario  : 0 ; 1 ; 10 ; 11 ; 100 ; 101 ; 110; 111 ; 1000 ; 1001 ; 1010,...

Decimal : 0  1    2     3      4       5       6      7         8        9        10

Esto nos permite establecer un sistema bastante sencillo de conversión del binario al decimal;

He aquí los valores siendo n el valor de la cifra:

    Cifra menos significativa:

           n*2^0 =    1 si n=1 o 0 si n=0

    Segunda cifra:

           n*2^1 =    2 si n=1 o 0 si n=0

    Tercera cifra:

           n*2^2 =    4 si n=1 o 0 si n=0

    Cuarta cifra:

           n*2^3 =    8 si n=1 o 0 si n=0

    Etc,...

Y así continuaríamos, aumentando el número al que se eleva 2. Traduzcamos entonces el número binario '10110111'

2^7+ 0 +2^5+2^4+ 0 +2^2+2^1+2^0  = 128 + 0 + 32 + 16 + 4 + 2 + 1 = 183

1   0   1   1   0   1   1   1

De todos modos, esta transformación la he puesto símplemente para que se comprenda con mas claridad cómo funcionan los números binarios. Es mucho más aconsejable el uso de una calculadora científica que permita realizar conversiones entre decimales, hexadecimales y binarios. Se hace su uso ya casi imprescindible al programar.

La razón del uso de los números binarios es sencilla. Es lo que entiende el ordenador, ya que interpreta diferencias de voltaje como activado ( 1 ) o desactivado ( 0 ), aunque no detallaré esto. Cada byte de información está compuesto por ocho dígitos binarios, y a cada cifra se le llama bit. El número utilizado en el ejemplo, el 10110111, sería un byte, y cada una de sus ocho cifras, un bit.

Y a partir de ahora, cuando escriba un número binario, lo haré con la notación usual, con una "b" al final del número ( ej: 10010101b )

Ahora me paso al hexadecimal, muy utilizado en ensamblador. Se trata de un sistema de numeración en base dieciseis. Por tanto, hay dieciseis símbolos para cada cifra, y en vez de inventarse para ello nuevos símbolos, se decidió adoptar las primeras letras del abecedario. Por lo tanto, tendremos ahora:

  Hex   Dec

1 -->  1

2 -->  2

3 -->  3

4 -->  4

5 -->  5

6 -->  6

7 -->  7

8 -->  8

9 -->  9

A --> 10

B --> 11

C --> 12

D --> 13

E --> 14

F --> 15

10 --> 16

11 --> 17

 Etc,...

Como vemos, este sistema nos planteas bastantes problemas para la conversión. Repito lo dicho, una calculadora científica nos será casi imprescindible para esto.

Por que utilizar este sistema ? Bien sencillo. Volvamos al byte, y traduzcamos su valor más alto, "11111111". Resulta ser 256. Ahora pasemos esta cifra al sistema hexadecimal, y nos resultará "FF". Obtenemos un número más comprensible que el binario ( difícil de recordar ), y ante todo

mucho más compacto, en el que dos cifras nos representaran cada byte. Podremos además traducir fácilmente el binario a hexadecimal con esta tabla; cada cuatro cifras binarias pueden traducirse al hexadecimal:

Binario

Hexadecimal

0000

0

0001

1

0010

2

0011

3

0100

4

0101

5

0110

6

0111

7

1000

8

1001

9

1010

A

1011

B

1100

C

1101

D

1110

E

1111

F

Por ejemplo, el número binario:

            1111001110101110

En hexadecimal sería:

            1111 0011 1010 1110

              F    3    A    E

Para referirnos a un número hexadecimal sin especificarlo, usaremos la notación que se suele usar al programar, con un

0 al principio (necesario cuando hay letras) y una h al final, por ejemplo, el número anterior sería 0F3AEh



Artículos relacionados


No hay comentarios: