4 读入10个柱面

趁热打铁,我们继续学习下面的内容。C0-H0-S18扇区的下一扇区,是磁盘反面的C0-H1-S1,这次也从0xa400读入吧。按顺序读到C0-H1-S18后,接着读下一个柱面C1-H0-S1。我们保持这个势头,一直读到C9-H1-S18好了。现在我们就来看一看projects/03_day下的harib00d内容。

本次添加的部分

  1. ;读磁盘
  2. MOV AX,0x0820
  3. MOV ES,AX
  4. MOV CH,0 ; 柱面0
  5. MOV DH,0 ; 磁头0
  6. MOV CL,2 ; 扇区2
  7. readloop:
  8. MOV SI,0 ; 记录失败次数的寄存器
  9. retry:
  10. MOV AH,0x02 ; AH=0x02 : 读入磁盘
  11. MOV AL,1 ; 1个扇区
  12. MOV BX,0
  13. MOV DL,0x00 ; A驱动器
  14. INT 0x13 ; 调用磁盘BIOS
  15. JNC next ; 没出错时跳转到next
  16. ADD SI,1 ; SI1
  17. CMP SI,5 ; 比较SI5
  18. JAE error ; SI >= 5时,跳转到error
  19. MOV AH,0x00
  20. MOV DL,0x00 ; A驱动器
  21. INT 0x13 ; 重置驱动器
  22. JMP retry
  23. next:
  24. MOV AX,ES ; 把内存地址后移0x200
  25. ADD AX,0x0020
  26. MOV ES,AX ; 因为没有ADD ES,0x020指令,所以这里稍微绕个弯
  27. ADD CL,1 ; CL1
  28. CMP CL,18 ; 比较CL18
  29. JBE readloop ; 如果CL <= 18,则跳转至readloop
  30. MOV CL,1
  31. ADD DH,1
  32. CMP DH,2
  33. JB readloop ; 如果DH < 2,则跳转到readloop
  34. MOV DH,0
  35. ADD CH,1
  36. CMP CH,CYLS
  37. JB readloop ; 如果CH < CYLS,则跳转到readloop

首先还是说说新出现的指令JB。这也是条件跳转指令,是“jump if below”的缩写。翻译过来就是:“如果小于的话,就跳转。”还有一个新指令,就是在程序开头使用的EQU指令。这相当于C语言的#define命令,用来声明常数。“CYLS EQU 10”意思是“CYLS = 10”。EQU是“equal”的缩写。只将它定义成常数是因为以后我们可能修改这个数字。现在我们先随意定义成10个柱面,以后再对它进行调整(CYLS代表cylinders)。

现在启动区程序已经写得差不多了。如果算上系统加载时自动装载的启动扇区,那现在我们已经能够把软盘最初的10 × 2 × 18 × 512 = 184 320 byte=180KB内容完整无误地装载到内存里了。如果运行“make install”,把程序安装到磁盘上,然后用它来启动电脑的话,我们会发现装载过程还是挺花时间的。这证明我们的程序运行正常。画面显示依然没什么变化,但这个程序已经用从软盘读取的数据填满了内存0x08200~ 0x34fff的地方。