昨天把磁盘的结构搞清楚了,今天搞清楚软盘的细解。
3.5 英寸软盘是旧时代的产物了,只能采用 CHS 方式寻址:
; ========================================================================================
; 3.5英寸软盘的 CHS 参数:
; 80个柱面,柱面编号 0 ~ 79;
; 2个磁头,磁头编号 0、1;
; 每个磁道有 18 个扇区,每个磁道上扇区编号 1 ~ 18;
; 每个扇区可存放 512 字节的数据。
; ----------------------------------------------------------------------------------------
; LBA 与 CHS 的换算:
; NH 表示磁头数,NS 表示每磁道扇区数,C、H、S 表示柱面号、磁头号和扇区号
; LBA 表示逻辑扇区号
; div 表示整除求商,mod 表示整除求余
; 则由:LBA = ( NH × C + H ) × NS + S - 1
; 推算出:C = ( LBA div NS ) div NH,H = ( LBA div NS ) mod NH,S = ( LBA mod NS ) + 1
; ----------------------------------------------------------------------------------------
; 对 3.5 英寸软盘而言,NH = 2,NS = 18,则:
; C = LBA div 36,H = ( LBA div 18) mod 2,S = ( LBA mod 18) + 1
; ****************************************************************************************
系统 BIOS 提供了对磁盘读写操作的相关中断:
; ========================================================================================
; int 13h(直接磁盘服务)功能表
; ----------------------------------------------------------------------------------------
; 1、磁盘系统复位
; 入口参数:AH = 00H
; DL = 需要进行复位的驱动器号:00H ~ 7FH 为软驱(00h 软驱 A,01h 软驱 B ……)
; 80H ~ FFH 为硬盘(80h 硬盘 C,81h 硬盘 D ……)
; 出口参数:CF = 0 —— 操作成功,AH = 00H;
; 否则,AH = 状态代码,其定义如下:
; 00H — 无错
; 01H — 非法命令
; 02H — 地址目标未发现
; 03H — 磁盘写保护(软盘)
; 04H — 扇区未发现
; 05H — 复位失败(硬盘)
; 06H — 软盘取出(软驱)
; 07H — 错误的参数表(硬盘)
; 08H — DMA(Direct Memory Access)越界(软盘)
; 09H — DMA 超过 64K 界限
; 0AH — 错误的扇区标志(硬盘)
; 0BH — 错误的磁道标志(硬盘)
; 0CH — 介质类型未发现(软盘)
; 0DH — 格式化时非法扇区号(硬盘)
; 0EH — 控制数据地址目标被发现(硬盘)
; 0FH — DMA 仲裁越界(硬盘)
; 10H — 不正确的 CRC(Cyclic Redundancy Check code)
; 或 ECC(Error Checking & Correcting code)编码
; 11H — ECC 校正数据错(硬盘)
; 20H — 控制器失败
; 40H — 查找失败
; 80H — 磁盘超时(未响应)
; AAH — 驱动器未准备好(硬盘)
; BBH — 未定义的错误(硬盘)
; CCH — 写错误(硬盘)
; E0H — 状态寄存器错(硬盘)
; FFH — 检测操作失败(硬盘)
; ----------------------------------------------------------------------------------------
; 2、读、写 CHS 扇区
; 入口参数:AH = 功能号:02H 读扇区、03H 写扇区
; AL = 需要进行操作的扇区个数,需要进行操作的全部扇区必须在同一条磁道内
; CH = 柱面号
; CL = 起始扇区号
; DH = 磁头号
; DL = 驱动器号:00H ~ 7FH 为软驱(00h 软驱 A,01h 软驱 B ……)
; 80H ~ FFH 为硬盘(80h 硬盘 C,81h 硬盘 D ……)
; ES : BX = 存放数据的内存缓冲区地址
; 出口参数:CF = 0 —— 操作成功,AH = 00H,AL = 实际完成操作的扇区个数;
; 否则,AH = 状态代码,参见上面的说明。
; ****************************************************************************************
好了,准备工作都完成了,现在可以直接读写3.5英寸软盘了。由于 int 0x13 中断提供的读写操作不能跨越磁道,连续读两个扇区有可能导致跨越扇区的错误,写一个只读一个扇区操作。很简单,照着上面的公式计算就行:
; ----------------------------------------------------------------------------------------
; 函数功能:从软盘读取 1 个逻辑扇区
; 入口参数:ax = 逻辑扇区号
; es : bx = 存放数据的内存缓冲区地址
; 出口参数:同 ah = 2、int 0x13
Read1Sector:
push bp
mov bp, sp
push dx
push cx
; 由 LBA 计算 CHS
mov dl, 18
div dl
mov ch, al
mov dh, al
mov cl, ah
shr ch, 1
inc cl
and dh, 1
; 读一个扇区
mov ax, 0x0201
xor dl, dl
int 0x13
.Return:
pop cx
pop dx
mov sp, bp
pop bp
ret