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

Men*_*Rox 1 x86 assembly dos floppy x86-16

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

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

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

Cod*_*ray 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字节组的表并将表的地址传递给寄存器对,为每个要格式化的扇区指定这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
Run Code Online (Sandbox Code Playgroud)

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

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

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

  2. 呼叫服务18h以设置格式的媒体类型.

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

  4. 最后,呼叫服务05h以格式化轨道.

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

所有这些磁盘I/O服务都使用与上面列出的相同的参数,但是,与服务一样05h,其中一些可能会被忽略.在线搜索中断指南以获取更多详细信息.例如,这是ROM BIOS磁盘I/O服务的完整列表.而这里是另一个.Peter Norton的上述指南也非常出色,如果你能找到一个躺在某处的老版本,比如亚马逊

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


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

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

DOS的功能44h是设备I/O控制(IOCTL),所以,你可以AH44h之前调用INT 21h(一个DOS中断).

要格式化,您需要IOCTL用于块设备.块IOCTL函数至少需要DOS 3.2或更高版本(有些版本需要甚至更高版本).它们不仅允许一次访问整个轨道,还支持格式化功能.它们是使用子功能访问的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除了这个页面,我找不到任何在线文档.这些东西早于网络,很少上传到那里.:-(你真的需要一本像高级MS-DOS编程的书,我也没有副本.

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