4 读入10个柱面
趁热打铁,我们继续学习下面的内容。C0-H0-S18扇区的下一扇区,是磁盘反面的C0-H1-S1,这次也从0xa400读入吧。按顺序读到C0-H1-S18后,接着读下一个柱面C1-H0-S1。我们保持这个势头,一直读到C9-H1-S18好了。现在我们就来看一看projects/03_day下的harib00d内容。
本次添加的部分
;读磁盘
MOV AX,0x0820
MOV ES,AX
MOV CH,0 ; 柱面0
MOV DH,0 ; 磁头0
MOV CL,2 ; 扇区2
readloop:
MOV SI,0 ; 记录失败次数的寄存器
retry:
MOV AH,0x02 ; AH=0x02 : 读入磁盘
MOV AL,1 ; 1个扇区
MOV BX,0
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS
JNC next ; 没出错时跳转到next
ADD SI,1 ; SI加1
CMP SI,5 ; 比较SI与5
JAE error ; SI >= 5时,跳转到error
MOV AH,0x00
MOV DL,0x00 ; A驱动器
INT 0x13 ; 重置驱动器
JMP retry
next:
MOV AX,ES ; 把内存地址后移0x200
ADD AX,0x0020
MOV ES,AX ; 因为没有ADD ES,0x020指令,所以这里稍微绕个弯
ADD CL,1 ; CL加1
CMP CL,18 ; 比较CL与18
JBE readloop ; 如果CL <= 18,则跳转至readloop
MOV CL,1
ADD DH,1
CMP DH,2
JB readloop ; 如果DH < 2,则跳转到readloop
MOV DH,0
ADD CH,1
CMP CH,CYLS
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的地方。