5. 硬盘的访问(重点)
PATA/SATA接口中的数据端口是16位的,读写硬盘的基本单位是字扇区(硬盘是典型的块设备,不能仅读写扇区中的某一个字节)。读写硬盘可以有两种方式,一种是CHS模式(即向硬盘控制器分别发送磁头号,柱面号和扇区号),另一种就是LBA模式,所谓LBA模式,其实就是将磁头号,柱面号和扇区号统一编号,LBA的计算方法是:
LBA号=C*磁头总数*每道扇区数+H*每道扇区数+(S-1)
早期LBA采用28个比特来表示逻辑扇区号(LBA28),从逻辑扇区(0x0000000~0xFFFFFFF),一共可以表示228个比特,每个扇区可以有512个字节,所以LBA28可以管理128GB的硬盘。现在普遍采用的是LBA48,采用48个比特来表示逻辑扇区号,这样一来就可以表示131072TB的硬盘了。
教材采用的是LBA28访问硬盘(因为讲的是实模式)。
第一步:设置要读取的扇区数量(操作端口0x1f2),这个数值要写入0x1f2端口,这是个8位的端口,因此每次最多读写255个扇区。
如果对0x1f2端口写入0,那么就表示要读取256个扇区,每读取一个扇区,这个数值就会减1,如果读写的过程中发生错误,那么这个端口就包含这尚未读取的硬盘数。
第二步:设置起始LBA扇区号(操作端口0x1f3-0x1f7),扇区的读写是连续的,所以只要给出第一个扇区的编号就可以读取所有的扇区了,28个扇区号将会被分成4段(每个段8位),分别写入0x1f3-0x1f6端口,其中0x1f3端口存放的是0-7位,
0x1f4端口存放8-15位,0x1f5存放16-23位,0x1f6存放24-27位,最后,0x1f6高4位用来指示是主盘或者是从盘,以及是采用CHS模式还是LBA模式。
第三步:向端口0x1f7写入0x20,请求端口读(写入0x30就是请求端口写)
第四步:等待读写操作完成(操作端口0x1f7)。0x1f7既是命令端口,又是状态端口。在硬盘内部操作期间,它会将0x1f7端口的第7位置1,表明硬盘在忙,一旦硬盘准备好了,它再将这个位清零,同时将第三位置1,表明这个时候主机可以向硬盘发送数据或者从硬盘接受数据了。我们可以使用条件转移指令完成这个动作,代码如下:
第五步:连续取出数据(操作端口0x1f0)。0x1f0是硬盘的数据接口,而且这个端口还是16位的,一旦硬盘准备就绪,就可以连续地从这个接口写入或者读取数据了。代码例子如下:
最后,0x1f1是一个错误代码寄存器,里面可以读取硬盘读写错误的原因。
6. 加载用户程序以及用户程序重定位,加载器到用户程序的跳转(重点)