您的位置:首页 > 移动开发 > IOS开发

《30天自制操作系统》学习笔记——第1-3天

2014-11-26 09:41 260 查看
这本书作者是日本人,虽然书翻译为中文,但是源代码里注释都是日文,对不懂日语的人来说看起来不够方便,我把书本中给出的注释翻译,以及书本介绍的一些知识,加到了注释里,阅读起来能够方便些。

前3天主要就是写一个ipl程序(initial program loader启动程序加载器),不论是用二进制编辑器直接写机器指令还是用汇编生成二进制程序,最终目的都是得到第一个扇区的512字节的启动程序。

0x10号bios函数用于显示文字

0x13号bios函数提供磁盘的读,写,扇区校验,寻道操作,AH=0x02读盘操作

这两个bios函数调用时以寄存器的值为参数,提供相应操作。

; haribote-ipl
; TAB=4

CYLS  	EQU		10				;
ORG		0x7c00			;ORG伪指令,编译不生成机器代码,用于给链接器定位用,将程序装载到内存的指定位置
;0x7c00~0x7dff 512字节放置启动程序

; 标准FAT12格式软盘专用的代码

JMP		entry			;jmp跳转 至标签entry处;JMP 0x7c50 没问题,JMP跳转到的就是内存地址
DB		0x90			;DB即data byte 往文件里写入一个字节,DW写一个word,16位,DD写double word,32位
DB		"HARIBOTE"		;启动区的名称,可以是任意的字符串(8字节)
DW		512				;每个扇区(sector)的大小(必须为 512字节)
DB		1				;簇(cluster)的大小(必须为 1 个扇区)
DW		1				;FAT(File Allocation Table:文件配置表)的起始位置(一般从第一个扇区开始)
DB		2				;FAT的个数,必须为2
DW		224				;根目录的大小(一般设成224项)
DW		2880			;该磁盘的大小(必须为2880个扇区)
DB		0xf0			;磁盘的种类(必须为0xf0)
DW		9				;FAT的长度(必须是9扇区)
DW		18				;一个磁道(track)有几个扇区(必须是18)
DW		2				;磁头数(必须是2)
DD		0				;不使用分区,必须是0
DD		2880			;重写一次磁盘大小
DB		0,0,0x29		;意义不明,固定
DD		0xffffffff		;(可能是)卷标号码
DB		"HARIBOTEOS "	; 磁盘的名称(11字节)
DB		"FAT12   "		; 磁盘格式名称(8字节)
RESB	18				; reserve word 从当前地址空出18个字节,nask会把这18个字节填充为0x00

entry:
MOV		AX,0 			;AX accumulator 	累加寄存器 (16位)把0复制到AX中,初始化AX
MOV		SS,AX 			;SS stack segment	栈段寄存器 (16位)
MOV		SP,0x7c00		;SP stack pointer	栈指针寄存器(16位)
MOV		DS,AX 			;DS data segment	数据段寄存器(16位)

MOV		AX,0x0820 		;MOV AL,[ES:BX] 代表ES*16+BX的内存地址
;0x7c00~0x7dff用于启动区,0x7e00~0xfbff没有特别的用途,操作系统随便用
;缓冲区地址,将要把软盘上读取的数据放到0x8200之后,内存分布图上0x8000后无人使用
;0x8000~0x81ff留给启动区,将启动区内容读到这里
MOV		ES,AX 			;ES extra segment	附加段寄存器(16位)	ES=0x0820,BX=0
MOV		CH,0 			;CH	counter high    计数寄存器高位(8位)	柱面0
MOV		DH,0 			;DH	data high		数据寄存器高位(8位)	磁头0
MOV		CL,2 			;CL counter low		计数寄存器地位(8位)	扇区2,计数读的扇区标号
readloop:
MOV		SI,0 			;SI	source index	源变址寄存器(16位)	记录失败
retry:
MOV		AH,0x02 		;AH	accumulator high 累加寄存器高位(8位) AX=0x02 读盘
MOV		AL,1 			;AL	accumulator low  累加寄存器低位(8位) AL=1 1个扇区
MOV		BX,0 			;BX base			 基址寄存器(16位)
MOV		DL,0x00  		;DL	data low		 数据寄存器低位(8位)	A驱动器
INT		0x13			;INT interrupt 软件中断指令,暂且当作函数调用 调用磁盘BIOS
JNC		next			;jump if not carry 	如果进位标志为0,跳转至next	0x13调用有错标志为1,无错为0
ADD		SI,1 			;SI加1
CMP		SI,5 			;比较SI和5
JAE		error 			;jump if above or equal SI>=5时跳转到error
MOV		AH,0x00 		;
MOV		DL,0x00 		;A驱动器
INT		0x13 			;重置驱动器
JMP		retry 			;无条件 跳转到retry
next:
MOV		AX,ES 			;把内存地址后移0x200 512字节 512/16=0x20 [ES:BX]
ADD		AX,0x0020		;
MOV		ES,AX 			;没有ADD ES,0x20指令
ADD		CL,1 			;CL+1
CMP		CL,18 			;比较CL和18(1-18 18个扇区)
JBE		readloop		;jump if below or equal cl<=18 跳转到readloop
MOV		CL,1 			;扇区标号更新为1
ADD		DH,1 			;磁头数+1,读磁盘反面
CMP		DH,2 			;比较DH 2
JB 		readloop 		;jump if below DH<2 时跳转到readloop
MOV		DH,0 			;磁头初始化为0
ADD		CH,1 			;柱面+1
CMP		CH,CYLS 		;比较CH 和 CYLS=10
JB 		readloop 		;jump if below  CH<10 跳转到readloop
;空软盘保存文件时,文件名会写在0x2600以后的地方,文件内容会写在0x4200以后
MOV		[0x0ff0],CH	 	;把磁盘装载地址的结束写到内存0x0ff0处
JMP		0xc200 			;程序从启动区开始,把磁盘上的内容装载到内存0x8000号地址,磁盘0x4200处的内容应该位于
;0x8000+0x4200=0xc200号地址
error:
MOV		SI,msg			;msg地址复制到SI
putloop:
MOV		AL,[SI]			;[]表示内存地址,这句是把内存地址为SI的数据复制到AL中
ADD		SI,1 			;SI+1
CMP		AL,0 			;比较AL和0
JE		fin 			;jump if equal
MOV		AH,0x0e 		;
MOV		BX,15 			;
INT		0x10 			;调用bios 0x10号函数
JMP		putloop 		;
fin:
HLT 					;CPU停止动作,进入待机状态,外部发生变化,比如按下键盘,cpu会苏醒过来,继续执行程序
JMP			fin			;无限循环
msg:
DB		0x0a,0x0a 		;2个换行
DB		"load error" 	;DB直接写字符串,汇编语言自动查找编码
DB		0x0a			;换行
DB		0 				;标志msg结束

RESB	0x7dfe-$		;$指示当前行在文件中所处的字节数;在使用ORG指令后

DB		0x55,0xaa		;软盘的第0x1fe即第510字节开始处必须为55 aa
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  操作系统 汇编 bios