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

程序中的行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		; 表示这个扇区的开头是启动程序,并开始执行这个程序


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值