1

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

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

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

4

1 回答 1

8

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

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

服务的参数05h与其他所有磁盘读/写服务的参数基本相同,只是您不需要指定扇区号(通常传入CL),因为您无法格式化单个扇区。以下是软盘服务所需参数的列表:

  • 驱动器号:DL
  • 头号:DH
  • 缸号:CH
  • 扇区号:(CL不用于格式!)
  • 扇区数:AL
  • 缓冲区地址:ES:BX

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

用 Peter Norton 的话来说,来自The New Programmer's Guide to the IBM PC 和 PS/2

软盘磁道上的每个扇区都有 4 个与之相关的描述性字节。通过创建一个 4 字节组的表并在寄存器对中传递表的地址,您可以为要格式化的每个扇区指定这 4 个字节ES:BX。当您格式化磁盘磁道时,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 字节)。

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

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

  2. 调用服务18h来设置格式的媒体类型。

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

  4. 最后,调用服务05h格式化轨道。

  5. 或者,通过调用服务04h来验证格式化过程。这验证了扇区可以被找到和读取,并且循环冗余校验 (CRC) 是正确的。DOSformat.com这样做是为了在格式化后验证每个磁道,但磁盘驱动器通常足够可靠,因此不需要验证。

所有这些磁盘 I/O 服务都使用上面列出的相同参数,尽管与 service 一样05h,其中一些可能会被忽略。在线搜索中断指南以获得更详细的信息。例如,这里是 ROM BIOS 磁盘 I/O 服务的完整列表。这是另一个。彼得·诺顿(Peter Norton)前面引用的指南也很棒,如果您可以在某个地方找到旧副本,例如亚马逊

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


更新:事实证明,毕竟可能有一个 DOS API 可以做到这一点。不幸的是,我不知道它真的让事情变得简单得多。关键是使用IOCTL。

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

DOS函数44h是设备I/O控制(IOCTL),所以你在调用之前设置AH为(一个DOS中断)。44hINT 21h

要格式化,您需要 IOCTL 用于块设备。块 IOCTL 功能至少需要 DOS 3.2 或更高版本(有些需要更高版本)。它们不仅允许一次访问整个轨道,还支持格式化功能。它们是使用 subfunction 访问的0Dh,所以你设置AL0Dh.

将这些放在一起,您只需设置AX440Dh调用INT 21h. 格式化函数的次要代码42h是,放在CL.

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

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

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

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

确实设法在 Scribd 上找到了这个文档,它声称是由 Pierre Desloover 编写的使用 IOCTL 的格式实现。我没有测试过。

于 2017-01-05T16:46:45.743 回答