如何使用 16 位汇编在 DOS 下格式化软盘?
How to format a floppy diskette in DOS using 16-bit assembly?
我在旧书上学习x86汇编DOS编程,在关于中断的讨论中,我看到了13h。书上说我可以用它来格式化驱动器。但不幸的是,我的书中没有提供更多关于如何做到这一点的信息。
我很好奇,想自己用,但是不行。如何使用 16 位 x86 程序集格式化驱动器 A: 中的软盘?做起来简单吗?我在 MS-DOS 中使用 TASM 编译和 link,以及 运行。
也许除了使用 int 13h
之外还有其他方法吗?
int 13h
是合适的方法,但不是调用 DOS 服务,您实际上是在使用它来调用 ROM BIOS 服务。我不认为 DOS 提供任何格式化磁盘的服务。应用程序通常将 FAT 的这种低级操作留给操作系统,仅使用 OS 提供的服务来执行高级 read/write 操作。
具体来说,int 13h
,服务05h
格式化磁盘轨道。 (调用中断时,服务编号进入 AH
寄存器。)请注意,此服务格式化 单个轨道 ,而不是一次格式化整个磁盘。您必须多次调用此服务才能格式化整个磁盘。这样做的好处是,它允许您为每个轨道指定不同的特征 - 甚至轨道上的每个扇区(一些老式的复制保护方案通过创建具有奇怪格式的轨道来使用它)。
服务05h
的参数与其他磁盘read/write服务的参数基本相同,只是不需要指定扇区号(通常传入CL
), 因为您不能格式化单个扇区。以下是软盘服务所需参数的列表:
- 驱动器号:
DL
- 头号:
DH
- 缸数:
CH
- 扇区号:
CL
(不用于格式化!)
- 扇区数:
AL
- 缓冲区地址:
ES:BX
如果带有进位标志(CF
)的中断returns被清除,则没有错误发生并且AH
寄存器将包含0。如果CF
被设置,然后发生错误,AH
寄存器包含错误代码。
Peter Norton 的话,来自 IBM PC 新程序员指南和 PS/2:
Every sector on a diskette track has 4 descriptive bytes associated with it. You specify these 4 bytes for each sector to be formatted by creating a table of 4-byte groups and passing the table's address in the register pair ES:BX
. When you format a disk track, the 4-byte groups are written to the diskette immediately in front of the individual sectors in the track. The 4 bytes of data associated with a sector on the disk are known as address marks and are used by the disk controller to identify individual sectors during the read, write, and verify operations. The 4 bytes are referred to as C for cylinder, H for head, R for record (or sector number), and N for number of bytes per sector (also called the size code).
When a sector is being read or written, the diskette controller searches the diskette track for the sector's ID, the essential part of which is R, the record or sector number. The cylinder and head parameters are not actually needed in this address mark because the read/write head is positioned mechanically at the proper track and the side is selected electronically, but they are recorded and tested as a safety check.
The size code (N) can take on any one of the four standard values shown below:
N | Sector Size (bytes) | Sector Size (KB)
–––––|–––––––––––––––––––––|–––––––––––––––––
0 | 128 | 1/8
1 | 256 | 1/4
2 | 512 | 1/2
3 | 1024 | 1
The normal setting is code 2 (512 bytes).
格式化软盘轨道的完整过程相当复杂,涉及的不仅仅是调用服务 05h
。您需要执行以下操作:
调用服务17h
设置要格式化的软盘类型。 (这只需要在开始操作之前完成一次。)
调用服务 18h
为格式设置媒体类型。
为要格式化的轨道创建一个table地址标记,方法如上文所述。每个扇区的 table 中必须有一个 4 字节的条目。
最后,调用服务05h
格式化曲目。
可以选择调用服务 04h
来验证格式化过程。这将验证是否可以找到并读取该扇区,以及循环冗余校验 (CRC) 是否正确。 DOS 的 format.com
这样做是为了在格式化后验证每个磁道,但磁盘驱动器通常足够可靠,因此实际上不需要验证。
所有这些磁盘 I/O 服务都使用上面列出的相同参数,尽管与服务 05h
一样,其中一些可能会被忽略。在线搜索中断指南以获得更详细的信息。例如,here is a complete list of ROM BIOS disk I/O services. And here is another. The aforequoted guide by Peter Norton is also excellent, if you can find an old copy lying around somewhere, like maybe Amazon?
(请注意,格式化硬盘的情况略有不同,对于 PS/2s 中的 ESDI 驱动器,您必须使用完全不同的格式化服务 —1Ah
。)
更新: 原来可能有DOS API来做这件事,毕竟。不幸的是,我不知道它真的让事情变得简单得多。关键是要用IOCTL。
IOCTL API由DOS定义,但实际上是由设备驱动implemented/handled定义的,也就是说支持是由驱动厂商和版本决定的,而不是DOS 的版本。如果你用的是VM环境,应该是支持的,不过我没实际测试过。
DOS函数44h
是设备I/O控制(IOCTL),所以你在调用INT 21h
之前将AH
设置为44h
(一个 DOS 中断)。
要格式化,您需要块设备的 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
结构的地址,指示要格式化的磁头和柱面号
如果在函数 returns 时设置了进位标志,则 AX
包含错误代码。
不幸的是,除了 this page. This stuff predated the web and very little has been uploaded there. :-( You really need a book like Advanced MS-DOS Programming 之外,我在网上找不到 IoctlFmtVrfyTrackRec
的任何文档,我也没有它的副本。
I did 设法出现 this document on Scribd,它声称是使用 IOCTL 的格式实现,由 Pierre Desloover 编写。我没有测试过。
我在旧书上学习x86汇编DOS编程,在关于中断的讨论中,我看到了13h。书上说我可以用它来格式化驱动器。但不幸的是,我的书中没有提供更多关于如何做到这一点的信息。
我很好奇,想自己用,但是不行。如何使用 16 位 x86 程序集格式化驱动器 A: 中的软盘?做起来简单吗?我在 MS-DOS 中使用 TASM 编译和 link,以及 运行。
也许除了使用 int 13h
之外还有其他方法吗?
int 13h
是合适的方法,但不是调用 DOS 服务,您实际上是在使用它来调用 ROM BIOS 服务。我不认为 DOS 提供任何格式化磁盘的服务。应用程序通常将 FAT 的这种低级操作留给操作系统,仅使用 OS 提供的服务来执行高级 read/write 操作。
具体来说,int 13h
,服务05h
格式化磁盘轨道。 (调用中断时,服务编号进入 AH
寄存器。)请注意,此服务格式化 单个轨道 ,而不是一次格式化整个磁盘。您必须多次调用此服务才能格式化整个磁盘。这样做的好处是,它允许您为每个轨道指定不同的特征 - 甚至轨道上的每个扇区(一些老式的复制保护方案通过创建具有奇怪格式的轨道来使用它)。
服务05h
的参数与其他磁盘read/write服务的参数基本相同,只是不需要指定扇区号(通常传入CL
), 因为您不能格式化单个扇区。以下是软盘服务所需参数的列表:
- 驱动器号:
DL
- 头号:
DH
- 缸数:
CH
- 扇区号:
CL
(不用于格式化!) - 扇区数:
AL
- 缓冲区地址:
ES:BX
如果带有进位标志(CF
)的中断returns被清除,则没有错误发生并且AH
寄存器将包含0。如果CF
被设置,然后发生错误,AH
寄存器包含错误代码。
Peter Norton 的话,来自 IBM PC 新程序员指南和 PS/2:
Every sector on a diskette track has 4 descriptive bytes associated with it. You specify these 4 bytes for each sector to be formatted by creating a table of 4-byte groups and passing the table's address in the register pair
ES:BX
. When you format a disk track, the 4-byte groups are written to the diskette immediately in front of the individual sectors in the track. The 4 bytes of data associated with a sector on the disk are known as address marks and are used by the disk controller to identify individual sectors during the read, write, and verify operations. The 4 bytes are referred to as C for cylinder, H for head, R for record (or sector number), and N for number of bytes per sector (also called the size code).When a sector is being read or written, the diskette controller searches the diskette track for the sector's ID, the essential part of which is R, the record or sector number. The cylinder and head parameters are not actually needed in this address mark because the read/write head is positioned mechanically at the proper track and the side is selected electronically, but they are recorded and tested as a safety check.
The size code (N) can take on any one of the four standard values shown below:
N | Sector Size (bytes) | Sector Size (KB) –––––|–––––––––––––––––––––|––––––––––––––––– 0 | 128 | 1/8 1 | 256 | 1/4 2 | 512 | 1/2 3 | 1024 | 1
The normal setting is code 2 (512 bytes).
格式化软盘轨道的完整过程相当复杂,涉及的不仅仅是调用服务 05h
。您需要执行以下操作:
调用服务
17h
设置要格式化的软盘类型。 (这只需要在开始操作之前完成一次。)调用服务
18h
为格式设置媒体类型。为要格式化的轨道创建一个table地址标记,方法如上文所述。每个扇区的 table 中必须有一个 4 字节的条目。
最后,调用服务
05h
格式化曲目。可以选择调用服务
04h
来验证格式化过程。这将验证是否可以找到并读取该扇区,以及循环冗余校验 (CRC) 是否正确。 DOS 的format.com
这样做是为了在格式化后验证每个磁道,但磁盘驱动器通常足够可靠,因此实际上不需要验证。
所有这些磁盘 I/O 服务都使用上面列出的相同参数,尽管与服务 05h
一样,其中一些可能会被忽略。在线搜索中断指南以获得更详细的信息。例如,here is a complete list of ROM BIOS disk I/O services. And here is another. The aforequoted guide by Peter Norton is also excellent, if you can find an old copy lying around somewhere, like maybe Amazon?
(请注意,格式化硬盘的情况略有不同,对于 PS/2s 中的 ESDI 驱动器,您必须使用完全不同的格式化服务 —1Ah
。)
更新: 原来可能有DOS API来做这件事,毕竟。不幸的是,我不知道它真的让事情变得简单得多。关键是要用IOCTL。
IOCTL API由DOS定义,但实际上是由设备驱动implemented/handled定义的,也就是说支持是由驱动厂商和版本决定的,而不是DOS 的版本。如果你用的是VM环境,应该是支持的,不过我没实际测试过。
DOS函数44h
是设备I/O控制(IOCTL),所以你在调用INT 21h
之前将AH
设置为44h
(一个 DOS 中断)。
要格式化,您需要块设备的 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
结构的地址,指示要格式化的磁头和柱面号
如果在函数 returns 时设置了进位标志,则 AX
包含错误代码。
不幸的是,除了 this page. This stuff predated the web and very little has been uploaded there. :-( You really need a book like Advanced MS-DOS Programming 之外,我在网上找不到 IoctlFmtVrfyTrackRec
的任何文档,我也没有它的副本。
I did 设法出现 this document on Scribd,它声称是使用 IOCTL 的格式实现,由 Pierre Desloover 编写。我没有测试过。