@nanochess@nanochess Main page Intel 8080 emulator Chess programs Contests Store Retrogaming FAQ Links About me Ver en español

我的青少年时代:Transputer 操作系统之旅

使用我的 C 编译器在 transputer 中进行光线追踪的机器人

我之前的文章中,我谈到了如何为 transputer 创建一个自包含的操作系统。这包括基本操作系统、文本编辑器、Small-C 编译器和一个汇编器。

那是 1995 年,我 16 岁,收音机里播放着 Lemon Tree 和 Zombie,ARPANET 在 1990 年左右关闭,开始被称为 Internet,在墨西哥,只有少数人通过 Compuserve Mexico 使用它。 我没有那么幸运能使用这项服务。

我不断改进我的操作系统,修改它并改进它,重新编译并重新启动。 我对编译任何我能找到的 C 语言源代码非常感兴趣,并且我得到了几个 CD-ROM 光盘,但是我无法编译大多数东西,因为我有一个 Small-C 编译器,而不是一个完整的 C 编译器。

这促使我扩展我的 C 语言编译器以支持更多的 C 功能。 因为年轻人很勇敢,所以我像 Small C 一样,继续将输入中的文本片段进行比较。 我在一个只有 128 KB 内存的平台上工作,我能够完成这项壮举,因为 transputer 指令集生成了非常小的可执行文件。 当然,一个合适的词法分析器会使编译速度更快。

随着我在 C 语言特性实现上的进展,遵循 K&R 书籍的附录 A,我发现开发这些特性中的大多数非常直接,比如 structunionTypedef 是最难理解的。 指针算术语法优先级非常困难,特别是对于获取函数指针数组。 我仍然为我如何为 C 类型制作字节码描述而感到自豪,唯一困难的事情是正确地进行递归调用来处理优先级。 此外,让初始化程序工作也很难,因为它们在真正的编译器中具有非常宽松的语法。

C 编译器比 Pascal 编译器花费了我更多的时间,从我的修订笔记中,我花了几乎一整年的时间才得到一个几乎完整的 K&R C 编译器(K&R 指 Kernighan & Ritchie,或者他们在原始书中描述的编译器)。 我的信息已经过时了,因为我拥有 1978 年的书,但是这本书在 1988 年进行了更新,并且 ANSI C 在 1989 年获得批准。

我根据我找到的用于测试的每个新源代码来调整预处理器。 当我的编译器最终设法运行 Vern Paxson 在 USENET 上运行的一个晦涩的竞赛中的一个国际混淆 C 代码竞赛(IOCCC)的国际象棋程序时,我感到非常高兴。 我在 Peter Van Der Linden (1994) 的《Expert C Programming》一书中找到了这个程序。

一旦 C 编译器支持浮点数,我就能够将我在 Pascal 中制作的光线追踪器移植回来,并且我按照 Alan Watt (1993) 的《3D Computer Graphics》一书中的课程和练习开发了一个 3D 多边形模型程序。

添加到主机 Z280 计算机的最后添加是一个 SCSI 卡,并且所有外围设备基本上都是从技术垃圾中回收的,例如,一个 SCSI 硬盘驱动器(在常见的驱动器是 500 MB 时,功能强大的 40 MB),一个 SCSI DAT 磁带驱动器和一个 SCSI CD-ROM 读取器(至少这是新的!)。

CD 光盘 The Cranberries: Everybody Else Is Doing It, So Why Can't We?

我向我的 transputer 操作系统添加了一种读取 High-Sierra 和 ISO-9660 格式结构以访问 CD-ROM 数据的方法,以及一个从这些光盘中解压缩文件的程序。 我非常自豪我设法编译了用于 ZIP 文件的 Inflate 公共领域版本的源代码。 另一件事是这些 CD-ROM 驱动器可以自动播放音频 CD,您只需放入一张 CD(我的那张是 Everybody Else Is Doing It, So Why Can't We?),就可以在工作时听音乐。

磁带驱动器是 DAT 格式,我使用我的 TAR 程序进行了一些备份。 我已经完全忘记这些磁带存储在哪里了,现在这是最安全的备份存储! 没人能找到的那个。

我在 1996 年夏天左右达到了 transputer 开发的最高点,但是处理器开始显示出它的老旧。 128K RAM 的内存勉强够用。 随着我的程序因更多功能而膨胀,transputer 看起来越来越慢。 不幸的是,从未制造过另一块板。 我会对处理多处理非常感兴趣。

恢复操作系统

恢复我的操作系统的工作并不像我想象的那么容易。 我必须扩展 buildboot.c 程序以创建最新文件系统格式的软盘映像,以及硬盘映像。 后来,当我把镜像文件放在一起时,我需要支持增长的磁盘目录。

主要的区别在于目录条目扩展到 64 字节。 这是发现我可以随意指定我的操作系统的副产品,所以对我来说的第一件事就是“从当时 MS-DOS 中常见的 8.3 文件名格式中大逃亡”(Windows 95 几个月前才发布)。 这不是一步完成的,我对文件系统的第一次扩展是使用 32 字节目录条目的十五个字母名称(1996 年 1 月 1 日),下一次扩展是使用 64 字节条目的三十一个字母名称(1996 年 2 月 6 日)。

我的文件系统的 64 字节条目 我的文件系统的 64 字节条目。 请注意 C 子目录的标志。

一旦磁盘映像生成器准备就绪,我就将 SOM.32.bin 文件以及 Interfaz.p 放入软盘映像中,并在 transputer 模拟器中添加所需的服务后尝试启动它(包括三个驱动器单元:软盘、RAM 磁盘和硬盘驱动器)。 在读取引导扇区后,它卡住了,原因是扇区编号的字节顺序是大端。 在模拟器中进行更改后,它能够读取内存中的整个文件并且卡住了。

显然,计时器不起作用,因为屏幕没有更新,因此我为低优先级线程添加了计时器处理,并且屏幕变得可见。 仍然,它卡住了。 我对主机接口代码(一个信号量)进行了简要修改,但它仍然无法运行。 唯一的理由是 MAESTRO.CMG 文件使用不同的协议与操作系统交互。 我在我的文件中搜索直到我找到正确的文件和源代码,我使用这个文件来启动操作系统,它在第一次尝试时就起作用了,并且它前进到抱怨缺少 C:/Interfaz.p

我忘记了我的操作系统是如何启动的!

非常破旧的 1993 年软盘,其中包含 transputer 的 MAESTRO 汇编代码 非常破旧的 1993 年 3.5 英寸软盘,其中包含 transputer 的 MAESTRO 汇编代码。 请注意它是双密度的 (720 kb)。

最低要求的文件

事实证明,软盘用于启动操作系统(文件 SOM.32.bin),反过来它会通过 C 驱动器访问硬盘驱动器以加载命令行处理器。

一旦加载了此文件,我需要一些其他文件才能在操作系统内部编译程序:editor.pcc.pens.pejecutable.p

我首先测试我的文本编辑器,并且非常高兴地看到它如何对预处理器指令和 C 语言元素进行着色。 所有源代码都用西班牙语注释编写,并且将其翻译成英语的代码太多了。

视觉文本编辑器显示具有语法着色的 C 源代码。 视觉文本编辑器显示具有语法着色的 C 源代码。

我从未实现当前目录功能,因此您需要键入每个文件的完整路径。 我的操作系统的一个功能是假设 A: 驱动器,因此您需要编写 c:cc 以从硬盘驱动器执行 C 编译器。 这也是为什么所有路径都具有像 C(用于我的源代码)和 lib(用于库)这样的短名称的原因。 当然,您需要键入每个 DIR 命令的路径。

但是,当我尝试运行 C 编译器时,我感到困惑。 在键入 cc 之后,什么也没有出现,它一直说“Archivo inexistente”(文件不存在)我很确定上次它起作用(几乎 30 年前)

我尝试了 MEM 命令,它说 99240 字节可用。 并且使用 C 编译器可执行文件运行 Info.p 实用程序给了我答案:程序大小 = 38112 字节,堆栈大小 = 8192 字节,全局数据 = 56816 字节,在添加所有这些之后,它需要 103120 字节。 我很困惑! 我确定我在没有任何额外内存的情况下编译了一些程序。

我花了一个小时才想起 transputer 处理器有 4 千字节的内部存储器,并且如果您以经典的镜像方式映射 128K RAM,则处理器在使用最低存储区域 $80000000 - $80000fff 时永远不会使用总线,但是它会使用总线在外部 RAM 的较低 4K 中镜像的任何地址之外的任何地址,例如 $80020000 - $80020fff。 因此,获得额外 4K 的一个简单的增强是将工作空间扩展为从 $80021000 开始(它向较低的地址移动)。

我修改了启动代码,C 编译器启动并运行了!

如何组装您自己的文件

鉴于 transputer 中不同大小的指令,编写链接器太困难了。 因此,我求助于一种混合方法,我的汇编器允许处理串联的 transputer 汇编器文件,进而生成一个初步的可执行文件。 此文件应由 ejecutable.p 处理,这样用户就可以输入堆栈大小,并且该程序会添加一个头信息,以指示它将使用多少堆栈空间。

可执行文件头

偏移量| 字段 +0| OTBE (0x4542544f) Oscar Toledo Binario Ejecutable +4| 0x08031996 (1996 年 3 月 8 日) +8| 代码大小 +12| 额外数据大小 +16| 堆栈大小 +20| 数据大小 +24| 未使用 ...| ... +60| 未使用

我从未在我的操作系统中实现适当的命令行处理,因此每个程序都必须以一个条目序列开始,以提供选项和文件名。 反过来,这使得实现批处理命令文件变得更加困难,因为所有程序都需要用户输入。

我开始编译我拥有的源树中的每个程序,并且当我执行光线追踪程序和 3D 建模器程序时,我在输出中无法获得任何图像。

我也忘记了如何链接我自己的程序! 事实证明,我制作了一个文档,其中描述了如何重建每个程序,该文档很好地位于 Documentos/Programas.doc 中,并且 Mat.len 库旨在放置在汇编程序程序的开头,以便它可以正确加载其常量。 如果没有启动代码,每个数学函数都返回零。

顺便说一句,我重新发现了为什么我在 B 驱动器中制作了一个小的 512 KB RAM 磁盘。 首先,它是主机 Z280 系统中可用的内存,其次,它帮助我更快地组装程序,因为它不必访问 SCSI 硬盘驱动器。

因此,我只需要将 C 语言程序(从硬盘驱动器读取)编译到 RAM 磁盘,并在 RAM 磁盘上进行汇编。 最后,可以将完成的可执行文件写回硬盘驱动器。 这比我以前在软盘上做的任何汇编都要快得多,而且我的程序已经增长到非常需要的程度。

浮点错误

现在我在 3D 建模器中获得了一个图像,但是它有明显的数学错误计算。 我可以逐个修订例程,并尝试了解出了什么问题,或者我可以检查一小部分浮点指令并检查是否正确模拟。 我很幸运能够立即发现 fpldnldbi 仅以一种奇怪的方式从处理器堆栈中删除项目,并且 fpldnlsni 有一个双重索引(可能我从 fpldnldbi 复制并粘贴了代码)。 自 1996 年以来,犹他茶壶首次以其所有 3D 荣耀显示出来。 美好的回忆!

在 transputer 模拟中具有渲染错误的犹他茶壶 在 transputer 模拟中具有渲染错误的犹他茶壶。

以 3D 渲染的犹他茶壶 在更正后以 3D 渲染的犹他茶壶。

我从《3D Computer Graphics》一书的附录 D 中获得了犹他茶壶顶点数据,其中包括 3D 计算机图形课程,读者(学生)的项目是基于本书提出的计算编写一个 3D 建模器。 它从本书中学到了很多东西,我能够在几周内编写建模器。

有趣的是,我认为光线追踪器可以工作,但是它在处理圆柱体时有一个非常特殊的失败,在图像上创建了随机的黑色像素。 在此过程中,我更正了多云的天空函数,它传递了 col[2] 而不是 col2,导致崩溃,因为它写在随机内存地址上。

我提醒说这是一个已知的错误,当时我永远无法使圆柱体代码工作。 出于某种原因,我找不到该错误。 现在有了完整的模拟,我能够将该错误精确定位到二次交点函数:


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

它以单精度执行浮点加载和乘法,然后立即将该值保存为双精度。 因此,该错误不在移植的代码中,而是在我的 C 编译器中。

恰好我的 C 编译器尝试在使用 32 位浮点数时优化代码,如果所有值均为 32 位,但是如果操作太复杂,它会将当前值保存在工作空间中作为临时值。 只是有一个小问题:它总是将临时值保存为 64 位浮点值。

更改“相对”容易。 我的编译器 ccexpr.c 文件中的原始代码如下所示:


   if(haz_compatible(&izq, info, &der, info2)) {
    crea_nodo(N_MULPF, izq, der, 0);
   } else {

函数 haz_compatible() 使表达式树的左节点和右节点的类型兼容,并为浮点运算返回一个非零值。 transputer 假设我们将正确的值传递给指令,因此我们可以将 fpmul 指令用于 float 和 double。

但是,我们需要添加有关两者都是 float 类型的异常的信息,以用于保存临时值(如果表达式树太复杂):


   if(haz_compatible(&izq, info, &der, info2)) {
    crea_nodo(N_MULPF, izq, der, *((char *) info[0]) == FLOAT);
   } else {

这样,esp[] 数组(由 crea_nodo 写入)将包含一个值,如果操作数是浮点数而不是双精度数。 随着代码从不支持 struct 的 C 编译器发展而来,指针作为整数保存在数组中(是的,非常不可移植!)

现在我们应该修改用于在 ccgencod.c 中保存临时值的代码。 这是函数 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);
   }
/*
** 将寄存器 A 保存在堆栈中。
*/
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;
 }
}
/*
** 从堆栈中检索寄存器 A。
*/
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() 保存临时值,并使用 recupera() 恢复它。 我们添加了有关浮点值的信息:


     } 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);
   }

/*
** 将寄存器 A 保存在堆栈中。
*/
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;
 }
}
/*
** 从堆栈中检索寄存器 A。
*/
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;
 }
}

只剩下再次编译 C 编译器和光线追踪程序。 更正后,它可以正确地渲染测试圆柱体,最后,我能够正确地看到我在 1996 年制作的光线追踪机器人。 我花了 29 年的时间才更正错误! 现在看起来很简单,但是当时我找不到它。

在 transputer 模拟中由于 transputer 的 C 编译器的错误而具有渲染错误的光线追踪机器人 在 transputer 模拟中由于 transputer 的 C 编译器的错误而具有渲染错误的光线追踪机器人。

在 C 编译器更正后在 transputer 中光线追踪机器人 在 C 编译器更正后在 transputer 中光线追踪机器人。

安装它(就像新的一样!)

确保您的终端设置为 80x25 个字符,并使用 ISO Latin 1 (ISO-8859-1) 作为字符集。 我有没有告诉过你我发现我可以创新? 我使用了 $80-$9f 字符(ISO-8859-1 未使用)来放置像 PC 中一样的框图形,因为我可以在 VGA 显卡中定义任何我想要的东西,但是目前这些将在终端中显示为空白。 也许我可以制作一个转换为 UTF-8 的转换器。

os_final_ 目录已添加到 git,并且 tree_ 目录中包含我的操作系统的备份。 已经有一个预构建的软盘映像和硬盘,因此您只需要使用正确的参数运行模拟器即可。 但是,为了完整起见,以下是重建驱动器映像文件的步骤序列。

以下命令行在 build_f1.shbuild_f2.shbuild_hd.sh shell 文件中提供。

使用 os_final_ 目录中的命令行,使用 buildboot_ 实用程序创建 40 mb 的硬盘驱动器映像文件,它仅包含文件 Interfaz.p(命令行处理器):


  ../transputer/os/buildboot -hd -v2 harddisk.img . tree/Interfaz.p

现在使用所需的基本文件创建第一个软盘映像:


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

现在应该使用我的 transputer 模拟器运行操作系统(可以添加带有 ISO 映像的进一步参数以在驱动器 D 中获取 CD-ROM):


  ../transputer/tem -os2 maestro.cmg floppy.img harddisk.img

现在可以使用此命令行将文件复制到硬盘驱动器(CD 创建一个目录,COPIA 复制文件):


  CD C:/C
  CD C:/Lib
  COPIA *.P C:
  COPIA *.C C:/C
  COPIA *.LEN C:/C
  DIR C:
  HALT

现在创建第二个软盘映像:


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

现在可以使用此命令行将文件复制到硬盘驱动器(CD 创建一个目录,COPIA 复制文件):


  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

您现在可以重置软盘映像(只需确保它包含 SOM.32.bin 文件),或使用 BORRA 命令(删除)手动删除文件。 整个操作系统(包括源代码)占用不到 3 兆字节。

使用操作系统

您可以通过键入 AYUDA 来查看可用命令的列表(如果您阅读过我之前的文章,这比我早期操作系统的几个命令要复杂得多)。

要按顺序运行几个 commmad,您可以使用分号,例如:


  C:EDITOR ; C:CC ; C:ENS

或者您可以输入此命令来查看多任务处理的小例子,以在屏幕的右上角获取一个时钟:


  @C:/DESARROLLO/RELOJ

要退出操作系统,请使用 C:HALT_,因为这将正确关闭驱动器映像文件。

编译程序

要编译程序,只需键入 C:CC_ 并按 Enter 键。 对于前两个问题,键入 N,然后键入源代码文件的路径,例如 c:/C/Hora.c,然后键入目标汇编器文件,例如 b:hora.len。 您应该汇编程序,键入 C:ENS_ 并按 Enter 键。 键入 b:hora.len 并按 Enter 键,键入 c:/lib/stdio.len 并按 Enter 键,现在单独按 Enter 键,然后键入 b:hora.e 作为输出文件。 现在我们需要将其转换为可执行文件,键入 C:EJECUTABLE_ 并按 Enter 键,键入 b:hora.e 并按 Enter 键,键入 8192_ 并按 Enter 键(堆栈大小),键入 0_(零)并按 Enter 键(额外数据大小),然后键入 C:hora.p 作为输出文件。 要运行该程序,请键入 C:Hora_ 并按 Enter 键。

文档

我开始掌握文档将如何完全电子化,因此我编写了一些关于操作系统、文件系统、程序和一些其他说明的不完整描述。 所有这些文件都可以在 Documentos_ 目录中找到。 这是一个非常不同的时代。

如果您阅读了我之前的文章,则可以使用 macOS 中的 Fn+F1 访问可视编辑器的帮助窗口。 您可以使用 Fn+F4 读取文本文件,并使用箭头键导航文件。

其他程序

此操作系统中的其他程序包括:

如您所见,我非常忙于编写所有这些! 有三个光线追踪机器人行走的动画(我将这些与 Pascal 版本的 Ray Tracer 一起使用),但是,我没有测试这些,并且创建 FLI 动画的 process 实用程序是用 Z280 机器代码编写的。

后来发生了什么?

我喜欢这个操作系统如何展示解决问题的原始思维,例如仅使用 128 kb 的 RAM、拥有 31 个字母的文件名、使用完整路径名来引用文件、改编字符集的自由空间以用于图形字符、管理 RAM 磁盘以加速开发,当然还可以开发一个 K&R C 编译器。

我可以做更多的事情,但是,主机计算机显示出其在图形方面的速度慢,并且我达到了 RAM 内存的限制。 这阻止了我将 C 编译器扩展到 ANSI C,我可以从外部来源编译很少的程序,链接器从未完成,因此我无法在模块中编译程序(反过来,C 编译器没有实现