为Z80移植GW-Basic

2020-06-23 06:17:26

我们花了大量的试验、错误和检查整个代码和Z80指令集,才找到在GW-BASIC源代码的反向翻译中可以改进的模式和东西。这件事最终有点复杂,但足够复杂,足以匹配和转换我可以找到的所有模式,这些模式一次需要转换多条指令。随着我对Z80功能有了更多的了解,比如条件调用或RET指令,一些模式开始出现,这一步得到了一些非常需要的改进。最后一步是生成Z80代码。我必须做的第一件事是找出8086和Z80的寄存器映射。这并不难,因为GW-BASIC中的许多较旧的代码仍然有引用Intel8080寄存器的注释,这些寄存器在Z80中的名称是相同的。一些较新的代码无法映射到Intel8080,但幸运的是,由于索引寄存器IX和IY的存在,它们可以在Z80中映射。右边的表格根据阅读源代码注释和Z80指令的可用性总结了我的转换器正在使用的寄存器映射。在编写转换步骤之前,我不知道如何使用AH寄存器。整个代码库都有一些用途,而Z80中没有对应的用途:16位寄存器AF、F的低位部分用于标志;它不是真正的通用寄存器。幸运的是,由于8086GW-BASIC代码的性质,AH寄存器的使用遵循一种模式(由专有的Microsoft ISA转换器发出),我能够找出并发出指令,例如ex AF,AF';(将AF与其影子寄存器AF进行交换,AF';),或者根据情况推送AF和POP AF。最后一步要么在尝试使用错误数量的参数生成指令时断言失败,要么在其他不变量都不成立的情况下引发异常。例如,生成8086 ROR(向右旋转)指令的Z80等价物的代码如下:def_gen_direction_ror(self,Token):assert len(TOKEN[';Operators';])==2 op1,op2=Token[';Operators';]if op2==1:if op1=';AL';:如果不是self,则返回';rra&39;_is_16bit_reg(Op1)和自身中的op1。regmap:返回';rr%s';%self。regmap[OP]if op1==';[bx]';:return';rr(HL)';raise SyntaxError(";Don';t知道如何使用op%s,%s&34;%(op1,op2)生成ROR)。

它将只识别对GW-Basic源代码有意义的RoR指令的使用。这个主题一遍又一遍地重复。MAP、Z80 Heaven等站点以及详细说明每个条件跳转指令如何使用每组标志的这个表都非常有帮助。其他一些网站,如CPC技术页面或WikiTI,有一些很棒的提示,帮助我将8086指令映射到Z80,并给了我一些关于如何实现IMUL或IDIV等指令的想法。我家里碰巧也有一些死树的书,包括最初的英特尔8086手册和一本针对MSX的Z80编程的书(虽然它实际上没有提到非文档说明,其中一些在编写这个转换器时很有用),但帮助不大。缺少Ctrl+F对这类文档没有帮助。最后,但同样重要的是,我想不分先后地感谢里卡多·比腾古尔、丹尼尔·卡埃塔诺、乔瓦尼·努内斯和皮特·朋克等人在我发推特谈论这件事时给予的帮助。这个转换工具已经可以做很多工作了,但是它还不完整。我确实因为个人原因暂停了一段时间的工作,但正如我之前提到的,它正在被重构,以便在Transformer和Writer步骤之间有一个中间步骤,这应该会在解决由于生成无效Z80指令而导致的错误时减少一些干扰。在GW-Basic源代码的其他分支中也进行了一些工作,人们试图使用较旧版本的Microsoft汇编器和Linker,或者使用更现代的工具(如JWAsm和JWLink)来构建GW-Basic源代码。一些使解释器工作的代码丢失了,但它主要是特定于平台的粘合代码,这些代码要么从头开始重新实现,要么从之前在MIT许可下发布的(仅限二进制的)BASICA.COM代码进行反向工程。一些丢失的符号的名称对我来说是可疑的,事实上,它们中的许多实际上是MSX中的BIOS函数的名称。考虑到微软在这些电脑中设计了BIOS,这并不令人惊讶。(这也很好,因为如果我能让它在MSX上运行,我就不需要重新实现那些东西了。)。最终,我的想法是以此为基础