Content #
LBA28使用28个比特表示逻辑扇区号,共可以管理128GB的硬盘。
个人计算机上的主硬盘控制器被分配了8位端口,端口号从0x1f0到0x1f7。
从硬盘上读逻辑扇区 #
设置要读取的扇区数量 #
数量写入0x1f2端口,这是个8位端口,因此每次只能读写255个扇区。
mov dx, 0x1f2
mov al, 0x1 ;1个扇区
out dx, al
如果写入的值为0,则表示读取256个扇区。
设置起始LBA扇区号 #
扇区读写是连续的,只要设定好第一个扇区的编号即可。28位扇区号,按从低到高,分别写入端口0x1f3, 0x1f4, 0x1f5, 0x1f6。
mov dx, 0x1f3
mov al, 0x02 ;起始扇区号为0x02
out dx, al ;7~0
inc dx
mov al, 0x00
out dx, al ;15~8
inc dx
out dx, al ;23~16
inc dx ;0x1f6
mov al, 0xe0 ;LBA模式
out dx, al
0x1f6端口的含义如下图所示:
高3位是111,表示LBA模式。
请求硬盘读 #
mov dx, 0x1f7
mov al, 0x20 ;读命令
out dx, al
等待读写操作完成 #
0x1f7端口即是命令端口,也是状态端口。向这个端口发送读写命令之后,硬盘就会把0x1f7端口的第7位设为1,表示自己很忙。一旦数据准备完成,第7位会被重新置0,同时,第3位会被置1,表示数据准备好了。

mov dx, 0x1f7
waits:
in al, dx
and al, 0x88
cmp al, 0x08
jnz waits
0x88的二进制为10001000,表示只取出al中的第3位与第7位。
取出数据 #
0x1f0是16位的数据端口。下面的代码从硬盘读取256字节,放到DS指定的数据段,偏移地址由BX指定。
mov cx, 256
mov dx, 0x1f0
readw:
in ax, dx
mov [bx], ax
add bx, 2
loop readw