可编程计算器的EFORTH

这是161eForth v0.5b系列中的第一篇文章,在此处结束: habr.com/en/post/452572

现在,EFORTH转换器也可以在家用MK-161电子计算器上使用! 5月17日,版本v0.5b成功通过了我的测试,以及五个TEST-TEST4编写测试。 我已经实现了独自完成的工作,但是我认为这只是成功的一半。 现在该是通过开放161eForth代码进行公共测试向社区介绍新工具的时候了。 我列出了需要改进的地方以及在哪里进行“稳定工作”。 在完成工作并发布1.0版时,将考虑您的建议和评论。

在将最新版本的eForth移植到家用平台时,成功克服了两个障碍-以自己的输入语言编程的8位计算机的相对较低的速度,以及适度的可用二进制内存量(请参见2.4.1),仅为4096字节。


在编写161eForth时,使用了为Callisto(家用PMK的下一代输入语言)准备的现成解决方案。 这是一项通过RS-232串行端口运行在十进制ALU和“哈佛”架构,控制台驱动程序和字母数字键盘布局以及基于它们的软件终端之上的堡垒机器的技术。 除了Electronics MK-161和161eForth发行版之外,您可能还需要一个自制的跳线键盘,键盘上会用俄语和英语字母签名。 字母从左到右,从上到下按字母顺序排列。


eForth的现代版本的作者Chen-Hanson Ting博士在他的书中[1]强调了理解堡垒的两个组成部分的重要性。 这是一个内部(“地址”)解释器,使设备可以执行Fort的车缝代码,而这是一个外部(“文本”)解释器,负责与人进行对话。

在两篇文章中,我将详细介绍在Electronics实施这两种解释器时使用的最根本的解决方案。 学习这些解决方案可能会很有用,并且会启发您将eForth迁移到内存和性能有限的其他设备。 了解这些文章将有助于对可编程微计算器(PMC)和Fort进行初步介绍。 我将解释电子MK和eForth转换器特有的困难时刻。

首先,eForth一词分为一般和系统两类。 字母的大小很重要。 普通单词的名称以大写字母定义,而系统则以小写字母定义。 我还以小写形式在eForth中进行了创新。 eForth的作者建议以CAPS模式进行主要对话。 当您需要使用系统单词时,将时间切换为小写字母(FP组合键)。

在这篇文章中,所有单词都用大写字母写出来,以便从文本中脱颖而出。 在几个早期的eForth实施中,系统字头被排除,并且WORDS命令不输出。 这有助于简化eForth的外观并节省初次使用Fort的人们的注意力。 在161eForth中,保存这些单词的标题主要是因为存在SEE冒号单词反编译器(请参见文章末尾的视频3),如果删除了系统单词的标题,则不会显示系统单词的名称。

为了简化本文并使其有用,我在定义它们之前必须使用几个术语。 Fort和PMK专业人员应该熟悉这些术语。 初学者有时必须查看相邻的部分(我将链接放在正确的位置)或重新阅读了几次。

此处列出了161eForth本身以及源文本,图形屏幕键盘和帮助word.txt,其中包含所有已实现词的描述: http ://the-hacker.ru/2019/161eforth0.5b.zip

我还在YouTube上发布了5个小视频,为没有MK-161的用户演示了161eForth的操作。 您可以在YouTube上观看整个播放列表 。 下面是其中的第一个,其余4个在文章结尾。



eForth及其实施


eForth被设计为现代替代著名的fig-Fort转换器。 为了转移到MK-161,我选择了带有间接缝制代码的32位5.2版86eForth转换器,该转换器于2016年在Windows操作系统的MASM汇编器上编写。 第三版eForth和Zen [1]中对该版本进行了详细描述。 那些懂英语的人,我建议您查找和学习本书,这对于理解161eForth非常有用。

在一封私人信件中,作者确认本书的86eForth502.asm是eForth的最新版本。 在Internet上,您可以找到有关此版本和eForth早期版本的许多英语信息。

eForth的发展遵循了Wirth教授使用其编程语言Oberon的示例所教授的科学道路。 eForth的每个后续版本都是先前版本的简化。 一切可以免除的东西都从舌头上去除了。 仍然需要一组经过深思熟虑的强大而富有表现力的语言构造,它们的功能已在各种平台的40多种eForth实现中进行了测试。 现在在计算器上!

作为Fort的极简方言,eForth的目标不是赢得与最小Fort的比赛。 他提供的单词集非常实用,可以很容易地由程序员按照其任务所必需的方向扩展。

eForth的第一版于1990年在适用于8086处理器的MASM汇编程序中发布,并在MS-DOS下工作。 它包含31个与机器相关的核心词和191个高级词。 这个想法很简单-您只需将31个单词翻译成汇编语言,然后立即在计算机上使用eForth。

这种方法在Internet上受到批评,因为最小化汇编程序中字数的方法导致嵌入式系统的性能极低。 在eForth的第二版中,已经开始在汇编程序中实现单词的最大数量,这不仅使易于使用的便携式程序而且更倾向于实用的编程系统。

几年来,eForth的原始作者Bill Munch和他的同事Ting-Hanson Ting博士并行发布了eForth发行版。 每个版本都有自己的特点。 其他程序员也已使用了针对不同平台的eForth选项。

2016年发布的5.2版包含71个单词的“代码”和110个单词的“冒号”。 四分之一世纪的搜索理想导致单词总数大大减少。 同时,出于性能原因,在低级别实施的单词所占的百分比有所增加。

拟议的161eForth享受了这一进展带来的巨大好处,但并未假装进一步发展干线。 我的实现为程序员提供了5.2版中提供的所有工具。 当MK-161体系结构使某些86eForth单词的实现变得不可能或毫无意义时,我不会抛弃多余的东西,而是给程序员提供了完全的替代品,它取自ANSI / ISO标准[4]。 那些寻求极简主义的人可以独立抛出“多余”的单词,因为传统上161eForth附带了源代码。

在实施eForth时,我坚持作者的理解。 例如,在我看来,初始值为n的FOR NEXT循环应准确执行n次。 最终得出相同的结论的是Chuck Moore,他是Forth和colorForth语言的作者。 不幸的是,eForth使用了一个过时的约定,并且执行了n + 1次这样的循环,计数器从n到0。我没有解决这个问题和其他一些缺点,而是希望161eForth与其他平台的实现兼容。

由于161eForth是MK-161电子产品的第一个实用的机载编程系统,除了工厂语言外,我追踪了eForth的悠久历史,并返回了一些单词,以返回在其他平台上有用的语言,现在可能需要。

例如,新旧变量'BOOT包含单词的标记(请参阅3.1),该标记在初始化环境之后但在对话开始之前首先执行。 默认情况下,“ BOOT”包含一个TLOAD令牌,用于解释“文本区域”中的代码(请参见2.4.2)。 这样,程序员就可以为自己定制eForth,而无需重新编译环境,而在“ Electronics”上仍然无法生产该环境。

该实现的优先任务是节省二进制内存(请参见2.4.1)并提高性能。 他们的解决方案大大减少了高级单词的数量,因为由于廉价程序存储器中实现的快速核心单词的数量增加,他们的代码占用了宝贵的内存(请参阅2.4.3)。

结果,161eForth包含129个代码字,78个高级字,并占用MK-161二进制存储器的1816字节,即不到一半。 这为直接在电子设备上对其高级部分进行元编译提供了希望。

eForth MK-161的源代码分为两大部分。 用MK-161命令系统编写的核心包含在eForth0.mkl文件中。 高级单词在SP-Forth中定义,并放置在eForth.f文件中。

该发行版还具有一个帮助文件words.txt,该文件在一行中记录了所有161eForth单词,带有堆栈符号和简要说明。

1.1内核eForth0.mkl的源代码


eForth内核包含在MK-161程序的内存中运行的可执行代码(请参见2.4.3),该代码通过标准方式(例如,专有的MKL2MKP编译器)在计算机上编译为eForth0.mkp文件。

eForth0.mkl文件中包含的内核源代码使用拉丁字母助记符编写。 例如,在此助记符中将读取寄存器E(又名R14)的IPE命令写为RME。 拉丁语助记符对于苏联PMK所有者而言是不寻常的,可方便地从计算机键盘键入内容。 确实,比起童年时的Fx²,输入奇怪的FX ^ 2要容易得多。

eForth0.mkp文件是内核预设。 除了原语代码外,它还包含一个内核头和一个名称为tblNames的表,eForth.f在解码过程中将这些表传输给十进制寄存器(请参阅2.4.4)。 将基于eForth0.mkp创建eForth.mkp内核(请参阅2.4.3),因此必须首先编译eForth0.mkl。

1.2高级单词eForth.f的源代码


eForth.f文件被馈送到出色的家用编译器SP-Forth [5]的输入。 该文件包含所有高级单词的定义。 随着时间的流逝,它们可以在eForth本身上被识别,并可能直接在电子MK-161上编译。

在编译过程中,eForth.f读取核心空白eForth0.mkp,并在其帮助下在当前目录中创建三个文件以供随后加载到MK-161中:eForth.mkp,eForth.mkd和eForth.mkb。 尽管eForth.mkb的标题位于eForth.mkd文件中,但它包含高级单词的主体。

第四个文件eForth.mkt是用eForth手动编写的,可以使用内置的文本编辑器在MK-161上进行编辑。 我将在下面更详细地分析这四个文件中的每个文件(请参见2.4)。

2.电子MK-161


新西伯利亚的一家制造商称MK-161为旧缩写。 那是苏联最早的计算器的名字。 MK-161指令系统继承了苏联计算器“ Electronics B3-34”和“ Electronics MK-61”的命令系统。 这意味着为苏联计算器编写的程序将在MK-161上运行,而无需更改或进行较小的更改。

反之则不正确。 eForth不会去苏联的PMK,因为 使用了许多资源,这些资源最初出现在MK-152 / 161中,而该系列的先前型号中没有。

考虑MK-161的输入语言和体系结构的特征,这些特征影响了161eForth(以下简称为eForth),并为所讨论的eForth实现提供了“俄罗斯口音”。

这些功能的第一个是“高级初中地址”协议,该协议在MK-161中得到一致维护。 例如,数字1000 = 3×256 + 232将被写入两个连续的字节中,例如3和232。

2.1间接寻址


编程苏联PMK听说过间接寻址。 对于直接寻址,我们明确指出要引用的寄存器号。 例如,P IP 44考虑了寄存器44的内容。MK-152中出现的P键用于访问编号为15或更大的寄存器-这些寄存器在苏联PMK中不存在。

间接寻址中,所需寄存器编号事先未知。 该号码在另一个寄存器中。 例如,如果寄存器8包含数字44,则命令K PI 8将考虑寄存器44(R44)的内容。

K和P键可以组合使用。 例如,命令R K BP 20会将控制权(拉丁语记忆中的GOTO)转移到R20中存储的地址。

事实证明对内部eForth解释器很重要的功能与间接寻址期间寄存器的初步增加/减少有关。 此功能是从苏联PMK继承的。

例如,间接读取命令KI 0,KI 1,KI 2和KI 3将寄存器0、1、2或3的内容减1到所需的寄存器,命令KI 4,KI 5和KI 6在读取之前,将寄存器4、5或6的内容加1。

地址寄存器的这种“修改”使您可以循环处理整个寄存器组。 它与C中的++ R和--R相似。 寄存器寄存器号很重要。 由他决定通过间接寻址增加还是减少(寄存器4-6)还是减少(寄存器0-3)。

161eForth体系结构受到以下事实的影响:通过间接寻址增加寄存器4-6是初步的 。 结果,位于R6中的解释指针(IP)始终指向缝纫代码的最后一个字节 。 在86eForth中,IP始终指示尚未读取的后续字节。

对于存储在寄存器2中的返回堆栈指针(RP),也是如此。R2始终指向返回堆栈的顶部。

MK-161的一个有用功能是,如果使用新键R进行间接寻址,则寄存器中不会增加/减少。例如,RKIP02从返回堆栈的顶部开始对数字进行计数,而无需更改指针。 这是一个现成的Fort R @团队。 从上面可以得出,读取的值比下一个标记的地址小一个,该标记将在从单词“冒号”返回后执行。

当您必须开发或研究与eForth内部解释器紧密交互的单词时,请务必完全理解与夸张相关的细微之处。

2.2表格,有序和关联的


MK-161表位于程序存储器中(请参见2.4.3)。 它们出现在新西伯利亚的“ Electronics MK”中,完全不熟悉苏联PMK专家。 所用表的地址始终存储在寄存器9042中,但对它们的访问不同。

有序表是无符号16位整数的数组。 eForth包含一个带有基本地址的tblTokens表(请参阅3.1.1)-用MK-161命令系统编写的Fort单词。 地址解释器(请参阅3.2)使用tblTokens快速执行缝制代码,因此eForth尝试始终在R9042中包含此表的地址。

要访问有序表,您需要在R9210中写入所需项目的编号。 寄存器X中的数字n将由具有数字n的表元素的值替换,计数从零开始。

eForth主要使用基元(FIND)来主动使用关联表 (“按值搜索”),以其名称查找单词。 另外,在屏幕上打印字母以处理换行符和其他控制代码时,将使用tblCHPUT关联表。

要在关联表中搜索元素n,请将n写入R9212。 寄存器X中的数字n(管理层将其称为“索引”)将由表中记录的16值立即替换为“索引” n。

MK-161“固件”中以汇编语言实现的这种快速,简单的搜索功能的存在,帮助eForth在识别单词名称和编译程序时获得了可接受的性能。 当然,为此,我不必开发最简单的名称识别表,而为此功能“锐化了”。 我们将在第二篇文章中更详细地讨论这一点。

2.3中断和控制台


“ MK Electronics”允许其所有者以输入语言编写程序来响应某些事件,例如按下或释放按钮,结束计时器计数。

当提示输入时,eForth会主动使用此中断系统进行键盘输入和闪烁的光标显示,以及通过通用串行端口(RS-232)进行输入/输出。

当您按下按键时,从键盘输入的字母将排在bufKbd队列中。 这非常方便,并节省了低速系统的时间。 字母和大小写切换由KeyPress中断处理,不占用队列空间。 长按按键可调用自动重复。

当8个字母的行已满并且eForth尚未准备好处理输入时(这种情况非常罕见),MK-161将发出不愉快的尖叫声。 当然,我不希望在翻译器中实现键盘的所有自然功能,而是要把MK-161作为内置程序(固件)的服务直接使用。 但是,正如他们所说,那是丰富的。

开始工作后,eForth的整个输出将定向到MK-161的图形屏幕 。 字母的输出是通过CNCut的相对简单的例程执行的。 唯一的困难是BS控制代码的实现,即“退格”。 MK-161使用比例字体。 因此,在特殊的缓冲区tblBS中,您必须记住所显示字符的位置,随后BS输出代码会从这些位置获取它们。

在对话期间,用户可以使用单词IO>将所有I / O重定向到RS-232串行端口,这使得可以从熟悉的计算机键盘或另一个MK-161对MK-161进行编程单词CON>将控制权返回到计算器控制台。

2.4 MK-161的内存区域和安装eForth


“ MK-161电子设备”存储器由可单独寻址的程序存储器和数据寄存器存储器组成。反过来,寄存器存储器是异构的,分为三个大区域。

数字从0到999的寄存器存储“十进制数”。这些是普通的寄存器,例如“ Electronics B3-34”和其他计算器中的寄存器。它们仅能够存储“尾数”的8位,而不是12位小数。

编号从1000到8167的寄存器存储从0到255的整数。地址从5096到8167的该区域的后3 KB称为文本区域

编号从9000到9999的寄存器称为功能寄存器地址空间的此服务区类似于微处理器的I / O端口。在写和读命令的帮助下,这些地址用于访问I / O设备,中断系统等。

要在电子产品MK-161上安装eForth,例如使用制造商MK.EXE的程序将四个文件传输到计算器就足够了:
  • 从第0页开始将eForth.mkp写入程序存储器。0.5b版占用74页。
  • 将eForth.mkd写入十进制数据存储器
  • 将eForth.mkb写入二进制数据存储器
  • 将eForth.mkt写入文本存储器

转移到计算器后,建议立即将这四个文件保存在内置“电子磁盘” 的单独目录中由于它们具有相同的名称,因此您可以一次作为“软件包”立即下载eForth。

2.4.1二进制(“字节”)存储器MK-161:eForth.mkb


电子MK寄存器的编号从1000到5095,用于存储0到255的数字。计算器的寄存器存储器的这一区域称为二进制。可以从eForth作为两个16位的“单元”访问两个连续的二进制寄存器,并且(如MK-161上的任何地方),高8位在寄存器中,而其编号较小。

eForth使用这个很小的“二进制内存”作为主要内存。话语对她有用!和@,HERE和ALLOT,仅地址解释器从此处执行缝制的代码(请参见3.2)。这里是eForth变量,文本输入缓冲区(TIB),字典和tblBS回滚堆栈以实现退格。

按照现代标准,4096个字节非常适中。因此,已经付出了巨大的努力来将所有可能的东西带到其他存储区域。

2.4.2文本区域:eForth.mkt


二进制存储器紧随其后是一个文本区域,其编号从5095到8167的寄存器。从技术上讲,它们是相同的字节寄存器,但是能够将它们写入磁盘并作为单独的文件读取,使得该区域很特别。

TLOAD一词用于eForth中的“文本”。它将整个区域作为一个字符串(长度为3072个字母)提供给文本解释器的输入。

关于如何将文本分成几行,存在分歧。MK Electronics内置的编辑器坚持使用24个字符的行长。Callisto使用Fort约定,其中字符串包含64个字符。eForth为用户提供了将所有文本计数为一条长行的选择。您可以使用内置编辑器MK-161。您可以编写自己的,与Callisto兼容的。

为了方便起见,这是eForth.mkt的初始内容,分为三行:

: hi ." , %user%!" CR ; ' hi 'boot ! hi \ 

第一行定义了迎接用户的新单词hi。 第二行使用该单词的标记(请参阅3.1)并将其放置在变量'BOOT中(请参阅1)。 现在,每次eForth启动时,文本区域将停止编译。 相反,将执行已编译的问候语。

最后一行以单词hi开头,在屏幕上显示问候语。 单词\完成对文本的解释,将控制权返回到控制台。

要编译任意文本文件,您需要使用BYE命令转到计算器,转到主菜单并以DOS模式加载所需的文件。 您也可以从计算机传输mkt文件。 C / P键将使您返回eForth,然后使用TLOAD命令可以编译加载到文本区域中的文件。

2.4.3程序存储器:eForth.mkp


程序存储器MK-161是一个隔离的地址空间。 它还存储字节,但是它们是只读的。 程序存储器包含10,000个“步骤”,这对于eForth来说是多余的。 超过四分之一的程序存储器被证明是可用的,这为翻译器的开发提供了良好的储备。

只有在程序存储器中才能实现“代码字”。 此外,此处还会显示名称识别表和所有已知的文本字符串,从而节省了二进制内存。

如果地址不是正数,则某些字(例如C @,COUNT和TYPE)可以寻址程序存储器。 例如,短语0 C @从程序存储器的地址0开始算作“步长”(字节)。

2.4.4小数内存:eForth.mkd


MK Electronics的数字从0到999的寄存器称为十进制,其中包含用于计算器上常规计算的数字-“尾数”的12个十进制数字和“顺序”的2个十进制数字。 该堡垒设计为使用最长4个字节的整数工作,这样的资源对于eForth显然是多余的。

十进制内存用于保存宝贵的二进制内存。 在这里进行数据栈和返回。 单词的标题存储在此处-用户定义的和嵌入的,每个标题一个寄存器。 这种方法使您甚至可以重新定义具有标准名称的单词。

十进制存储器中的堆栈会导致MK-161具备Fort的许多功能。 首先,堆栈元素的值范围很大;它可以容纳32位整数。 MK-161上不再需要“双整数”,尽管出于兼容性考虑,我已经使用了相应的单词eForth。 MK-161上的“双整数”表示为两个堆栈单元,其中包含从0到65535的数字,并在附加代码中编码一个带符号的32位整数。 此数字的高16位放在顶部,即最低地址。

按位逻辑运算AND,OR,XOR和NOT将其自变量视为16位整数。 从32768到65535的结果将转换为从-32768到-1的负数。 在eForth中,false编码为零,真值编码为一。 除零以外的任何值也为true。

161eForth数据堆栈的第二个功能是它包含带符号的数字。 当单词@从16位“单元”中读取数字65535时,它将自动转换为-1。 提供一个特殊的“无符号”字U @以便直接计数65535,并带有加号。

我记得为了提高速度,数据堆栈两个高位元素不在十进制存储器中,而是直接在X和Y寄存器中

eForth不使用十进制寄存器可以包含小数和浮点数的事实。 eForth虚拟机使用这些寄存器存储带符号的12位十进制整数。 十进制寄存器由C @和C来访问! -适用于任何单个寄存器的相同寄存器。

3.内部口译员


eForth核心是用MK-161输入语言编写的程序。 她的第一个MAIN命令将控制权转移到MAIN代码,该代码首先找出重新启动的情况。 如果是由错误的令牌引起的,MK-161将发出吱吱声。 在第一次启动时,以及在打开MK-161之后,屏幕都会被清除。 接下来,MAIN调用Init子例程来初始化中断系统以及MK-161控制台驱动程序所需的所有内容。

初始化数据堆栈并返回后,启动的低级部分已完成。 哈佛架构的机器发生了难以置信的事情-eForth继续执行字节存储器中的“有线代码”。 第一个荣誉是一个单词,其标题地址记录在R43中。 这通常是“冷”一词。

如何安排高级单词 (IED)? 任何单词都由两部分组成:主体和标题。 标头以十进制存储。 它可以帮助外部解释器和反编译器找到单词的名称和正文。 该标题还包含一个“词典”字段 -一组标志,可帮助外部解释器正确处理找到的单词。 对于位于二进制存储器中并存储在字典中的VCA主体,内部解释器更为重要。 他甚至可以执行没有标题的单词。

VCA 的主体 以code字段的字节开头,其中包含给定字的处理器地址。 四个VCA处理程序以MK-161输入语言编写,并从程序存储器的第一页开始。 我们将对它们全部进行分析(请参阅3.3),但是主要的一个称为DOLST,位于地址MAIN BP之后立即位于地址02。 该处理程序执行用冒号定义的Fort单词。

在代码字段的字节之后任意长度的参数字段 。 在“冒号”中,参数字段包含“缝制代码”-一系列16位令牌,每个令牌指示分配给它的一个动作。

首先,我们将更详细地考虑令牌。 然后,我们将研究INEXT内部解释器,该解释器将从一个令牌转移到另一个令牌的执行。 EForth将INEXT称为原始处理程序。 我们通过分析所有四个IED处理器来结束内部解释器的浏览。

3.1代币


令牌表示缝合代码和堆栈中的单词,从而可以快速执行该单词。 令牌是指向单词主体的指针,但是MK-161的苛刻架构对其这种简单的想法进行了自己的调整。 让我们从原始令牌开始分析所有类型的令牌。

3.1.1基本令牌


eForth分布中包含的所有单词的编号从0到206。此编号是端对端的,同时考虑了原语和VCA。 这样做是为了使单词的数量很容易恢复他的名字 。 这些名称存储在程序存储器中。 通过标题表可以轻松找到所需名称的链接。

原始数字是其令牌 。 像任何令牌一样,原语在缝制代码中占用两个字节。 第一个为零。 第二个包含他的电话号码。 使用tblTokens表,您可以通过该数字快速找到原始代码的地址。 tblTokens地址永久存储在R9042中(请参见2.2),也就是说,所有东西随时都在执行原语。

单词XT>允许您通过编号(令牌)找出原始代码的地址。 由于原语代码始终位于程序存储器中,因此接收到的地址始终为负(请参见2.4.3)。

3.1.2 VCA令牌


VCA可以具有自己的编号和关联的标准名称,也可以是全新的,由用户创建。 在所有情况下, VCA令牌都是其代码字段的地址 (请参阅3),即1000到5095之间的数字。

在缝纫代码中,VCA令牌以一种非常不寻常的方式编写。 在第一个字节中写入数百个(从10到50的数字),其余部分将令牌除以第二个字节中的100(从0到99的数字)。

例如,令牌1234将由两个字节12和34表示。使用来自ANSI标准的单词COMPILE对该令牌以及任何其他令牌进行编译。 要在缝制代码中写入和读取VCA令牌,请输入XT! 和XT @。 他们访问地址(请参阅3.1.4),单词XT @也能够读取原始令牌。

3.1.3整数文字


整个文字是一种原始标记。 它们非常不寻常,需要单独考虑。

在缝纫代码中,DOLIT和DOLITM令牌占据四个字节。 前两个字节包含已经考虑过的原始标记,即0和原始编号。 接下来的两个字节包含一个整数,该整数将在执行期间将给定的文字放入数据堆栈中。

DOLITM的不同之处在于,在将其放入堆栈之前,它会更改数字的符号。 它旨在实现负数。

3.1.4地址文字


与整个文字一样,三个地址文字 BRANCH,?BRANCH和DONXT在缝制的代码中分别占据4个字节。 前两个字节包含原始令牌,后两个字节是跳转地址。

地址以与VCA令牌相同的格式记录(请参阅3.1.2)。 第一个字节包含数百个数字,第二个字节包含将地址除以100的余数。我记得由于夸张(请参阅2.1),转换地址不包含所需令牌的地址,而是一个数字减去一个。

DONXT令牌有助于实现FOR-NEXT“结束周期”(请参见1)。 需要BRANCH无条件跳转来实现无限的BEGIN-AGAIN循环。 如果数据堆栈的顶部为零(假),则条件分支BRANCH转移控制权。 它用于实现条件IF-THEN语句,从“不确定循环” BEGIN-UNTIL和BEGIN-WHILE-REPEAT退出。

3.1.5字符串文字


字符串文字是VCA令牌的一种。 在字符串文字的缝合代码中,在令牌之后,有一个字节,其长度为字符串,其后是字符串本身,从第一个字节到最后一个字节。

EForth具有三个字符串文字:$“ | ,.” | 它们在eForth0.mkl文件中分别定义为STRQP,DOTQP和ABORQ令牌。“字面量”的主要工作是通过do $令牌DOSTR令牌完成的。

为了使文章大小合理,我不能过多地关注这个有趣的话题,但是很高兴知道它们在eForth中的可用性。

3.2地址解释器


现在是时候考虑令牌解释器了 ,该地址的地址总是写在寄存器9中。大多数原语使用命令K BP 9完成其工作,该命令将控制权转移到INEXT标签。

 INEXT: 6 Fx≠0 NPrime NData:  2 6 + 7 F⟳ 7 8 F⟳ 8 

首先,地址解释器使用KIP6命令读取下一个令牌的第一个字节。 如果为零,则为原语,标签为NPrime的代码将处理令牌。

标签NData表示VCA令牌的处理。 VP 2命令将第一个字节乘以100,然后KIP6 +将令牌的第二个字节添加到结果中(请参阅3.1.2)。 读令牌由P7团队输入“工作寄存器” WP(R7)中。

我们知道,VCA令牌是其代码字段的地址,其中包含处理器的地址。 KIP7 P8命令读取R8中代码字段的字节,KBP8命令将控制权转移到VCA处理器。 处理程序知道R7包含的数字比正在处理的单词的参数字段的地址小1。

代码为25的命令F⟳在堆栈上被“整理”。 事实是eForth将数据堆栈的前两个元素直接存储在MK-161堆栈的X和Y寄存器中。 这种解决方案加快了工作速度,但有必要确保这些重要数据不会丢失。

仍然需要了解地址解释器如何执行原语。

 NPrime: F⟳ 6 9210 8 F⟳ 8 

KIP6命令读取原始令牌的第二个字节。 RRP9210 P8命令从tblTokens表中读取该原语的地址(请参阅2.2和3.1.1),KBP8将控制权转移到该原语。

如上所述,F 1从堆栈中除去多余的,恢复寄存器X和Y的内容。

eForth地址解释器非常小,以至于它在程序存储器中重复了几次。 主副本由命令K BP 9执行,该命令可完成大多数原语。

作为练习,我建议研究在EXECU标签后面放置EXECUTE一词的实现。 这是一个INEXT变体,它不从缝纫代码读取令牌,而是从数据堆栈中获取令牌。

3.3 VCA处理程序


四种VCA具有四种不同的处理程序:DOLST,DOVAR,DOCON和DOCONM。 上面我们已经看到,在调用处理程序之前,地址解释器在R7中为要处理的单词的代码字段保留地址。

eForth.f通过从eForth0.mkp文件读取内核头文件来学习这些处理程序的地址。 通过将结果放在eForth.mkb文件中,这可以帮助他正确地为电子MK-161编译VCA。

3.3.1冒号词:DOLST和EXIT


INEXT之后的下一个重要主题是内部解释器在遇到通过冒号定义的单词的标记时所要做的事情。 这个单词的代码字段包含数字2,因此INEXT将控制权转移到DOLST处理程序,该处理程序进行必要的工作以开始解释新的令牌列表。

 DOLST: 6 2 F⟳ 7 6 F⟳ INEXT: 

正如我们已经讨论过的(见2.1),寄存器2包含一个RP返回堆栈指针。 IP6 KP2命令将R6的值(解释指针(IP))写入返回堆栈。 稍后,这将有助于记住旧标记列表中的当前位置,即INEXT遇到一个冒号。 现在IP7 P6将IP重新排列到新列表的开头。

在DOLST代码之后,立即放置INEXT代码,它将执行新令牌列表的第一个字。 与其他地方一样,F命令有助于维护数据堆栈的前两个元素。

冒号词通常以EXITT令牌结尾,与DOLST相比,反之则相反-它从返回堆栈中获取旧IP值,并返回到旧令牌列表的解释。

 EXITT: 02 6 x 1 2 + 2 F⟳ INEXT: 

命令RKIP02 P6从返回堆栈的顶部读取旧的IP值(请参阅2.1)。 之后,Cx 1 IP2 + P2命令会校正RP的值,将其增加一。 F⟳命令恢复堆栈,然后INEXT执行旧令牌列表中的下一个单词。

当然,在DOLST之后和EXITT之后都不能同时执行INEXT。 为此,我采用了苏联时期的一种古老技巧。 您也可以通过检查eForth0.mkl文件中的相应行来掌握它。

3.3.2 DOVAR,变量和数组处理程序


由单词CREATE和VARIABLE生成的单词使用相同的DOVAR处理程序。 该处理程序将位于参数字段中的变量的地址压入堆栈,该地址紧随代码字段的字节之后。 VARIABLE变量占用2个字节,并且使用CREATE创建的数组包含程序员所需的字节数。

 DOVAR: ⇔ 3 x 1 7 + 9 

命令⇔KP3将寄存器Y的内容保存在数据堆栈中,同时,将堆栈顶部的数字输入RY,将RX释放为新值。 在执行Cx 1 IP7 +命令后,堆栈顶部的这个新值将成为可执行字的参数字段的地址。 KBP9无需任何技巧即可将控制权转移到INEXT,继续进行下一个单词。

3.3.3常量处理程序:DOCON和DOCONM


与DOVAR不同, 常量处理程序访问其单词本身的参数字段。 DOCON从中读取一个16位常数值。 该值始终为正。

 DOCON: ⇔ 3 ⇔ 7 5 x 256 5 × 5 + 9 

命令⇔KP3⇔将RY保存在数据堆栈中。 但是这次,数据堆栈的旧顶部返回到RX。 IP7 P5命令将其强制返回RY,同时准备指针寄存器R5读取常量的值。 接下来,Cx 256用数字256替换寄存器X中的垃圾。

仪器KIP5×KIP5 +从参数字段读取数据栈顶部(即RX中)的常量。 我们记得,在MK-161中,第一个字节始终为高。 它乘以256,然后将常数的最低有效字节加到乘积上。 完成所有工作,KBP9将控制权转移到下一个单词。

DOCONM的工作原理完全相同,只是读取后的常数符号变为相反的符号。 为了提高速度,在MK-161上将负常数实现为单独的处理器:

 DOCONM: ⇔ 3 ⇔ 7 5 x 256 5 × 5 + /-/ 9 

现在,我们已经从数据区域完全弄清了eForth如何在MK-161电子设备上执行其代码,甚至涉及到字符串文字的更深层次的主题(请参阅3.1.5)。

在本系列的第二篇文章中,我将讨论外部“文本”解释器161eForth,分析头表的结构和名称识别。 译者的这一部分要求我开发更为激进的解决方案,而在此背景下,以上讨论的是传统的,古老而又美好的堡垒。

快乐堡编程!

文学作品


  1. 博士 丁陈汉森。 eForth和Zen-第3版,2017年。在Amazon Kindle上可用。
  2. Baranov S.N.,Nozdrunov N.R. Fort语言及其实现。 -L。:机械工程。 列宁格勒 系,1988。
  3. Semenov Yu.A. 用FORT语言编程。 -M .:无线电和通讯,1991年。
  4. ANS Forth标准。 X3.215-1994。 笔译
  5. SP-Forth文档
  6. Offete商店(Ting-Hanson Ting博士的论文集) ,在这里您可以下载Windows的86eForth v5.2英文文档。


影片插图


这四个小161eForth视频继续进行。 本文开头的第一个视频。

第5部分的第2部分。在MK-161上测试第3版“ eForth and Zen”一书中的TEST-TEST4。



第5部分的第3部分。SEE反编译器。



第5部分的第4部分。断点BYE,RS-232终端和对MK-161的远程访问。



第5部分,共5部分。结论词。

Source: https://habr.com/ru/post/zh-CN452398/


All Articles