对硬盘进行操作的常用端口是1f0h~1f7h号端口,各端口含义如下:
端口号 读还是写 具体含义
1F0H 读/写 用来传送读/写的数据(其内容是正在传输的一个字节的数据)
1F1H 读 用来读取错误码
1F2H 读/写 用来放入要读写的扇区数量
1F3H 读/写 用来放入要读写的扇区号码
1F4H 读/写 用来存放读写柱面的低8位字节
1F5H 读/写 用来存放读写柱面的高2位字节(其高6位恒为0)
1F6H 读/写 用来存放要读/写的磁盘号及磁头号
第7位 恒为1
第6位 恒为0
第5位 恒为1
第4位 为0代表第一块硬盘、为1代表第二块硬盘
第3~0位 用来存放要读/写的磁头号
1f7H 读 用来存放读操作后的状态
第7位 控制器忙碌
第6位 磁盘驱动器准备好了
第5位 写入错误
第4位 搜索完成
第3位 为1时扇区缓冲区没有准备好
第2位 是否正确读取磁盘数据
第1位 磁盘每转一周将此位设为1,
第0位 之前的命令因发生错误而结束
写 该位端口为命令端口,用来发出指定命令
为50h 格式化磁道
为20h 尝试读取扇区
为21h 无须验证扇区是否准备好而直接读扇区
为22h 尝试读取长扇区(用于早期的硬盘,每扇可能不是512字节,而是128字节到1024之间的值)
为23h 无须验证扇区是否准备好而直接读长扇区
为30h 尝试写扇区
为31h 无须验证扇区是否准备好而直接写扇区
为32h 尝试写长扇区
为33h 无须验证扇区是否准备好而直接写长扇区
注:当然看完这个表你会发现,这种读写端口的方法其实是基于磁头、柱面、扇区的硬盘读写方法,不过大于8G的硬盘的读写方法也是通过端口1F0H~1F7H来实现的^_^
一个通过对硬盘输入输出端口操作来读写硬盘的实例
让我们来看一个关于INT13H读写硬盘程序实例。在例子中详细说明了硬盘的读写操作所用到的端口,并且把通过INT13H读出的主引导区得到的数据和通过输入输出读主引导区得到的数据进行比较,从而证实这两种操作功能相同,程序片段如下:
mov dx,1f6h ; 要读入的磁盘号及磁头号
mov al,0a0h ;磁盘0,磁头0
out dx,al
mov dx,1f2h ;要读入的扇区数量
mov al,1 ;读一个扇区
out dx,al
mov dx,1f3h ;要读的扇区号
mov al,1 ;扇区号为1
out dx,al
mov dx,1f4h ;要读的柱面的低8位
mov al,0 ; 柱面低8位为0
out dx,al
mov dx,1f5h ; 柱面高2位
mov al,0 ; 柱面高2位为0(通过1F4H和1F5H端口我们可以确定
; 用来读的柱面号是0)
out dx,al
mov dx,1f7h ;命令端口
mov al,20h ; 尝试读取扇区
out dx,al
still_going:
in al,dx
test al,8 ;扇区缓冲是否准备好
jz still_going ;如果扇区缓冲没有准备好的话则跳转,直到准备好才向下执行。
mov cx,512/2 ;设置循环次数(512/2次)
mov di,offset buffer
mov dx,1f0h ;将要传输的一个字节的数据
rep insw ;传输数据
; ------
mov ax,201h ;以下是用INT13H读硬盘的0磁头、0柱面、1扇区
mov dx,80h
mov cx,1
mov bx,offset buffer2
int 13h
mov cx,512 ;以下部分用来比较2种方法读出的硬盘数据
mov si,offset buffer
mov di,offset buffer2
repe cmpsb
jne failure
mov ah,9
mov dx,offset readmsg
int 21h
jmp good_exit
failure:
mov ah,9
mov dx,offset failmsg
int 21h
good_exit: ;以下部分用来结束程序
mov ax,4c00h ;退出程序
int 21h
readmsg db 'The buffers match. Hard disk read using ports.$'
failmsg db 'The buffers do not match.$'
buffer db 512 dup ('V')
buffer2 db 512 dup ('L')