实验2

此次实验的基本内容是:

  1. 阅读《Linux 内核完全注释》的第 6 章,对计算机和 Linux 0.11 的引导过程进行初步的了解;
  2. 按照下面的要求改写 0.11 的引导程序 bootsect.s
  3. 有兴趣同学可以做做进入保护模式前的设置程序 setup.s。

改写 bootsect.s 主要完成如下功能:

  1. bootsect.s 能在屏幕上打印一段提示信息“XXX is booting…”,其中 XXX 是你给自己的操作系统起的名字,例如 LZJos、Sunix 等(可以上论坛上秀秀谁的 OS 名字最帅,也可以显示一个特色 logo,以表示自己操作系统的与众不同。)

改写 setup.s 主要完成如下功能:

  1. bootsect.s 能完成 setup.s 的载入,并跳转到 setup.s 开始地址执行。而 setup.s 向屏幕输出一行”Now we are in SETUP”。
  2. setup.s 能获取至少一个基本的硬件参数(如内存参数、显卡参数、硬盘参数等),将其存放在内存的特定地址,并输出到屏幕上。
  3. setup.s 不再加载 Linux 内核,保持上述信息显示在屏幕上即可。

Bootsect.s 简易版 :::info bootsect被存在第一个扇区内(引导磁盘 0磁道 0磁头 第一个扇区)会由bios程序将其加载到内存0x7c0处,bootsect在执行时会把自己移动到0x90000的地方,然后再加载setup(0磁道第二个扇区)到紧跟着他的后面0x90200(bootsect有512字节) :::

  1. SETUPLEN=2
  2. SETUPSEG=0x07e0 !0x7c00+0200
  3. entry _start
  4. _start:
  5. mov ah,#0x03 !读光标位置
  6. xor bh,bh
  7. int 0x10
  8. mov cx,#36 !传入的字符串长度
  9. mov bx,#0x0007 !页号和属性:BL=07黑白
  10. mov bp,#msg1 !偏移地址
  11. mov ax,#0x07c0 !段地址还是当前
  12. mov es,ax
  13. mov ax,#0x1301 !显示字符串
  14. int 0x10
  15. load_setup:
  16. mov dx,#0x0000 !从0磁道0驱动器读
  17. mov cx,#0x0002 !扇区号2和柱面号(磁道)0
  18. mov bx,#0x0200 !设置读入的内存地址:BOOTSEG+address = 512BX表示偏移512字节
  19. mov ax,#0x0200+SETUPLEN !AL:读入的扇区个数
  20. int 0x13
  21. jnc ok_load_setup !读成功 AH = 00H AL = 读取的扇区数,CF = 0
  22. mov dx,#0x0000
  23. mov ax,#0x0000
  24. int 0x13 !磁盘复位
  25. jmp load_setup
  26. ok_load_setup:
  27. jmpi 0,SETUPSEG
  28. msg1:
  29. .byte 13,10
  30. .ascii "Hello OS world, my name is LZJ"
  31. .byte 13,10,13,10
  32. .org 510
  33. boot_flag:
  34. .word 0xAA55

INT0x10
INT 10H 是由 BIOS 对屏幕及显示器所提供的服务程序,使用 INT 10H 中断服务程序时,先指定 AH 寄存器为下表编号其中之一,该编号表示欲调用的功用,而其他寄存器的详细说明,参考表后文字,当一切设定好之后再调用 INT 10H。
读光标位置:

  •   功能号:AH = 03H
  •   传入参数:BH = 页号
  •   返回参数:
    • CH = 光标起始行
    • CL = 光标结束行
    • DH/DL = 行/列 

显示字符串:

  •   功能号:AH = 13H
  •   输入参数:
    • ES:BP = 字符串地址
    • AL = 写方式(0~3)
    • CX = 字符串长度
    • DH/DL = 起始行/列
    • BH/BL = 页号/属性 :::info int 0x13中断向量所指向的中断服务程序实质上就是磁盘服务程序。
      用途:将指定扇区的代码加载到内存的指定位置。
      因此,在使用int 0x13中断时要将参数传递给服务程序:例如:将指定扇区和加载的内存位置传递给服务程序 :::

INT 0x13
读磁盘扇区:  

  • 功能号:AH = 02H
  • 调用参数:AL = 扇区数
  • CX中的0~5位代表扇区号,CX中的6~15位代表柱面号(其中,CL的6~7为柱面数的高两位,CH存低8位)
  • DH/DL = 磁头号/驱动器号
  • ES:BX = 数据缓冲区地址
  • 返回参数:
    • 读成功 ⇒ AH = 00H, AL = 读取的扇区数,CF = 0
    • 读失败 ⇒ AH = 错误码

磁盘复位:

  • 功能号:AH = 00H
  • 调用参数:DL = 驱动器号 (00H~7FH为软盘;80H~0FFH为硬盘)
  • 返回参数:读成功 ⇒ AH = 00H, CF = 0
  • 读失败 ⇒ AH = 错误码

setup.s 将获得硬件参数放在内存的 0x90000 处。原版 setup.s 中已经完成了光标位置、内存大小、显存大小、显卡参数、第一和第二硬盘参数的保存。
ah=#0x03 调用 0x10中断可以读出光标的位置,用 ah=#0x88调用0x15 中断可以读出内存的大小。有些硬件参数的获取要稍微复杂一些,如磁盘参数表。在 PC 机中 BIOS 设定的中断向量表中 int 0x41的中断向量位置(4*0x41 = 0x0000:0x0104)存放的并不是中断程序的地址,而是第一个硬盘的基本参数表。第二个硬盘的基本参数表入口地址存于 int 0x46中断向量位置处。每个硬盘参数表有 16 个字节大小。