Le Grand Pressigny, FRANCIA - Tony Tebby
(Artículo original: revista “International QL Report” V5i5, Enero de 1996)
Traducción: Juan José Ruiz Leo - Febrero de 2008
SMSQ/E se distribuye como un solo fichero que provee un sistema operativo, un procesador de comandos de línea / intérprete de programas (SBASIC), varios módulos de idioma y un conjunto completo de controladores de dispositivos para el sistema objetivo. SMSQ/E no es, sin embargo, una unidad monolítica, sino una colección de módulos que proveen diferentes funciones. Es posible, por ejemplo, quitar el intérprete de SBASIC y substituirlo por una concha UNIX, o quitar módulos de idioma no queridos o substituirlos por otros idiomas.
En las versiones actuales, SMSQ no está muy finamente dividido: para evitar la duplicación de rutinas de utilidad, los controladores de dispositivos están enlazados juntos en grandes módulos y el sistema operativo en si mismo está dispuesto como un solo módulo. La versión de QXL tiene 14 módulos, la de Gold Card tiene 20 módulos y la de Atari 17 módulos.
No todos los módulos están cargados. Para la versión de Atari, por ejemplo, hay dos módulos de sistema operativo diferentes para permitir dos esquemas de manejo de memoria diferentes. Sólo se carga uno de estos, el otro es desechado durante la carga.
La estructura de módulo estándar comprende una cabecera estandarizada, código de preproceso del módulo y el código del módulo en sí.
La cabecera de módulo estándar comienza con un bloque de tamaño fijo obligatorio con información de cabecera: 24 octetos.
Palabra larga |
mbase |
El desplazamiento desde el comienzo de la cabecera a la base del módulo = la longitud de la cabecera |
Palabra larga |
mlength |
La longitud del módulo en sí (sin incluir la cabecera) |
Palabra larga |
rlength |
La longitud máxima después de recolocación (puede que el módulo encoja) |
Palabra larga |
cksum |
La suma de comprobación del módulo |
Palabra larga |
select |
El desplazamiento desde el comienzo de la cabecera al “código de seleccionar” que será llamado antes de que se cargue el módulo |
Octeto |
level |
El nivel de módulo (para carga automática) |
Octeto |
spare |
|
Palabra |
name |
Apuntador relativo al nombre del módulo |
Todas las longitudes y apuntadores relativos deben ser pares.
El “nivel” está reservado para uso futuro. Debería ser siempre 1. El nombre debería definirse siempre. Es una cadena QDOS (longitud en una palabra seguida por los caracteres, que deberían estar ajustados a un número par). Como el nombre normalmente seguirá a la cabecera directamente, el apuntador relativo normalmente será 2. Como convenio el nombre debería estar seguido por una identificación de versión de 4 caracteres (a menudo ésta es simplemente cuatro espacios). La suma de comprobación se calcula normalmente de la siguiente forma.
Inicializar la palabra larga de suma a cero.
Por cada palabra en el módulo
Sumar la palabra a la palabra larga de suma
Rotar la palabra larga de suma a la derecha por (palabra MOD 7)
moveq #0,d0 moveq #0,d1 loop move.w (a1)+,d0 siguiente palabra larga add.l d0,d1 acumulada and.w #7,d0 MOD 7 ror.l d0,d1 rotar subq.l #2,d3 decrementar el octeto de cuenta por 2 bgt.s loop
Una suma de comprobación de cero es siempre aceptable y es más fácil de calcular.
Como un módulo tiene una suma de comprobación, no es posible incorporar datos configurables. Para esquivar este problema, cualquier bloque de configuración debería ponerse en la cabecera y una rutina de “seleccionar” incorporada para copiar la información al módulo. (Esto también asegura que el módulo no está abarrotado de texto de configuración.)
Aunque la rutina de seleccionar se puede usar para efectuar mucho más que una simple selección, el propósito principal de la rutina de selección es determinar si un módulo en particular debería ser cargado.
El primer módulo “activo” de cada versión del sistema operativo es el cargador. Éste es el módulo que explora el resto de los módulos cargando el código en los lugares “correctos”, etc. Por cada módulo, llama a la rutina de “seleccionar” (si el desplazamiento no es cero) en modo supervisor. La rutina de seleccionar debe devolver un código en D0:
D0 0 no cargar este módulo
D0 1 cargar este módulo
Así, por ejemplo, el controlador de visualización monocroma del Atari comprueba si hay una pantalla monocroma conectada y, si la hay, devuelve 1 (cargar) para asegurar que se carga el controlador de pantalla monocroma. En cambio, los controladores de pantalla del emulador QL del Atari devuelven 0 (no cargar) si hay una pantalla monocroma adjunta y por lo tanto, a no ser que tenga una versión de SMSQ/E que incluya un controlador monocromo, no obtendrá ningún controlador de consola en absoluto.
Las rutinas de seleccionar pueden, naturalmente, hacer más que eso. Los módulos de manejo de caché, por ejemplo, no tienen un módulo real: el código de manejo de caché para los diversos procesadores MC680x0 está construido en la cabecera y el código requerido para el procesador en particular es copiado en el área de vectores de SMSQ. Las rutinas de seleccionar del manejo de caché, por tanto, siempre devuelven 0 (no cargar).
El cargador pasa la dirección de un “bloque de comunicación de rutina de seleccionar” a cada rutina de seleccionar. Este bloque es inicializado con una cierta cantidad de datos útiles por el cargador, pero las rutinas de seleccionar pueden usarlo para pasar información de una a otra. Este bloque de comunicación está apuntado por A5.
Palabra larga |
family |
ID de familia de máquina (ATST, QXL, GOLD) |
Palabra larga |
mtype |
Tipo de máquina (depende de la familia pero el MSB siempre es el tipo de procesador: $00=68000, $40=68040) |
Palabra |
lang |
Identificador de idioma (ó 0) |
Palabra |
spare |
|
Palabra larga |
facility |
32 bits, cada uno de los cuales puede ser activado para indicar que una utilidad particular ya ha sido cargada (para prevenir, por ejemplo, que se carguen dos controladores CON contradictorios). SMSQ actualmente sólo usa los bits 30 y 31. Otros suministradores de software deberían usar del bit 0 hacia arriba. |
Las rutinas de seleccionar pueden usar hasta $30 octetos tras este bloque definido. Note, sin embargo, que estos $30 octetos no son inicializados. Las rutinas de seleccionar no pueden usar ningún servicio del sistema operativo (son llamadas antes de que el sistema operativo sea inicializado).
Cuando todos los módulos han sido cargados, SMSQ llama al propio código de cada módulo, en modo usuario, para inicializar los módulos (enlazar controladores, añadir procedimientos SBASIC y Things). El código del módulo debería terminar con RTS. Tiene la misma forma que un fichero que se pretenda cargar con LRESPR. Note, sin embargo, que cuando los módulos con inicializados, el canal 0 no está abierto.
Habría sido muy conveniente tener una estructura de módulo que fuera la misma para todos los módulos, pero, como SMSQ/E tiene que empezar como un programa que se ejecuta bajo un sistema operativo diferente, el fichero entero del sistema operativo SMSQ/E tiene que parecer un programa válido en ese sistema. Por esta razón , hay un módulo especial: el MÓDULO ANFITRIÓN.
El módulo anfitrión no incluye ningún código que sea cargado. Es el programa que será ejecutado por el sistema operativo ANFITRIÓN. Para la Gold Card simplemente entra en modo supervisor y espera 2,5 segundos antes de saltar al módulo cargador de la Gold Card.
Está claro que es imposible tener una cabecera en un módulo anfitrión. El módulo anfitrión, por tanto, ¡tiene un remolque! A fin de ser capaz de encontrar el remolque, siempre se pone al final del fichero – todos los otros módulos se insertan entre el módulo anfitrión y el remolque. Este remolque es de $18 octetos y tiene la misma forma que una cabecera de módulo estándar. Hay, sin embargo, algunas ligeras diferencias en el contenido.
Palabra larga |
mbase |
0 |
Palabra larga |
mlength |
La longitud del módulo en sí (sin incluir el remolque) |
Palabra larga |
rlength |
0 |
Palabra larga |
cksum |
La suma de comprobación del módulo |
Palabra larga |
flength |
El desplazamiento desde el comienzo del módulo a la “tabla de arreglo de longitud de fichero” |
Palabra larga |
oslen |
Longitud del fichero de sistema operativo ó 0 |
La tabla de arreglo de longitud de fichero es requerida para decirle al sistema operativo anfitrión cuánto mide el fichero poniendo la longitud (más o menos un bit) en el programa anfitrión (¡¡SÍ, ALGUNOS SISTEMAS OPERATIVOS NO SABEN CUÁNTO MIDE UN PROGRAMA!!). Si este apuntador no es cero apunta a una tabla de asientos de dos palabras largas de la forma:
Apuntador relativo a la palabra larga a ser sobreescrita
Ajuste a añadir a la longitud antes de sobreescribir
La tabla está terminada por una palabra larga con valor cero.
La vida es incluso peor para la QXL. El fichero entero está precedido por un programa MS-DOS. A fin de encontrar el “verdadero” comienzo del fichero del sistema operativo, la longitud del fichero del sistema operativo está almacenada en la última palabra larga. Es más, si se cambia la longitud del fichero SMSQE.EXE no sólo es necesario actualizar esta longitud, sino que se requiere un parche complejo para el programa MS-DOS (el cálculo parece ilógico, pero me han asegurado que es correcto). Esto se puede hacer después de que todas las operaciones se hayan completado.
OPEN #5,"SMSQE.EXE" lenf = FLEN(#5) lens% = INT((lenf + 511) / 512) lenb% = lenf – lens% * 512 IF lenb% = lenb% = lenb% + 512 BPUT #5\2,lenb% MOD 256,lenb% DIV 256,lens% MOD 256,lens% DIV 256 CLOSE #5
Un fichero SMSQ puede ser explorado bastante fácilmente con un simple programa SBASIC:
100 REMark – scan bootloader file 110 DIM version$(4): version$(0)=4 120 OPEN #0,CON: CLS: BORDER 1,4 130 height = 17 140 INPUT 'SMSQ file>';f$ 150 OPEN_IN #3,f$ 160 fln = FLEN(#3) 170 LGET #3\fln–$18+$4,mod_ptr : REMark – get length of host module 180 LGET #3\fln–$18+$14,bln : REMark – length of bootloader file 190 IF bln: mod_ptr = mod_ptr + fln – bln 200 FOR i=1 TO 9999 210 LGET #3\(mod_ptr),mbase,mlength 220 IF NOT mbase: EXIT : REMark – end of file 230 IF NOT i MOD height: INPUT a$; : REMark – pause at screen full 240 WGET #3\(mod_ptr+$16),name_rel : REMark – relative pointer to name 250 GET #3\(mod_ptr+$16+name_rel),name$ : REMark – fetch module name 260 IF LEN(name$) && 1: BGET #3,a : REMark – odd length name is padded 270 BGET #3,version$(1 TO 4) : REMark – get version, if any 280 PRINT HEX$(mlength,24) !! version$ ! name$ 290 mod_ptr = mod_ptr + mbase + mlength 300 END FOR i 310 CLOSE #3 320 INPUT a$
Esto imprimirá la longitud (en hexadecimal), la versión y el nombre de todo excepto el módulo anfitrión.
Si tiene un módulo (por ejemplo una tabla de teclado como las descritas en la edición de Mayo/Junio) que quiera incorporar, normalmente lo más fácil es añadirla al final. Para hacer esto necesitará quitar el remolque y añadir el nuevo módulo y añadir el remolque de nuevo. Puede que entonces necesite actualizar la longitud en el módulo anfitrión, o como se ha descrito arriba para la QXL o “apropiadamente”.
100 REMark – add module to bootloader file 110 OPEN #0,CON: CLS: BORDER 1,4 120 height = 17 130 INPUT 'SMSQ file>';f$ 140 OPEN #3,f$ 150 fln = FLEN(#3) 160 INPUT 'New module file>';m$ 170 OPEN_IN #4,m$ 180 mln = FLEN(#4) 190 DIM mod$(mln) 200 BGET #4,mod$(1 TO mln):mod$(0) = mln 210 INPUT 'Module name>';mn$ 220 mnlen = LEN(mn$) 230 mnlen2 = mnlen + (mnlen && 1) : REMark – round up module name len 240 mhead = $18 + 2 + mnlen2 + 4 : REMark – total module header length 250 : 260 LGET #3\fln–$18+$4,mod_ptr : REMark – get length of host module 270 LGET #3\fln–$18+$10,fix_up,bln : REMark – length of bootloader file 280 IF bln: bln = bln + mhead + mln 290 LPUT #3\fln–$18,mhead,mln,mln,0,0,$01000002 : REMark – $18 byte header 300 PUT #3,mn$: IF mnlen && 1: BPUT #3,0 : REMark – name and pad 310 BPUT 'VERS' : REMark – 4 character version 320 BPUT #3,mod$ : REMark – add module 330 LPUT #3,0,mod_ptr,fix_up,0,0,bln : REMark – replace trailer 340 fln = fln + mhead + mln 350 : 360 IF fix_up 370 REPeat 380 LGET #3\(fix_up),addr,offset : REMark – next fixup address/offset 390 IF addr=0: EXIT 400 LPUT #4\(addr+fix_up),fln+offset 410 fix_up = fix_up + 8 420 END REPeat 430 END IF
Alojado en / Hosted at: Sinclair QL Recursos en Castellano Sinclair QL Spanish Resources |