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=184320 byte=180KB内容完整无误地装载到内存里了。如果运行“make install”,把程序安装到磁盘上,然后用它来启动电脑的话,我们会发现装载过程还是挺花时间的。这证明我们的程序运行正常。画面显示依然没什么变化,但这个程序已经用从软盘读取的数据填满了内存0x08200~0x34fff的地方。