Mis años adolescentes: El sistema operativo para transputer
En
mi artículo previo platiqué acerca de como me las arreglé para crear un sistema operativo autocontenido para transputer. Esto incluía un sistema operativo básico, un editor de texto, un compilador de Small-C y un ensamblador.
El año era 1995, tenía 16 años, Lemon Tree y Zombie se tocaban en el radio, ARPANET cerró en 1990 y empezó a ser conocida como Internet, y en México solo un manojo de personas usaba este servicio a través de Compuserve México. No tuve tanta suerte como para usarlo.
Estaba evolucionando mi sistema operativo, modificándolo y mejorándolo, recompilando y arrancándolo de nuevo. Estaba muy interesado en compilar cualquier código fuente en C que pudiera tener en mis manos, y tuve varios discos CD-ROM, pero no podía compilar casi nada porque tenía un compilador de Small-C, no un compilador de C completo.
Esto me motivó a extender mi compilador de lenguaje C para admitir más características del C. Como la juventud es audaz, seguí haciendo comparaciones de piezas de texto de la entrada justo como Small C. Estaba trabajando en una plataforma con solo 128 kb. de RAM, y pude lograr este desafio porque el conjunto de instrucciones del transputer generaba ejecutables muy pequeños. Pero por supuesto, un analizador léxico propio hubiera permitido compilaciones más rápidas.
Así como progresaba en mi implementación de las características del lenguaje C, siguiendo el libro de K&R apéndice A, descubrí que desarrollar la mayor parte de estas era muy directo, como struct y union. Typedef fue la más complicada de entender. La precedencia de la sintaxis de aritmética de punteros fue muy difícil, en particular obtener un arreglo de apuntadores a función. Todavía estoy orgulloso de como hice descripciones en código de byte de los tipos de C, y la única cosa difícil fue lograr correctamente las llamadas recursivas para manejar la precedencia. También lograr que los inicializadores trabajaran fue difícil ya que la sintaxis en los compiladores reales era muy laxa.
El compilador de C me tomó bastante más tiempo que el compilador de Pascal, y de mis notas de revisión veo que usé casi un año completo para lograr un casi completo compilador de C K&R (K&R significa Kernighan & Ritchie, o un compilador como se describe en su libro original). Mi información también estaba desfasada, porque tenía el libro de 1978, pero fue actualizado en 1988, y el estándar ANSI C aprobado en 1989.
Ajusté el preprocesador con cada nuevo código fuente que encontraba para probar. Estuve muy feliz cuando mi compilador finalmente pudo correr un programa de ajedrez por Vern Paxson de un oscuro concurso de USENET, el
IOCCC (International Obfuscated C Code Contest). Encontré este programa en el libro
Expert C Programming por Peter Van Der Linden (1994).
Una vez que el compilador de C manejaba punto flotante, pude portar el Ray Tracer que hice en
Pascal, y desarrollé un programa de modelado poligonal 3D siguiendo el curso y ejercicios del libro
3D Computer Graphics por Alan Watt (1993).
Las últimas adiciones a la computadora Z280 anfitrión fueron una tarjeta SCSI, y todos los periféricos eran básicamente reciclados de la basura tecnológica, por ejemplo, un disco duro SCSI (poderosos 40 megabytes en una época donde ya eran común los 500 mb), una unidad SCSI de cinta DAT, y un lector de CD-ROM SCSI Toshiba XM-4101B (este si era nuevo).
Agregué a mi sistema operativo transputer una forma de leer estructuras de formato High-Sierra y ISO-9660 para acceder datos de CD-ROM, y un programa para descompactar archivos de estos discos. Estuve muy orgulloso de como logré compilar el código fuente de la versión de dominio público de Inflate para archivos ZIP. Otra cosa es que estas unidades de CD-ROM podían ejecutar CD de audio automáticamente, solo se ponía el CD (el mío era Everybody Else Is Doing It, So Why Can't We?) y oír música mientras se trabajaba.
La unidad de cinta era formato DAT, y realicé algunos respaldos usando mi programa TAR. Olvidé completamente donde guardé estas cintas ¡ese si que es un lugar seguro! El que nadie puede encontrar.
Alcancé la madurez de mi desarrollo con transputer cerca del verano de 1996, y el procesador empezó a mostrar su edad. 128 kb de memoria RAM era apenas suficiente para trabajar. Así como mis programas crecieron con más características, el transputer empezó a lucir más y más lento. Y desafortunadamente, nunca se hizo otro tablero. Hubiera sido muy interesante manejar multiprocesamiento.
Restaurando el sistema operativo
El trabajo para restaurar mi sistema operativo no fue tan fácil como pensé. Tuve que expandir el programa buildboot.c para crear imágenes de floppy disk en el moderno formato de sistema de archivo, y también imágenes de disco duro. Según montaba el archivo de imagen, también requerí soporte para que crecieran los directorios.
La diferencia principal es la expansión de las entradas de directorio a 64 bytes. Esto fue un efecto colateral de descubrir que era libre de especificar mi sistema operativo como yo quisiera, así que el primer resultado fue "el gran escape" del formato de nombres 8.3 común en MS-DOS en la época (Windows 95 apenas había aparecido unos meses antes). No se hizo en un solo paso, mi primera expansión del sistema de archivo fue nombres de 15 letras usando entradas de directorio de 32 bytes (01-ene-1996), y la siguiente expansión fue nombres de 31 letras usando entradas de directorio de 64 bytes (06-feb-1996).
Las entradas de 64 bytes en el sistema de archivos. Notése las banderas para el subdirectorio C.
Una vez que el constructor de imágenes de disco estaba listo, puse el archivo SOM.32.bin junto con Interfaz.p en la imagen de floppy, e intenté arrancarlo después de agregar los servicios requeridos en el emulador de transputer (incluyendo tres unidades: disco flexible, disco RAM, y disco duro). Se atoró después de leer el sector de arranque, y la causa fue el orden de bytes de los números de sectores big-endian. Después de hacer el cambio en el emulador, fue capaz de leer el archivo completo en la memoria y se atoró.
En apariencia los temporizadores no funcionaban ya que la pantalla no se actualizaba, así que agregué manejo de temporizadores de baja prioridad, y la pantalla se hizo visible. Aún así, se trabó. Hice una pequeña modificación al código de interface con el anfitrión (un semáforo), pero todavía no funcionaba. La razón para esto era que el archivo MAESTRO.CMG usaba un protocolo diferente para interfazar con el sistema operativo. Busqué en mis archivos hasta que encontré el correcto y su código fuente, y usé este archivo para arrancar el sistema operativo y funcionó en el primer intento, lo suficiente para quejarse de que faltaba C:/Interfaz.p
¡Había olvidado como arrancaba mi sistema operativo!
Disco floppy muy gastado de 1993 con el código ensamblador de MAESTRO para transputer.
Notése que es doble densidad (720 kb).
Los archivos mínimos requeridos
Resulta que el disco flexible era usado para arrancar el sistema operativo (el archivo SOM.32.bin), y a su vez accedía el disco duro en la unidad C: para cargar el procesador de línea de comandos.
Una vez que el archivo estaba cargado, necesitaba unos pocos archivos más para compilar programas dentro del sistema operativo: editor.p, cc.p, ens.p, y ejecutable.p.
Comencé a probar mi editor de texto, y quedé muy complacido mirando como colorea las directivas del preprocesador y los elementos del lenguaje C. Todo el código fuente está escrito con comentarios en español, y la verdad es mucho código como para traducirlo al inglés.
El editor de texto visual ilustrando código C con coloreo de sintaxis.
Nunca implementé una característica de directorio actual, así que se necesita teclear el camino completo a cada archivo. Una característica de mi sistema operativo es que la unidad A: se asume, así que se requiere escribir c:cc para ejecutar el compilador de C desde el disco duro. Por esto todos los directorios tienen nombres cortos como C (para mi código fuente) y lib (para las librerías). Y por supuesto, se necesita escribir el camino para cada orden DIR.
Sin embargo, me confundí cuando intenté ejecutar el compilador de C. Después de teclear cc, nada aparecía, seguía diciendo "Archivo inexistente" y yo estaba muy seguro de que funcionaba la última vez (hace casi 30 años)
Intenté la orden MEM y decía 99240 bytes libres. Y ejecutando la utilidad Info.p con el ejecutable del compilador de C me dio la respuesta: tamaño del programa = 38112 bytes, tamaño de pila = 8192 bytes, datos globales = 56816 bytes, y después de agregar esto requería 103120 bytes. Me dejó con el ojo cuadrado, estaba seguro que compilaba programas sin ninguna memoria extra.
Me tomó una hora completa recordar que el procesador transputer tiene 4 kilobytes de memoria interna, y si se mapea una memoria de 128 kb es un estilo clásico de espejo, el procesador nunca usa la memoria baja $80000000 - $80000fff, pero usa el bus para cualquier dirección fuera del rango como $80020000 - $80020fff, y esto cae en los 4K bajos de la RAM externa. Así que una mejora sencilla para obtener 4K extras era expandir el workspace para comenzar en $80021000 (se mueve hacia direcciones más bajas).
Modifiqué el código de arranque ¡y el compilador de C funcionó!
Como ensamblar tus propios archivos
Dadas las instrucciones de diferente tamaño del transputer, era muy díficil escribir un enlazador. Así que opté por una opción mezclada, mi ensamblador permitía concatenar archivos de ensamblador de transputer, y generaba un ejecutable preliminar. Este archivo debe ser procesado por ejecutable.p para que el usuario entre el tamaño de pila, y el programa añade un encabezado de información para indicar cuanta pila se usa.
Encabezado ejecutable |
Offset | Contenido |
+0 | OTBE (0x4542544f) Oscar Toledo Binario Ejecutable |
+4 | 0x08031996 (Mar/08/1996) |
+8 | Tamaño de código |
+12 | Tamaño de datos extras |
+16 | Tamaño de pila |
+20 | Tamaño de datos |
+24 | Sin usar |
... | ... |
+60 | Sin usar |
Nunca implementé procesamiento de línea de comandos en mi sistema operativo, así que cada programa tenía que comenzar con una secuencia de entrada para proveer las opciones y nombres de archivo. Esto además hizo más difícil implementar procesamiento de comandos por lote, porque todos los programas requerían entrada del usuario.
Comencé a compilar cada programa en el árbol de fuentes que tenía, y cuando ejecuté el programa de ray tracing y el modelador 3D, no pude obtener ninguna imagen en la salida.
¡También había olvidado como enlazar mis programas! Resulta que hice un documento con una descripción de como reconstruir cada programa, disponible agradablemente como Documentos/Programas.doc y la librería Mat.len se suponía que debía ponerse al principio del ensamblaje, para que pudiera cargar correctamente sus constantes. Sin el código de arranque cada función matemática regresa cero.
Por cierto, redescubrí porqué hice un disco RAM de 512 KB en la unidad B. Primero, era la memoria disponible en el sistema anfitrión Z280, segundo, me ayudó a ensamblar más rápido los programas ya que no tenía que acceder el disco duro SCSI.
Así que solo tenía que compilar el programa de lenguaje C (leído del disco duro) al disco RAM, y ensamblar en el disco RAM. Al final el ejecutable completo podía ser escrito al disco duro. Esto era bastante más rápido que ningún otro ensamblaje que hubiera hecho en el disco flexible, y muy requerido ya que mis programas habían crecido.
Errores de punto flotante
Ahora tenía una imagen en el modelador 3D pero tenía obvios cálculos matemáticos incorrectos. Podía revisar rutina por rutina para intentar obtener una idea de que estaba mal, o podía irme sobre el pequeño montón de instrucciones de punto flotante y revisar su correcta emulación. Tuve suerte de encontrar casi inmediatamente que fpldnldbi removía datos de una forma extraña de la pila del procesador, y que fpldnlsni tenía un indice doble (probablemente al cortar y pegar código de fpldnldbi). Y entonces la tetera de la universidad de Utah se ilustró en toda su gloria 3D por la primera vez desde 1996. ¡Buenos recuerdos!
Tetera de la universidad de Utah con bugs de rendeo en la emulación de transputer.
Tetera de la universidad de Utah rendeada en 3D después de las correcciones.
Obtuve los datos de vertices para la tetera de la universidad de Utah del apéndice D del libro "3D Computer Graphics" que incluía un curso de gráficos de computadora 3D, y el proyecto para el lector (o estudiante) era escribir un modelador 3D basado en los cálculos presentados por el libro. Aprendí mucho con este libro, y pude codificar el modelador en unas pocas semanas.
Interesante, yo pensé que el ray tracer funcionaba, pero tenía una falla muy particular al manejar cilindros, creando pixeles negros aleatorios en la imagen. En el camino corregí la función para nubes en el cielo, ya que pasaba col[2] en lugar de col2 causando un crash ya que escribía en locaciones aleatorias de la memoria.
Recordé que este era un bug conocido, nunca pude hacer que el código del cilindro funcionara en ese tiempo. Por alguna razon no pude encontrar el error. Ahora con una emulación completa, pude delimitar el error a la función de intersección quadrática:
Iptr=8000a0d3 A=8000a0ae B=8000a098 C=8000a098 Wptr=8000f4e8
FA=00000000 FB=4132972c687bac40 FC=4132972c687bac40 ldlp 3
Iptr=8000a0d5 A=8000f4f4 B=8000a0ae C=8000a098 Wptr=8000f4e8
FA=00000000 FB=4132972c687bac40 FC=4132972c687bac40 fpldnlmulsn
Iptr=8000a0d7 A=8000a0ae B=8000a098 C=8000a098 Wptr=8000f4e8
FA=80000000 FB=4132972c687bac40 FC=4132972c687bac40 ajw -2
Iptr=8000a0d8 A=8000a0ae B=8000a098 C=8000a098 Wptr=8000f4e0
FA=80000000 FB=4132972c687bac40 FC=4132972c687bac40 ldlp 0
Iptr=8000a0da A=8000f4e0 B=8000a0ae C=8000a098 Wptr=8000f4e0
FA=80000000 FB=4132972c687bac40 FC=4132972c687bac40 fpstnldb
Realiza una carga de punto flotante y multiplicación de precisión simple, pero entonces salvar el valor como precisión doble. Así que el bug no estaba en mi código portado, sino en mi compilador de C.
Resulta que mi compilador de C intenta optimizar el código usando punto flotante de 32 bits si todos los valores son de 32 bits, pero si la operación es muy compleja, salva el valor actual en el workspace como temporal. Solo hay un pequeño problema: siempre guarda el temporal como un valor de punto flotante de 64 bits.
El cambio fue "relativamente" fácil. El código original del archivo de mi compilador ccexpr.c se lee como:
if(haz_compatible(&izq, info, &der, info2)) {
crea_nodo(N_MULPF, izq, der, 0);
} else {
La función haz_compatible() hace compatibles los tipos para los nodos izquierdo y derecho del árbol de expresiones, y devuelve un valor no cero para operaciones de punto flotante. El transputer asume que pasamos los valores correctos a la instrucción, y se usa la misma instrucción fpmul para float y double.
Sin embargo, necesitamos agregar información para la excepción de ambos siendo tipo float, para los propósitos de salvar el valor temporal si la expresión es demasiado compleja:
if(haz_compatible(&izq, info, &der, info2)) {
crea_nodo(N_MULPF, izq, der, *((char *) info[0]) == FLOAT);
} else {
De esta forma el arreglo esp[] (escrito por crea_nodo) contiene uno si los operandos son float en lugar de double. Como el código evolucionó de un compilador de C que no admitía struct, los apuntadores se salvan como enteros en arreglos (¡sí! totalmente no portable)
Ahora debemos modificar el código que salva los valores temporales en ccgencod.c. Este es el código original en la función gen_nodo():
} else {
gen_nodo(nodo_der[nodo]);
salva(1);
gen_nodo(nodo_izq[nodo]);
if(op == N_SUMAPF) {
recupera(2);
return;
} else if(op == N_MULPF) {
recupera(3);
return;
}
recupera(1);
}
/*
** Salva el registro A en la pila.
*/
salva(flotante)
int flotante;
{
if(flotante) {
emite_texto("ajw -2\r\nldlp 0\r\nfpstnldb\r\n");
pila -= 2;
} else {
emite_texto("ajw -1\r\nstl 0\r\n");
--pila;
}
}
/*
** Recupera el registro A desde la pila.
*/
recupera(flotante)
int flotante;
{
if(flotante) {
emite_linea("ldlp 0");
if(flotante == 1)
emite_linea("fpldnldb");
else if(flotante == 2)
emite_linea("fpldnladddb");
else if(flotante == 3)
emite_linea("fpldnlmuldb");
emite_linea("ajw 2");
pila += 2;
} else {
emite_texto("ldl 0\r\najw 1\r\n");
++pila;
}
}
Salva el valor temporal usando la función salva() y lo restaura usando recupera(). Agregamos la información para valores float:
} else {
gen_nodo(nodo_der[nodo]);
salva(esp[nodo] ? 2 : 1);
gen_nodo(nodo_izq[nodo]);
if(op == N_SUMAPF) {
recupera(esp[nodo] ? 5 : 2);
return;
} else if(op == N_MULPF) {
recupera(esp[nodo] ? 6 : 3);
return;
}
recupera(esp[nodo] ? 4 : 1);
}
/*
** Salva el registro A en la pila.
*/
salva(flotante)
int flotante;
{
if(flotante == 1) {
emite_texto("ajw -2\r\nldlp 0\r\nfpstnldb\r\n");
pila -= 2;
} else if(flotante == 2) {
emite_texto("ajw -1\r\nldlp 0\r\nfpstnlsn\r\n");
--pila;
} else {
emite_texto("ajw -1\r\nstl 0\r\n");
--pila;
}
}
/*
** Recupera el registro A desde la pila.
*/
recupera(flotante)
int flotante;
{
if(flotante) {
emite_linea("ldlp 0");
if(flotante == 1)
emite_linea("fpldnldb");
else if(flotante == 2)
emite_linea("fpldnladddb");
else if(flotante == 3)
emite_linea("fpldnlmuldb");
else if(flotante == 4)
emite_linea("fpldnlsn");
else if(flotante == 5)
emite_linea("fpldnladdsn");
else if(flotante == 6)
emite_linea("fpldnlmulsn");
if(flotante < 4) {
emite_linea("ajw 2");
pila += 2;
} else {
emite_linea("ajw 1");
++pila;
}
} else {
emite_texto("ldl 0\r\najw 1\r\n");
++pila;
}
}
Solo quedaba compilar de nuevo el compilador de C y el programa ray tracer. Después de la corrección pudo rendear correctamente el cilindro de prueba, y finalmente pude ver correctamente el robot que hice en 1996. ¡Sólo me tomó 29 años corregir el bug! Ahora parece simple, pero en ese tiempo no lo pude encontrar.
Robot rendeado con ray tracing con bugs en compilador de C para transputer.
Robot rendeado con ray tracing en transputer después de correcciones en el compilador de C.
Instalándolo (¡como nuevo!)
Hay que asegurarse de que la Terminal esta configurada como 80x25 caracteres, usando ISO Latin 1 (ISO-8859-1) como conjunto de caracteres. ¿Dije que me gustaba innovar? Usé los caracteres $80-$9f (no usados por ISO-8859-1) para poner gráficos de caja como en la PC ya que podía definir lo que yo quisiera en la tarjeta VGA, pero estos apareceran en blanco en la terminal. Tal vez pueda convertirlos a UTF-8.
El directorio os_final fue agregado al git, y dentro el directorio tree contiene el respaldo de mi sistema operativo. Ya hay una imagen preconstruida del disco flexible y el disco duro, así que solo se necesita correr el emulador con los argumentos correctos. Sin embargo, con afán de estar completos, aquí está la secuencia de pasos para reconstruir las imágenes de disco.
Las siguientes líneas de comando están provistas en los archivos de shell build_f1.sh, build_f2.sh, y build_hd.sh.
Con la línea de comandos en el directorio os_final, la imagen del disco duro de 40 mb es creada usando la utilidad buildboot, que incluye un solo archivo Interfaz.p (el procesador de línea de comandos):
../transputer/os/buildboot -hd -v2 harddisk.img . tree/Interfaz.p
Ahora la primera imagen de disco flexible es creada con los archivos básicos requeridos:
../transputer/os/buildboot -fd -v2 floppy.img . tree/SOM.32.bin tree/Interfaz.p tree/Editor.p tree/CC.p tree/Ens.p tree/Ejecutable.p tree/Info.p tree/Halt.p tree/C/CC.c tree/C/CCanasin.c tree/C/CCexpr.c tree/C/CCgencod.c tree/C/CCinter.c tree/C/CCvarios.c tree/C/CCvars.c tree/C/Checar.c tree/C/Compara.c tree/C/Concat.c tree/C/Conjunto.c tree/C/Copiador.c tree/C/CPC.c tree/C/DARC.c tree/C/Divide.c tree/C/DZIP.c tree/C/Editor.c tree/C/Efem.c tree/C/Ejecutable.c tree/C/Ens.c tree/C/Explode.c tree/C/Filtro.c tree/C/GZIP.C tree/C/Hora.c tree/C/Inflate.c tree/C/Info.c tree/C/Interfaz.c tree/C/Libro.c tree/C/Monitor.c tree/C/Prepara.c tree/C/Semana_santa.c tree/C/Som32.c tree/C/TAR.c tree/C/Unreduce.c tree/C/Unshrink.c tree/C/Vaciado.c tree/C/Halt.c tree/lib/E.len tree/lib/Graf.len tree/lib/MAT.len tree/lib/Mensajes.len tree/lib/Stdio.len
Ahora el sistema operativo debe ejecutarse usando mi emulador de transputer (un argumento extra con una imagen ISO puede ser agregado para obtener un CD-ROM en la unidad D):
../transputer/tem -os2 maestro.cmg floppy.img harddisk.img
Ahora los archivos pueden ser copiados en el disco duro usando estas líneas de comando (CD crea un directorio y COPIA copia archivos):
CD C:/C
CD C:/Lib
COPIA *.P C:
COPIA *.C C:/C
COPIA *.LEN C:/C
DIR C:
HALT
La segunda imagen de disco flexible se crea ahora:
../transputer/os/buildboot -fd -v2 floppy.img . tree/SOM.32.bin tree/Halt.p tree/Desarrollo/Ajedrez.c tree/Desarrollo/Reloj.c tree/Desarrollo/Tetris.c tree/C/Modelado.c tree/C/M3D.c tree/Dibujo_3D/* tree/Documentos/Archivo.doc tree/Documentos/Detalles.doc tree/Documentos/Ens.doc tree/Documentos/Peticiones.doc tree/Documentos/Programas.doc tree/Documentos/Servicios.doc tree/Documentos/Trabajo.doc tree/Documentos/Transputer.doc
Ahora los archivos pueden ser copiados en el disco duro usando esta línea de comandos (CD crea un directorio y COPIA copia archivos):
CD C:/Desarrollo
COPIA Ajedrez.c C:/Desarrollo
COPIA Reloj.c C:/Desarrollo
COPIA Tetris.c C:/Desarrollo
COPIA Modelado.c C:/C
COPIA M3D.c C:/C
CD C:/Documentos
COPIA *.doc c:/Documentos
HALT
Ya puedes resetear la imagen de disco flexible (solo asegurarse de que contenga el archivo SOM.32.bin), o borrar manualmente los archivos usando la orden BORRA. El sistema operativo completo (incluyendo código fuente) cabe en menos de 3 megabytes.
Usando el sistema operativo
Puede verse una lista de las órdenes disponibles tecleando AYUDA (si leíste mi artículo previo, esto es más complejo que las pocas órdenes de mi sistema operativo primitivo).
- AYUDA, muestra una lista de las órdenes disponibles.
- DIR [camino] -A -P, ilustra el directorio del camino, la opción -A muestra los nombres en dos columnas, y la opción -P muestra el directorio en páginas.
- COPIA [expresión] [camino], copia archivos de la fuente al camino.
- REN camino nombre, renombra un archivo con el nombre.
- ILUSTRA camino, ilustra el contenido de un archivo.
- BORRA expresión, borra un archivo. Puede usar asteriscos.
- VER, muestra la versión del procesador de comandos.
- MEM, muestra los bytes de memoria disponibles.
- LINEA texto, ilustra el texto en la pantalla (útil para comandos por lote)
- BLP, borra la pantalla.
- FIN, sale del procesador de línea de comandos.
- BD camino, borra un directorio.
- CD camino, crea un directorio.
Para correr varias órdenes en secuencia se usa punto y coma, por ejemplo:
C:EDITOR ; C:CC ; C:ENS
O se puede ver un pequeño ejemplo de multitarea tecleando esta orden para obtener un reloj en la parte superior derecha de la pantalla:
@C:/DESARROLLO/RELOJ
Para salir del sistema operativo utilice C:HALT ya que cerrará correctamente los archivos de imagen de unidades.
Compilando programas
Para compilar programas solo teclea C:CC y oprime Enter. Introduce N para las dos primeras preguntas, y teclea el camino al archivo fuente, por ejemplo c:/C/Hora.c y entonces el archivo ensamblador destino, por ejemplo b:hora.len
Ahora se ensambla el programa, teclea C:ENS y oprime Enter. Introduce b:hora.len y oprime Enter, teclea c:/lib/stdio.len y oprime Enter, ahora oprime Enter una vez más, y teclea b:hora.e como archivo de salido.
Se convierte ahora en un archivo ejecutable, teclea C:EJECUTABLE y oprime Enter, teclea b:hora.e y oprime Enter, teclea 8192 y oprime Enter (tamaño de la pila), teclea 0 (cero) y oprime Enter (tamaño extra de datos), y teclea C:hora.p como archivo de salida.
Para ejecutar el programa teclea C:Hora y oprime Enter.
Documentación
Comenzaba a tener una idea de como la documentación iba a ser completamente electrónica, así que escribí algunas descripciones incompletas del sistema operativo, sistema de archivo, programas y algunas notas extras. Todos estos archivos están disponibles en el directorio Documentos. Era una época muy diferente.
Si leíste mi artículo previo, puedes acceder la ventana de ayuda del editor visual usando Fn+F1 en macOS (o F1 en Windows y Linux). Y puedes leer los archivos de texto usando Fn+F4 (o F4 en Windows y Linux) y navegar los archivos con las teclas de las flechas.
Otros programas
Otros programas en ese sistema operativo son:
- Checar.p, verifica la integridad de la unidad.
- Compara.p, compara dos archivos de texto en busca de diferencias.
- Concat.p, concatena varios archivos.
- Conjunto.p, muestra el conjunto de caracteres.
- Copiador.p, copia un disco flexible (innecesario, se puede copiar archivos de imagen fácilmente)
- CPC.p, sirve para copiar archivos de discos con formato PC.
- DARC.p, descomprime archivos ARC.
- Divide.p, divide un archivo en varias partes.
- DZIP.p, descomprime archivos ZIP.
- Efem.p, un programa para mostrar efemerides.
- Filtro.p, convertidor del conjunto de caracteres PC-8 a ISO-8859-1. Desarrollado el 29-sep-1995, ese día todo mi código fuente se convirtió de PC-8 a ISO-8859-1.
- GZIP.p, descomprime archivos GZIP.
- Hora.p, muestra la hora y fecha actuales.
- Info.p, muestra información acerca del archivo ejecutable.
- Libro.p, formatea un archivo de texto como un libro para doblar en una HP LaserJet IIP
- Monitor.p, monitor de depuración para desarrollo de bajo nivel.
- Prepara.p, formatea un disco (innecesario, buildboot lo hace)
- Semana_santa.p, calcula la semana santa para cualquier año.
- TAR.p, crea/prueba/extrae archivos TAR (usé esto para las cintas DAT)
- Vaciado.p, vacia un archivo como ASCII hexadecimal.
- Modela.p, modelador poligonal 3D, se le pueden alimentar archivos escena* del directorio C:/Dibujo_3D. Por ejemplo, C:/Dibujo_3D/escena_tetera
- M3D.p, ray tracer, port del ray tracer en Pascal. Se le pueden alimentar archivos M3D del directorio c:/Dibujo_3D sin la extensión M3D. Por ejemplo, C:/Dibujo_3D/P
Como puedes ver estuve muy ocupado codificando todo esto.
Hay tres animaciones del robot ray tracing caminando (usé estas con la versión Pascal del ray tracer), sin embargo, no las he probado, y la utilidad para convertir la salida a una animación FLI fue escrita en código máquina Z280.
¿Y después?
Me gusta como este sistema operativo muestra pensamiento creativo para solucionar problemas, como trabajar con solo 128 kb. de RAM, tener nombres de archivo de 31 letras, usar caminos de directorio completos para referirse a archivos, adaptar el espacio libre del conjunto de caracteres para gráficos, manejar un disco RAM para acelerar el desarrollo, y por supuesto lograr realizar un compilador de C K&R en este.
Pude hacer más cosas, sin embargo, la computadora anfitrión ya mostraba su lentitud en particular con gráficos, y alcancé los límites de la memoria RAM. Esto evitó que expandiera el compilador de C a ANSI C, podía compilar muy pocos programas de fuentes externas, el enlazador nunca se terminó así que no podía compilar programas por módulos (y el compilador de C no implementó extern ni static). Me detuve.
Mi experimento con transputer había terminado, aunque aún hice unos pocos programas más pensando en el futuro (como un program para crear sistemas de archivo CD-ROM esperando una grabadora de CD que nunca llegó).
Mi primera visita a un café Internet fue alrededor del verano de 1996, y tristemente descubrí el fracaso de Inmos, fue una gran decepción ya que su T9000 prometido con velocidad diez veces mayor nunca se materializó.
También un nuevo procesador de 32 bits estaba viniendo y mi padre estaba construyendo una nueva computadora donde construí nuevo software, y después haría mi sistema operativo con ventanas, y todas mis herramientas de transputer se portarían a esta máquina más grande.
Un producto colateral de mi compilador de C, fue portarlo de vuelta a la computadora Z280 para compilar una herramienta educativa de desarrollo Z80 integrada (editor/ensamblador/uploader) que ya había hecho con el PCC de Mark DeSmet para MS-DOS. Me alegré mucho cuando compilé el mismo programa en mi computadora Z280 sin cambios. Ese fue el último suspiro de la computadora Z280.
¡Disfrutalo!
¿Te encantó este artículo? Invitame un café en ko-fi
Ligas relacionadas:
Última actualización: 12-mar-2025