
好的,以下是通过直接访问硬盘 I/O 端口进行硬盘控制的详细完整内容,包括 I/O 端口结构表、寄存器的作用及使用方法,以及具体的操作步骤。这将帮助您理解如何在不使用 BIOS 中断的情况下进行硬盘的低级读写操作。
硬盘 I/O 端口结构表(主 IDE 通道)
硬盘控制器在主 IDE 通道上拥有一组固定的 I/O 端口,用于实现硬盘的底层操作。以下是这些端口的详细结构。
| 端口地址 | 寄存器名称 | 位宽 | 读/写 | 作用描述 | 
|---|---|---|---|---|
0x1F0 | 
数据寄存器 | 16 位 | 读/写 | 用于数据传输,每次传输 16 位(2 字节)。 | 
0x1F1 | 
错误/特征寄存器 | 8 位 | 读/写 | 读模式下为错误寄存器,写模式下为特征寄存器,配置硬盘操作特性。 | 
0x1F2 | 
扇区计数寄存器 | 8 位 | 读/写 | 指定要读/写的扇区数量。0 表示 256 个扇区。 | 
0x1F3 | 
LBA 地址低 8 位 | 8 位 | 读/写 | 指定 LBA 地址的低 8 位。 | 
0x1F4 | 
LBA 地址中间 8 位 | 8 位 | 读/写 | 指定 LBA 地址的中间 8 位。 | 
0x1F5 | 
LBA 地址高 8 位 | 8 位 | 读/写 | 指定 LBA 地址的高 8 位。 | 
0x1F6 | 
驱动器/头寄存器 | 8 位 | 读/写 | 用于选择驱动器和磁头,以及 LBA 地址的 24-27 位。 | 
0x1F7 | 
命令/状态寄存器 | 8 位 | 读/写 | 读模式下为状态寄存器,写模式下为命令寄存器。 | 
辅助控制端口
| 端口地址 | 寄存器名称 | 位宽 | 读/写 | 作用描述 | 
|---|---|---|---|---|
0x3F6 | 
驱动器控制寄存器 | 8 位 | 写 | 控制硬盘的复位、禁用中断等操作。 | 
0x3F6 | 
驱动器地址寄存器 | 8 位 | 读 | 读取当前驱动器状态。 | 
各寄存器的功能说明
数据寄存器(
0x1F0):- 用于硬盘和 CPU 之间的数据传输,读操作时从此端口读取数据,写操作时将数据写入此端口。
 
错误/特征寄存器(
0x1F1):- 读模式:显示上次命令的错误信息,包括坏块(BB)、命令被中止(ABRT)等。
 - 写模式:配置硬盘特性,指定一些操作参数。
 
扇区计数寄存器(
0x1F2):- 用于指定本次读/写操作的扇区数量。写入 
0表示操作 256 个扇区。 
- 用于指定本次读/写操作的扇区数量。写入 
 LBA 地址寄存器(
0x1F3-0x1F5):- 用于指定要访问的 LBA 地址,分别为低 8 位、中 8 位和高 8 位。
 
驱动器/头寄存器(
0x1F6):- 位 6:设置为 
1表示使用 LBA 模式。 - 位 5:选择驱动器,0 表示主盘,1 表示从盘。
 - 位 0-3:存放 LBA 地址的 24-27 位。

 
- 位 6:设置为 
 命令/状态寄存器(
0x1F7):- 读模式:提供硬盘状态信息,包括忙碌(BSY)、数据请求(DRQ)等状态。
 - 写模式:用于发送命令给硬盘,例如 
0x20表示读命令,0x30表示写命令。
 
辅助控制端口(
0x3F6):- 控制硬盘的复位、中断禁用等操作。
 
硬盘读写操作步骤
通过 I/O 端口控制硬盘的操作主要包括读和写两个步骤,以下是这两个操作的详细流程:
读取扇区操作
- 等待硬盘空闲:读取 
0x1F7状态寄存器的BSY位,等待该位清零,表示硬盘空闲。 - 指定扇区数量:将要读取的扇区数写入 
0x1F2扇区计数寄存器。 - 设置 LBA 地址:依次向 
0x1F3、0x1F4和0x1F5写入 LBA 地址的低、中、高字节,将 LBA 的高 4 位写入0x1F6驱动器/头寄存器。 - 选择驱动器并发出读命令:在 
0x1F7中写入0x20(读命令)。 - 等待数据准备:读取 
0x1F7中的DRQ位,等待该位被置位,表示数据准备就绪。 - 读取数据:从 
0x1F0数据寄存器读取数据,每次读取 2 字节(16 位),直到读取完指定的扇区数。 
示例代码:读取一个扇区
以下是汇编代码示例,从硬盘读取一个扇区数据到指定内存位置:
mov dx, 0x1F6 ; 设置驱动器和头mov al, 0xE0 ; LBA 模式,选择主盘out dx, almov dx, 0x1F2 ; 设置扇区计数mov al, 1 ; 读取一个扇区out dx, almov dx, 0x1F3 ; 设置 LBA 低字节mov al, LBA_low ; LBA 地址的低 8 位out dx, almov dx, 0x1F4 ; 设置 LBA 中字节mov al, LBA_mid ; LBA 地址的中 8 位out dx, almov dx, 0x1F5 ; 设置 LBA 高字节mov al, LBA_high ; LBA 地址的高 8 位out dx, almov dx, 0x1F7 ; 写入读命令mov al, 0x20 ; 读命令out dx, al.wait_drq:in al, dx ; 检查 DRQ 位test al, 0x08 ; 检查 DRQ 位jz .wait_drq ; 如果 DRQ 未置位,等待mov dx, 0x1F0 ; 读取数据in ax, dx ; 从数据端口读取 16 位
写入扇区操作
- 等待硬盘空闲:读取 
0x1F7,检查BSY位是否清零。 - 指定扇区数量:将要写入的扇区数写入 
0x1F2。 - 设置 LBA 地址:依次向 
0x1F3、0x1F4和0x1F5写入 LBA 地址,将 LBA 的高 4 位写入0x1F6。 - 选择驱动器并发出写命令:向 
0x1F7写入0x30(写命令)。 - 等待数据请求:读取 
0x1F7中的DRQ位,等待数据请求信号。 - 写入数据:向 
0x1F0数据寄存器写入数据,每次写入 2 字节,直到写入完指定的扇区数。 
总结
通过直接访问硬盘 I/O 端口,可以在不调用 BIOS 中断的情况下
直接进行硬盘控制。主要的寄存器包括数据传输、错误检测、扇区计数和地址控制等。读写操作依赖于状态寄存器的 BSY 和 DRQ 位来同步硬盘的状态。掌握这些步骤后,可以在操作系统开发或嵌入式系统中灵活地实现硬盘的底层读写操作。
