一个操作系统的设计与实现——第9章 硬盘驱动

发布时间 2023-11-12 09:51:25作者: 樱雨楼

操作系统应当具备读写硬盘的能力。因此,本章将要实现的是硬盘驱动。硬盘驱动由两个函数构成:读硬盘函数与写硬盘函数。

9.1 读硬盘

想要读硬盘,就需要提供以下三个信息:

  1. 起始扇区号
  2. 读取的扇区数
  3. 数据存储的地址

需要注意的是:读取的扇区数只能是一个8字节的整数。

由于读硬盘需要使用大量的端口读写指令,所以,该函数使用汇编语言实现。

请看本章代码9/HD.h

第5行,声明了读硬盘函数。

接下来,请看本章代码9/HD.s

第1行,将编译模式设定为32位。

第3行,将读硬盘函数hdRead声明为外部链接的。

第13~15行,将读取的扇区数写入0x1f2端口。hdRead函数使用栈传参,sectorCount是第三个参数,故其在栈中的位置是[ebp + 16]

第17~32行,将起始扇区号写入0x1f3~0x1f6端口。startSectorhdRead函数的第二个参数,故其在栈中的位置是[ebp + 12]

第34~36行,将读硬盘命令0x20写入0x1f7端口。

第38~43行,等待硬盘准备就绪。

第46~47行,计算循环的总次数。一个扇区是512字节,insw指令一次处理2字节,所以,每读一个扇区,就需要256次循环。循环的总次数等于读取的扇区数左移8位。

第48行,从栈中取得数据存储的地址。tarPtrhdRead函数的第一个参数,故其在栈中的位置是[ebp + 8]

第49行,将硬盘中的数据读出。

9.2 写硬盘

写硬盘与读硬盘在实现上仅有以下不同:

  1. 写硬盘命令是0x30
  2. 当硬盘准备就绪后,需要向0x1f0端口连续写入数据

请看本章代码9/HD.h

第6行,声明了写硬盘函数。

接下来,请看本章代码9/HD.s

第58~82行,与hdRead函数一致。

第84~86行,将写硬盘命令0x30写入0x1f7端口。

第88~97行,与hdRead函数一致。

第98行,从栈中取得数据存储的地址。

第99行,将数据写入硬盘。

接下来,请看本章代码9/Makefile

第5行,将HD.s编译成ELF文件。

第6行,将HD.o文件添加到链接器。

9.3 测试

本章代码9/Kernel.c用于测试两个硬盘驱动函数。