
























在8086汇编中,磁盘操作主要通过int 13h(BIOS磁盘服务中断)实现,涉及软盘、硬盘的读写、状态查询等功能。下面我们学习模拟int 13h核心功能的自定义磁盘操作中断程序,支持磁盘复位、扇区读写、状态获取等基础功能,基于3.25英寸软盘实现。
; 常量定义(基于1.44MB软盘参数)
SECTORS_PER_TRACK equ 18 ; 每磁道扇区数
HEADS_PER_DISK equ 2 ; 磁头数(面数)
BYTES_PER_SECTOR equ 512 ; 每扇区字节数
DISK_STATUS_PORT equ 03F6h ; 磁盘状态端口(模拟)
DISK_DATA_PORT equ 03F5h ; 磁盘数据端口(模拟)
DISK_CMD_PORT equ 03F7h ; 磁盘命令端口(模拟)
STATUS_OK equ 00h ; 操作成功状态
STATUS_ERR equ 01h ; 操作失败状态
code segment
assume cs:code, ds:data
; 磁盘操作中断服务程序(入口:AH=功能号)
; 功能:
; AH=00h:磁盘复位(初始化磁盘控制器)
; AH=02h:读扇区(AL=扇区数,CH=柱面号,CL=扇区号,DH=磁头号,DL=驱动器号;ES:BX=缓冲区)
; AH=03h:写扇区(参数同读扇区)
; AH=01h:获取上次操作状态(返回AH=状态码)
disk_int proc far
push ax
push bx
push cx
push dx
push si
push di
push es
push ds ; 保存所有寄存器
push bp
mov bp, sp
; 根据功能号跳转处理
cmp ah, 00h
je disk_reset ; 磁盘复位
cmp ah, 01h
je get_disk_status ; 获取状态
cmp ah, 02h
je read_sector ; 读扇区
cmp ah, 03h
je write_sector ; 写扇区
jmp int_end ; 不支持的功能
; 功能00h:磁盘复位
; 操作:初始化磁盘控制器,重置状态
disk_reset:
; 向命令端口发送复位命令(假设命令00h)
mov al, 00h
out DISK_CMD_PORT, al
; 等待复位完成(轮询状态端口,bit7=1表示就绪)
wait_reset:
in al, DISK_STATUS_PORT
test al, 80h
jz wait_reset ; 未就绪则继续等待
mov [last_status], STATUS_OK ; 复位成功
jmp int_end
; 功能01h:获取上次操作状态
; 返回:AH=状态码(0=成功,1=失败)
get_disk_status:
mov ah, [last_status]
jmp int_end
; 功能02h:读扇区
; 入口参数:
; AL=要读取的扇区数,CH=柱面号,CL=起始扇区号,DH=磁头号(0-1),DL=驱动器号(0=A盘)
; ES:BX=接收数据的缓冲区
; 返回:CF=0表示成功,AH=0;CF=1表示失败,AH=错误码
read_sector:
; 检查参数合法性
cmp dh, HEADS_PER_DISK ; 磁头号是否超出范围(0-1)
jge read_err
cmp cl, SECTORS_PER_TRACK ; 扇区号是否超出范围(1-18)
jg read_err
cmp al, 0 ; 扇区数不能为0
je read_err
; 模拟读操作:向命令端口发送读命令(假设命令02h)
mov al, 02h
out DISK_CMD_PORT, al
; 发送参数(柱面、扇区、磁头)
mov al, ch
out DISK_DATA_PORT, al ; 柱面号
mov al, cl
out DISK_DATA_PORT, al ; 扇区号
mov al, dh
out DISK_DATA_PORT, al ; 磁头号
; 等待操作完成(轮询状态端口,bit0=0表示无错误)
wait_read:
in al, DISK_STATUS_PORT
test al, 01h
jnz wait_read ; 操作未完成则等待
; 读取数据(每扇区512字节,循环读取AL个扇区)
mov si, 0 ; 扇区计数
read_loop:
push cx
mov cx, BYTES_PER_SECTOR / 2 ; 每次读2字节(简化)
read_byte:
in ax, DISK_DATA_PORT ; 从数据端口读2字节
mov es:[bx], ax
add bx, 2
loop read_byte
pop cx
inc si
cmp si, al ; 是否读完所有扇区
jl read_loop
mov [last_status], STATUS_OK ; 读成功
clc ; 清除进位标志(表示成功)
jmp int_end
read_err:
mov [last_status], STATUS_ERR ; 读失败
stc ; 设置进位标志(表示失败)
jmp int_end
; 功能03h:写扇区
; 入口参数:同读扇区(ES:BX=待写数据缓冲区)
; 返回:CF=0表示成功,AH=0;CF=1表示失败,AH=错误码
write_sector:
; 检查参数合法性(同读扇区)
cmp dh, HEADS_PER_DISK
jge write_err
cmp cl, SECTORS_PER_TRACK
jg write_err
cmp al, 0
je write_err
; 模拟写操作:向命令端口发送写命令(假设命令03h)
mov al, 03h
out DISK_CMD_PORT, al
; 发送参数(柱面、扇区、磁头)
mov al, ch
out DISK_DATA_PORT, al
mov al, cl
out DISK_DATA_PORT, al
mov al, dh
out DISK_DATA_PORT, al
; 等待控制器就绪
wait_write:
in al, DISK_STATUS_PORT
test al, 80h
jz wait_write ; 未就绪则等待
; 写入数据(每扇区512字节,循环写入AL个扇区)
mov si, 0
write_loop:
push cx
mov cx, BYTES_PER_SECTOR / 2
write_byte:
mov ax, es:[bx] ; 从缓冲区取2字节
out DISK_DATA_PORT, ax ; 写入数据端口
add bx, 2
loop write_byte
pop cx
inc si
cmp si, al
jl write_loop
mov [last_status], STATUS_OK ; 写成功
clc ; 清除进位标志
jmp int_end
write_err:
mov [last_status], STATUS_ERR ; 写失败
stc ; 设置进位标志
jmp int_end
; 中断结束:恢复寄存器并返回
int_end:
pop bp
pop ds
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret ; 中断返回
disk_int endp
; 安装自定义磁盘中断向量(替换int 13h)
install proc
cli ; 关中断,防止安装冲突
mov ax, 0
mov es, ax ; ES指向中断向量表(0段)
mov di, 13h*4 ; int 13h向量地址:13h×4=0000:004C
mov ax, offset disk_int ; 中断服务程序偏移地址
stosw ; 写入偏移量
mov ax, cs ; 中断服务程序段地址
stosw ; 写入段地址
sti ; 开中断
ret
install endp
; 主程序:测试磁盘操作功能
main:
mov ax, data
mov ds, ax ; 初始化数据段
call install ; 安装磁盘中断
; 测试1:磁盘复位
mov ah, 00h
mov dl, 0 ; 驱动器A:
int 13h
; 测试2:读扇区(读A盘0柱面,1扇区,0磁头,1个扇区到缓冲区)
mov ah, 02h
mov al, 1 ; 读1个扇区
mov ch, 0 ; 柱面0
mov cl, 1 ; 扇区1
mov dh, 0 ; 磁头0
mov dl, 0 ; 驱动器A:
mov bx, offset disk_buf ; 缓冲区地址(ES=DS)
mov es, ds
int 13h
; 测试3:获取操作状态并显示(成功显示'0',失败显示'1')
mov ah, 01h
int 13h
add ah, 30h ; 转换为ASCII
mov dl, ah
mov ah, 02h
int 21h ; 调用DOS中断显示
jmp $ ; 暂停程序
code ends
; 数据段:保存磁盘状态和缓冲区
data segment
last_status db STATUS_OK ; 上次操作状态
disk_buf db BYTES_PER_SECTOR dup(0) ; 磁盘缓冲区(512字节)
data ends
end main此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。