int 13h 是执行此操作的适当方式,但您实际上不是调用 DOS 服务,而是使用它来调用 ROM BIOS 服务。我不认为 DOS 提供任何格式化磁盘的服务。应用程序通常将这种对 FAT 的低级操作留给操作系统,只使用操作系统提供的服务来执行高级读/写操作。
具体来说,int 13h, service 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。您需要执行以下操作:
-
致电服务17h 设置要格式化的软盘类型。 (这只需在开始操作之前完成一次。)
-
调用服务18h设置格式的媒体类型。
-
按照上面引用中描述的方式,为要格式化的轨道创建一个地址标记表。每个扇区的表中必须有一个 4 字节的条目。
-
最后,调用service05h格式化音轨。
-
或者,通过调用服务04h 来验证格式化过程。这验证了扇区可以被找到和读取,并且循环冗余校验 (CRC) 是正确的。 DOS 的format.com 这样做是为了在格式化后验证每个磁道,但磁盘驱动器通常足够可靠,因此不需要验证。
所有这些磁盘 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 的版本决定。如果你使用的是虚拟机环境,它应该支持这个,但我还没有实际测试过。
DOS 函数 44h 是设备 I/O 控制 (IOCTL),因此您在调用 INT 21h(DOS 中断)之前将 AH 设置为 44h。
要格式化,您需要 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,它声称是由 Pierre Desloover 编写的使用 IOCTL 的格式实现。我没有测试过。