真的是雅塔里街吗?

2020-09-22 18:17:40

本博客之前曾研究过DOS的BIOS模块中的一个非常非常奇怪的代码片段。简单地说,当决定引导扇区是否可能具有有效的BPB时,DOS会检查第一个字节是相对跳转(操作码E9h)还是短跳转(操作码EBh),这两个字节都由不同的DOS版本使用。但是它也用69h操作码检查“直接跳转”。

在日期为1987年5月1日的MS-DOS 3.21 Oak源文件中,代码如下所示:

CMP字节PTR cs:[DiskSector],069H;是直接跳转吗?JE Check_Signature;不需要查找NOP CMP字节PTR cs:[DiskSector],0E9H;DOS 2.0跳转?JE CHECK_Signature;不需要NOP CMP字节PTR cs:[DiskSector],0EBH;跳短怎么样。JNE BadDisk CMP字节PTR cs:[DiskSector]+2,090H;下一个是NOP吗?JNE坏盘。

代码在日期为1987年7月24日的MS-DOS 3.3 OAK源文件中没有实质性差异:

CMP字节PTR cs:[DiskSector],069H;是直接跳转吗?JE CHECK_BPB_MediaByte;DON';T是否需要查找NOP CMP字节PTR cs:[DiskSector],0E9H;DOS 2.0跳转?JE CHECK_BPB_MediaByte;不需要NOP CMP字节PTR cs:[DiskSector],0EBH;跳短怎么样。JNE INVALIDBOOTSEC CMP字节PTR cs:[DiskSector]+2,090H;下一个是NOP吗?JNE INVALIDBOOTSEC。

标签不同,但逻辑是相同的。但是,当然x86上没有这种“直接跳转”,69h操作码(8086上没有文档记录,更高的CPU上没有IMUL)毫无意义。那是什么?

一位读者之前曾提出这样的想法,即该代码可能是为了支持Atari St软盘。这在某种程度上是有道理的,但在某种程度上是不合理的。让我们从它是如何说不通的开始吧。

Atari ST使用的是摩托罗拉68000 CPU(ST指的是16/32,指的是68kCPU的外部和内部数据宽度),虽然引导扇区以跳转指令(BRA.S)开始,但其操作码是60h而不是69h。

但雅达利ST确实有很多方面是有意义的。Atari ST是少数使用胖格式软盘的非PC、非x86平台之一。Atari ST使用的是与PC相同的3.5英寸DD(最初)介质。雅达利ST和DOS之间在3.5英寸软盘上交换数据实际上是可能的。

雅达利ST于1985年推出。神秘的操作码69h检查是什么时候添加到DOS中的?碰巧的是,我们可以相当准确地确定时间线。检查PC DOS 3.1和3.2中的IBMBIO.COM清楚地显示,69h检查是在DOS 3.2中添加的。PC DOS 3.1中的IBMBIO.COM文件的日期为1985年3月,而PC DOS 3.2中的IBMBIO.COM文件的日期为1985年12月。换句话说,微软一定是在1985年的某个时候添加了69h检查。

从时间轴的角度来看,在1985年添加对Atari ST媒体的支持是很有意义的。碰巧PC DOS 3.2是第一个支持3.5英寸媒体的。

“直接跳转”的评论不那么明显,但至少有一定的道理。68k BRA指令是直接的,因为相对偏移量是指令操作码序列的一部分。与68k JMP不同,BRA指令不支持任何类型的间接寻址。

操作码不匹配也可以解释。可能是打字错误,因为“9”和“0”在键盘上紧挨着。这也可能是误读;特别是在手写文本上,草率地写成的0可能看起来像一个9。此外,8086程序员很可能不知道68k操作码,因此不会发现错误。

更重要的是,错误的检查可能很容易逃脱测试。首先,Atari ST可引导软盘确实以60h操作码(不是69h)开始,但非可引导ST软盘无论如何都没有这样的要求。除了DOS不需要有效的BPB即可使用软盘。如果在Atari ST上格式化720k软盘,则无法识别其引导扇区,但可以识别其胖介质字节。DOS将能够很好地使用它,并且测试人员不会注意到BPB有效性检查失败。

请注意,对于雅达利ST 800K软盘而言,上述情况并非如此。除非DOS具有有效的BPB(即引导扇区),否则DOS将无法正确处理这些问题。然而,这可能是没有经过测试的东西。

总而言之,即使它实际上是错误的,添加69h检查来支持Atari ST磁盘并不像看起来那么不可思议。这绝不是确凿的证据,但也不疯狂。而且,如果正如间接证据所显示的那样,在1985年添加该检查是为了支持某些非x86平台,那么Atari ST也是一个很好的解释。