您的位置:首页 > 编程语言 > C语言/C++

30天自制操作系统-第3天-harib00b-注释

2017-07-19 14:21 169 查看
程序中的行55的执行的3种情况:

A是如果读取磁盘顺利,第一次就读取成功,那么就会进入fin语句块,如果PC机有动作唤醒了CPU,那么就继续往下执行,由于error是跳转语句块,所以这里不会执行error语句块(如果没有跳转error的指令就不会执行error语句块),所以此时SI仍然等于0,那么就进入putloop语句块,由于SI不等于msg,[SI]的值应该是0,所以AL等于0,那么就会跳回到fin语句块,也就不会在显示屏上显示内容(msg语句块对应的内容),如果PC机有动作唤醒了CPU,那么就继续往下执行(语句84~86),结束启动程序。

B是如果读取磁盘出错,但是在5次以内读取磁盘成功,那么SI就等于(1~5)中的一个值,然后就会进入fin语句块,如果PC机有动作唤醒了CPU,那么就继续往下执行,由于error是跳转语句块,所以这里不会执行error语句块,所以此时SI仍然等于(1~5)中的一个值,那么就进入putloop语句块,由于SI不等于msg,[SI]的值应该是0,所以AL等于0,那么就会跳回到fin语句块,也就不会在显示屏上显示内容(msg语句块对应的内容),如果PC机有动作唤醒了CPU,那么就继续往下执行(语句84~86),结束启动程序。

C是如果读取磁盘5次后仍然出错,那么就会进入error语句块,在error语句块中把msg的值赋给SI,由于只有JMP指令在执行跳转语句块之后还会回到原来的JMP指令的语句处继续往下执行,现在的JAE指令跳转到error语句块之后就不会再跳回JAE指令的语句处,而是在error语句块的下面继续执行,那么此时就会进入putloop语句块,由于SI等于msg,所以putloop语句块就会经过多次循环在显示屏上显示内容(msg语句块对应的内容),显示完内容之后就会跳转到fin语句块,如果PC机有动作唤醒了CPU,那么就继续往下执行(语句84~86),结束启动程序。

注意:跳转指令中,只有JMP指令在执行完跳转语句块之后还会回到原来的JMP指令的语句处继续往下执行,其它的跳转指令(比如JNC指令、JAE指令)跳转到指定的语句块之后就不会再跳回该跳转指令的语句处,而是指定的语句块的下面继续执行。

下面是程序及其注释:

; haribote-ipl
; TAB=4

ORG 0x7c00 ; 指明程序的装载地址

; 以下这段是标准FAT12格式软盘专用的代码

JMP entry ; 启动IPL
DB 0x90 ; 启动IPL之后,就可以设置下面的属性
DB "HARIBOTE" ; 启动区的名称可以是任意的字符串(8字)
DW 512 ; 每个扇区(sector)的大小(必须为512字节)
DB 1 ; 簇(cluster)的大小(必须为1个扇区)
DW 1 ; FAT的起始位置(一般从第一个扇区开始)
DB 2 ; FAT的个数(必须为2)
DW 224 ; 根目录的大小(一般设成224项)
DW 2880 ; 该磁盘的大小(必须是2880扇区)
DB 0xf0 ; 磁盘的种类(必须是0xf0)
DW 9 ; FAT的长度(必须是9扇区)
DW 18 ; 1个磁道(track)有几个扇区(必须是18)
DW 2 ; 磁头数(必须是2)
DD 0 ; 不使用分区,必须是0
DD 2880 ; 重写一次磁盘大小
DB 0,0,0x29 ; 意义不明,固定
DD 0xffffffff ; (可能是)卷标号码
DB "HARIBOTEOS " ; 磁盘的名称(11字节)
DB "FAT12 " ; 磁盘格式名称(8字节)
RESB 18 ; 先空出18字节

; 程序核心

entry: ; 初始化一些寄存器
MOV AX,0 ; 初始化寄存器; 让累加寄存器AX的初始值为0
MOV SS,AX ; 让栈段寄存器SS的初始值为0
MOV SP,0x7c00 ; 让栈指针寄存器SP的初始值为0x7c00; 见上面的ORG,程序的起始地址就是0x7c00
MOV DS,AX ; 让数据段寄存器DS的初始值为0

; 阅读磁盘

MOV AX,0x0820 ; 让累加寄存器AX的值为0x0820; 该语句的作用:软盘数据加载到内存中的位置0x0820~0x83ff
MOV ES,AX ; 附加段寄存器ES的值赋值为AX的值,即0x0820; 该语句的作用:指定内存地址,先用ES指定大致的地址,下面再用BX指定其中的具体的地址,具体的内存地址是ES*16+BX
MOV CH,0 ; 柱面0; CH计数寄存器高位为0; 指定软盘上数据加载的位置
MOV DH,0 ; 磁头0; DH数据寄存器高位为0
MOV CL,2 ; 扇区2; CL计数寄存器低位为2

MOV SI,0 ; 记录失败次数的寄存器;SI是源变址寄存器
retry:
MOV AH,0x02 ; AH=0x02 ; AH累加寄存器高位的值为0x02; 该语句的作用:读盘
MOV AL,1 ; 1个扇区; AL累加寄存器低位的值为1
MOV BX,0 ; BX基址寄存器的值为0; 指定内存地址,具体的地址,具体的内存地址是ES*16+BX
MOV DL,0x00 ; A驱动器; DL数据寄存器低位的值为0x00; 该语句的作用:DL用来指定驱动器号
INT 0x13 ; 调用磁盘BIOS
JNC fin ; 没出错的话(进位标志为0)跳转到fin,出错的话(进位标志为1),继续往下执行
ADD SI,1 ; 往SI加1
CMP SI,5 ; 比较SI与5
JAE error ; 当SI>=5时,跳转到error
MOV AH,0x00 ; 复位软件状态
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS
JMP retry ; 跳回retry重新执行

; 让CPU睡眠,等待唤醒指令

fin:
HLT ; 让CPU停止,等待指令唤醒
JMP fin ; 无限循环

error:
MOV SI,msg ; 此时msg的地址是0x7c74(根据对应的汇编指令确定的这个地址),这里把这个值代入SI寄存器中;SI是源变址寄存器
putloop: ; 程序执行到(entry:)后,依次往下执行,执行到(JC error)处就跳到(error:)处执行,执行完(MOV SI,msg)后就继续往下执行(putloop:)
MOV AL,[SI] ; 把源变址寄存器SI所存储的内容放到累加寄存器低位AL里面去
ADD SI,1 ; 给SI加1
CMP AL,0 ; 比较AL是否等于0,如果AL等于0,说明[SI]储存的内容(即msg储存的内容,也就是地址0x7c74上存储的内容)等于0,也就是内容为空
JE fin ; 如果上面的条件成立就跳到fin中执行,如果不成立就继续往下执行,下面开始显示文字
MOV AH,0x0e ; 显示一个文字
MOV BX,15 ; 指定字符颜色
INT 0x10 ; 调用显卡BIOS
JMP putloop ; 循环显示文字
msg:
DB 0x0a, 0x0a ; 2个换行
DB "load error" ; 要显示的文字
DB 0x0a ; 换行
DB 0

RESB 0x7dfe-$ ; 填写0x00,直到0x7dfe

DB 0x55, 0xaa ; 表示这个扇区的开头是启动程序,并开始执行这个程序
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息