惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
Google Online Security Blog
Google Online Security Blog
月光博客
月光博客
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
The Cloudflare Blog
Blog — PlanetScale
Blog — PlanetScale
F
Full Disclosure
G
Google Developers Blog
罗磊的独立博客
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
A
About on SuperTechFans
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
GbyAI
GbyAI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
The Register - Security
The Register - Security
U
Unit 42
D
Docker
Martin Fowler
Martin Fowler
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
博客园_首页
Google DeepMind News
Google DeepMind News

faryou的博客

5月月考 - faryou的博客 - 日记 faryou的博客-五一回老家 【汇编 - 功能】中断安装中断实现 【汇编&硬件】时钟中断的具体实现 faryou的博客-这些年,我不再看《熊出没》 【汇编&硬件】关机中断的具体实现 【汇编&硬件】网络连接相关中断的具体实现 faryou的博客-年初小记 【汇编&硬件】鼠标控制中断的具体实现 【汇编&硬件】声音输出中断的具体实现 【汇编&硬件】屏幕输出中断的具体实现 【汇编&硬件】键盘读取中断的具体实现 【汇编】汇编环境的搭建及Debug的使用教程 【汇编】漫谈:学习汇编后的一些思考 faryou的博客-关于本站即日起实行“一站三体”运营制度 【汇编基础教程】完结篇 写在最后:前言 【汇编基础教程】使用BIOS的中断实现键盘输入及磁盘I/O 【汇编基础教程】中断 【汇编基础教程】端口 【汇编基础教程】标志寄存器 【汇编基础教程】再谈栈 【汇编基础教程】段 【汇编基础教程】来存一些数据! 【汇编基础教程】寄存器和内存&一些基本命令的说明 【汇编基础教程】来写个“函数” 【汇编基础教程】更灵活的定位内存 【汇编基础教程】理解一下[bx]和loop指令 【汇编基础教程】跳一跳! faryou的博客-我的竞赛经历&对人生的一些思考 faryou的博客-关于现在中小学计算机课的一些想法及思考 faryou的博客-2025年度总结 faryou的博客-临平山下十五年 faryou的博客-Windows 10即将停止支持,谈谈自己从小到大用电脑的感受 faryou的博客-谈谈一名10后的怀旧情怀 【汇编基础教程】8086CPU工作原理 【C语言】指针的理解与应用 【算法教程】【C/C++】DP(动态规划):区间DP——程序设计思路与代码实现 【算法教程】【C/C++】BFS(广度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】DFS(深度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】单源最短路径——程序设计思路与代码实现 【算法教程】【C/C++】最小生成树——程序设计思路与代码实现 【算法教程】【C/C++】并查集——程序设计思路与代码实现 【算法教程】【C/C++】DP(动态规划):背包DP——程序设计思路与代码实现 【算法教程】【C/C++】DP(动态规划):简单动规问题——程序设计思路与代码实现 【算法教程】【C/C++】递推——程序设计思路与代码实现 【算法教程】【C/C++】三分算法——程序设计思路与代码实现 【算法教程】【C/C++】二分答案——程序设计思路与代码实现 【算法教程】【C/C++】二分查找——程序设计思路与代码实现 【算法教程】【C/C++】贪心算法——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:快排——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:快速幂——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:进制转换——程序设计思路与代码实现 一文弄懂C++中的自定义函数 faryou的博客-2024年度总结
【汇编&硬件】磁盘读取中断的具体实现
作者: faryou · 2026-02-22 · via faryou的博客

前言

在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

代码说明

  1. 硬件抽象:基于1.44MB软盘的参数(每磁道18扇区、2磁头、每扇区512字节),模拟磁盘控制器的端口(状态、数据、命令端口),简化真实磁盘的硬件交互逻辑。
  2. 核心功能:a.磁盘复位:初始化控制器,重置状态,确保后续操作可用。b.读/写扇区:通过端口发送操作命令和参数(柱面、扇区、磁头),从数据端口读写数据,支持多扇区操作。c.状态查询:返回上次操作的结果(成功/失败),辅助判断操作是否有效。
  3. 中断安装:修改中断向量表中int 13h的入口地址,指向自定义服务程序,安装时关中断( cli )防止被其他中断干扰。
  4. 测试逻辑:主程序依次测试磁盘复位、读扇区和状态查询,并通过DOS中断显示操作结果(0表示成功,1表示失败)。