如何使用16位汇编在DOS中格式化软盘?

时间:2017-01-05 16:10:18

标签: assembly x86 dos x86-16 floppy

我在旧书中研究了DOS的x86汇编编程,在关于中断的讨论中,我看到了13h。这本书说我可以用它来格式化一个驱动器。但不幸的是,在我的书中没有提供关于如何做到这一点的更多信息。

我变得非常好奇,并试图将它用于自己,但它不起作用。如何使用16位x86汇编在驱动器A:中格式化软盘?这样做很简单吗?我使用TASM编译和链接,并在MS-DOS中运行。

除了使用int 13h之外,还有其他方法吗?

1 个答案:

答案 0 :(得分:8)

int 13h是执行此操作的合适方法,但您实际上使用它来调用ROM BIOS服务,而不是调用DOS服务。我不认为DOS提供任何格式化磁盘的服务。应用程序通常只使用OS提供的服务进行高级读/写操作,将FAT的低级操作留给操作系统。

具体而言,int 13h,服务05h格式化磁盘轨道。 (当您调用中断时,服务编号会进入AH寄存器。)请注意,此服务会格式化单轨,而不是整个磁盘。您必须多次调用此服务才能格式化整个磁盘。关于这一点的好处是,它允许您为每个轨道指定不同的特征 - 甚至是轨道上的每个扇区(一些老式的复制保护方案通过创建具有古怪格式的轨道来使用它)。

服务05h的参数与其他每个磁盘读/写服务的参数基本相同,只是您不需要指定扇区号(通常在CL中传递),因为你不能格式化个别部门。这是软盘服务所需参数的列表:

  • 车号:DL
  • 头号:DH
  • 柱面编号:CH
  • 扇区号:CL(不用于格式!)
  • 行业数量:AL
  • 缓冲区地址:ES:BX

如果中断返回并且进位标志(CF)清零,则不会发生错误,AH寄存器将包含0.如果设置了CF,则发生错误, AH寄存器包含错误代码。

用Peter Norton的话说,来自新程序员的IBM PC和PS / 2指南

  

软盘轨道上的每个扇区都有4个与之关联的描述性字节。通过创建一个4字节组的表并将表的地址传递给寄存器对ES:BX,可以为要格式化的每个扇区指定这4个字节。格式化磁盘磁道时,4字节组会立即写入磁盘中磁道的各个扇区前面。与磁盘上扇区相关联的4字节数据称为地址标记,并由磁盘控制器用于在读取,写入和验证操作期间识别各个扇区。 4个字节称为圆柱体C,头部为H,记录(或扇区编号)为R,每扇区字节数为N(也称为尺寸代码)。

     

当正在读取或写入扇区时,软盘控制器在软盘轨道中搜索扇区的ID,其中必要部分是R,记录或扇区号。此地址标记中实际上不需要气缸和磁头参数,因为读/写磁头机械定位在适当的轨道上,并且电子选择侧面,但它们作为安全检查进行记录和测试。

     

尺码(N)可以采用以下四种标准值中的任何一种:

  N  | Sector Size (bytes) | Sector Size (KB)
–––––|–––––––––––––––––––––|–––––––––––––––––
  0  |         128         |      1/8
  1  |         256         |      1/4
  2  |         512         |      1/2
  3  |        1024         |       1
     

正常设置是代码2(512字节)。

格式化软盘轨道的完整过程相当复杂,涉及的不仅仅是调用服务05h。您需要执行以下操作:

  1. 致电服务17h以设置要格式化的软盘类型。 (这只需要在开始操作之前完成一次。)

  2. 致电服务18h以设置格式的媒体类型。

  3. 按照上面引文中描述的方式为要格式化的曲目创建地址标记表。每个扇区的表格中必须有一个4字节的条目。

  4. 最后,致电服务05h以格式化曲目。

  5. 或者,通过调用服务04h进行跟进,以验证格式化过程。这将验证可以找到和读取扇区,以及循环冗余校验(CRC)是否正确。 DOS的format.com执行此操作以在格式化之后验证每个轨道,但磁盘驱动器通常足够可靠,以至于不需要验证。

  6. 所有这些磁盘I / O服务都使用与上面列出的相同的参数,但是,与服务05h一样,其中一些可能会被忽略。在线搜索中断指南以获取更多详细信息。例如,here is a complete list of ROM BIOS disk I/O services。并且here is another。 Peter Norton的上述指南也非常出色,如果你能找到一个旧版本,就像maybe Amazon那样?

    (请注意,格式化硬盘的情况略有不同,对于PS / 2中的ESDI驱动器,您必须使用完全不同的服务进行格式化 - 1Ah。)

    更新:事实证明,可能有一个DOS API可以执行此操作。不幸的是,我不知道它确实让事情变得更加简单。关键是使用IOCTL。

    IOCTL API由DOS定义,但它实际上是由设备驱动程序实现/处理的,这意味着支持由驱动程序供应商和版本而不是DOS版本决定。如果你正在使用VM环境,它应该支持这个,但我还没有真正测试过它。

    DOS函数44h是设备I / O控件(IOCTL),因此在调用AH(DOS中断)之前将44h设置为INT 21h

    要格式化,您需要IOCTL用于块设备。块IOCTL函数至少需要DOS 3.2或更高版本(有些版本需要甚至更高版本)。它们不仅允许一次访问整个轨道,还支持格式化功能。他们使用子功能0Dh进行访问,因此您需要将AL设置为0Dh

    将这些放在一起,您只需将AX设置为440Dh并致电INT 21h即可。格式函数的次要代码42h,位于CL

    总之,用于格式化逻辑驱动器上的轨道的DOS块IOCTL函数将被调用如下:

    • AX == 440Dh
    • CL == 42h
    • CH == 08h(阻止设备类别)
    • BX ==驱动器号码(0 =默认值,1 = A:,2 = B:等等)
    • DS:DX == IoctlFmtVrfyTrackRec结构的地址,表示要格式化的头部和柱面编号

    如果函数返回时设置了进位标志,则AX包含错误代码。

    不幸的是,除了this page之外,我无法在线找到IoctlFmtVrfyTrackRec的任何文档。这些东西早于网络,很少上传到那里。 :-(你真的需要一本像Advanced MS-DOS Programming这样的书,我也没有这本书的副本。

    设法出现this document on Scribd,声称是使用IOCTL格式的实现,由Pierre Desloover编写。我还没有测试过它。