启动程序装载器

下面开始我们新的一章的学习了。在这章开头,我先要吐槽一下这本书,我觉得这本在第三章,也就是第三天这里,感觉有些地方作者

讲的很含糊,有的地方需要深入的讲解却没有,但是有很多所谓的“风趣”的话,但是我倒不觉得有多风趣,纯属吐槽。

好了下面开始进入正文,在进入正文之前先讲解几个重要的概念

启动区:(boot sector)软盘第一个的扇区成为启动区,就是0面0道1扇区。那么什么是扇区呢?计算机读写软盘的时候,并不是一个字节

一个字节地读写的,而是以512字节为一个单位进行读写。因此软盘的512个字节就称为一个扇区,一张软盘的空间共有1440KB,也就是

1474560字节,除以512得2880,这也就是说一张软盘共有2880个扇区。那为什么第一个扇区称为启动区呢?那是因为计算机首先从最初一个

扇区开始读软盘,然后去检查这个扇区最后2个字节的内容。如果这最后2个字节不是55AA,计算机会认为这张软盘上没有所需的启动程序,就

会报一个不能启动的错误。如果计算机确认第一个扇区的最后两个字节正好是55AA,那它就认为这个扇区的开头是启动程序,并开始执行这个程序。

IPL:(initial program loader)的缩写。启动程序加载器,启动区只有区区512字节,实际的操作系统很大,根本装不进去,所以几乎所有

的操作系统,都是把加载操作系统本身的程序放在启动区里的。有鉴于此,有时也将启动区称为IPL。

概念说完,那就上代码了:

; haribote-ipl
; TAB=4

CYLS	EQU		10				

		ORG		0x7c00			



		JMP		entry
		DB		0x90
		DB		"HARIBOTE"		
		DW		512				
		DB		1				
		DW		1				
		DB		2				
		DW		224				
		DW		2880			
		DB		0xf0			
		DW		9				
		DW		18				
		DW		2				
		DD		0				
		DD		2880			
		DB		0,0,0x29		
		DD		0xffffffff		
		DB		"HARIBOTEOS "	
		DB		"FAT12   "		
		RESB	18				



entry:
		MOV		AX,0			
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX



		MOV		AX,0x0820		;表示要把磁盘0柱面0磁头2扇区的数据加载到内存0x8200开始的位置
		MOV		ES,AX
		MOV		CH,0	 		;柱面0		
		MOV		DH,0			;磁头0
		MOV		CL,2			;扇区2
readloop:
		MOV		SI,0			
retry:
		;这里是读一个扇区的操作
		MOV		AH,0x02			;AH=0x20:读盘
		MOV		AL,1			;1个扇区(表示要处理的扇区数)
		MOV		BX,0
		MOV		DL,0x00			;A驱动器
		INT		0x13			;调用磁盘BIOS
		
		JNC		next			;读盘没出错那就跳转到next标号
		
		;这里是试错操作,软盘这东西很不可靠,有时发生不能读数据的状况,这时候重新再读一次就行了。
		ADD		SI,1			
		CMP		SI,5			
		JAE		error			
		MOV		AH,0x00
		MOV		DL,0x00			
		INT		0x13			
		JMP		retry
		
next:
		;移动地址
		MOV		AX,ES			;把内存地址后移0x200(为什么?下面讲解)
		ADD		AX,0x0020
		MOV		ES,AX			
		
		;下面的操作就是从C0-H0-S1一直读到C9-H1-S18
		ADD		CL,1			
		CMP		CL,18			
		JBE		readloop		;循环18个扇区
		
		MOV		CL,1
		ADD		DH,1
		CMP		DH,2
		JB		readloop		;循环磁头
		
		MOV		DH,0
		ADD		CH,1
		CMP		CH,CYLS
		JB		readloop		;循环柱面



		MOV		[0x0ff0],CH		;保存CYLS值
		JMP		0xc200			;跳转到0xc200地址开始执行指令

;下面这串暂时没用,可以忽略
error:
		MOV		SI,msg
putloop:
		MOV		AL,[SI]
		ADD		SI,1			
		CMP		AL,0
		JE		fin
		MOV		AH,0x0e			
		MOV		BX,15			
		INT		0x10			
		JMP		putloop
fin:
		HLT						
		JMP		fin				
msg:
		DB		0x0a, 0x0a		
		DB		"load error"
		DB		0x0a			
		DB		0

		RESB	0x7dfe-$		

		DB		0x55, 0xaa

 

 

1,下面先来看看几个BIOS的函数调用

INT 0x13:磁盘读,写,扇区校验,以及寻道

AH = 0x02;(读盘)

AH = 0x03;(写盘)

AH = 0x04;(校验)

AH = 0x0c;(寻道)

AL = 处理对象的扇区数(只能同时处理连续的扇区)

CH = 柱面号 & 0xff;

CL = 扇区号(0-5位) | (柱面号&0x300) >> 2;

DH = 磁头号;

DL = 驱动器号

ES:BX=缓冲地址;(校验及寻道时不使用)

返回值: FLACS.CF == 0: 没有错误,AH==0

FLAGS.CF == 1: 有错误,错误号码存入AH内

 

INT 0x13

AH = 0x00

DL = 0x00

这个三个组合就是系统复位功能,它的功能是复位软盘状态,再读一次。

 

2,下面要总结几个跳转指令

(1),JC,是"jump if carry"的缩写,意思是如果进位(carry flag)是1的话,就跳转。

(2),JNC,是"jump if not carry"的缩写,意思是如果进位(carry flag)是0的话,就跳转。

(3),JAE,是"jump if above or equal"的缩写,意思是大于或等于时跳转。

(4),JB,是"jump if below"的缩写,如果小于的话,就跳转

 

3,讲解几个我觉得需要注意的地方

(1)就是程序开始时为什么要将ES指定为0x0820?作者的理由如下:

我们指定了ES=0x0820,BX=0,所以软盘的数据将被装载到内存中0x8200到0x83ff的地方,可能有人会想,怎么也不弄个整点的数,

比如0x8000什么的,那多好,但0x8000-0x81ff这512字节是留给启动区的,要将启动区的内容读到那里,所以就这样吧。

但在后面作者又说0x7c00-0x7dff用于启动区,0x7e00以后直到0x9fbff为止的区域没有特别的用途,操作系统可以随便使用。

所以这里就给我造成了疑问,但是是0x8000-0x81ff还是0x7c00-0x7dff用于启动区呢,BIOS规定为把0盘0面1扇区的内容加载到

0x7c00的位置,这肯定是无可厚非的。但是作者后面又说0x8000-0x81ff这512字节是留给启动区的呢?

但是,我觉得一定不是作者弄错了,只不过没表达清晰而已,因为我们的代码是从0盘0面2扇区的内容开始加载进来的,假如我们

的代码是从0盘0面1扇区的内容加载的,那么物理地址=0x8200+汇编地址(即是当前的代码相对于文件的偏移量),但是问题现在

作者是从0盘0面2扇区的内容,所以作者把0x8000-0x8lff预留给启动区的(即使作者这段地址实际上是没用的),那么现在的物理地址

=0x8000+汇编地址。这里有点难解释清楚,得自己看书好好体会。

(2)第二个问题我觉的是作者的疏忽。在第52页中作者写到:"CL是扇区号,ES指定读入地址。0x20是十六制512除以16的结果,如果

写成ADD AX,512/16或许更好懂,笔者在写的时候,直接在头脑中换算成了0x20,当然写成512/16也一样。可能有人会说:往BX里加上

512不是更简单吗",这里的代码不能直接往BX直接加上512,因为每次BX的值每次都被更新为0了,除非上面的代码需要改了。

那下面可以看看这个启动区的代码怎么来进行加载下面的helloworld程序。

; haribote-os
; TAB=4
 
ORG0xc200
 
entry:
MOVAX,0
MOVSS,AX
MOVSP,0xc200
MOVDS,AX
MOVES,AX
 
MOVSI,msg
putloop:
MOVAL,[SI]
ADDSI,1
CMPAL,0
JEfin
MOVAH,0x0e
MOVBX,15
INT0x10
JMPputloop
fin:
HLT
JMPfin
 
msg:
DB0x0a, 0x0a
DB"hello, world"
DB0x0a
DB0

 运行效果如下:



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值