30天自制操作系统(一)启动区

一、启动区

	ORG		0x7C00
	JMP		entry
	DB		0x90
	DB		"HELLOIPL"
	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		"HELLO-OS   "
	DB		"FAT12   "
	RESB	18
	
entry:
	MOV		AX, 0
	MOV		SS, AX
	MOV		SP, 0x7c00
	MOV		DS, AX
	
	MOV		AX, 0x0820
	MOV		ES, AX
	MOV		CH, 0	;柱面0
	MOV		DH, 0	;磁头0
	MOV		CL, 2	;扇区2
	
readloop:
	MOV		AL, 1	;扇区数量
	MOV		BX, 0
	MOV		DL, 0	;A驱动器
	MOV		AH, 0x02	;读扇区
	INT		0x13
	JNC		next
	
error:
	MOV		AH, 0x0e
	MOV		AL, 'e'
	INT		0x10
	MOV		AL, 'r'
	INT		0x10
	MOV		AL, 'r'
	INT		0x10
	MOV		AL, 'o'
	INT		0x10
	MOV		AL, 'r'
	INT		0x10
	JMP		fin
	
next:
	MOV		AX, ES	
	ADD		AX, 0x20	;下一扇区
	MOV		ES, AX
	ADD		CL, 1
	CMP		CL, 18
	JBE		readloop
	
	MOV		CL, 1
	ADD		DH, 1
	CMP		DH, 2
	JB		readloop	;读反面的磁头1
	
	MOV		DH, 0
	ADD		CH, 1
	CMP		CH, 10		;读10个柱面
	JB		readloop
	
	JMP		0xc200

fin:
	HLT
	JMP		fin

	RESB	0x7dfe-$
	DB		0x55, 0xaa

前面的一部分内容(entry之前)是img镜像文件的固定格式,后面是启动区的正式内容

使用循环的方式读磁盘,按扇区——磁头——柱面的顺序,一个磁头18个扇区,一个柱面两个磁头。

程序的最后跳转到0xc200,因为磁盘内容装载在0x8000,文件内容存在0x4200,所以kernal.com就在0x8000+0x4200=0xc200的位置

(二)操作系统本身

;kernal.nas

[BITS 16]
	ORG	0xc200

	MOV	AH, 0x0e
	MOV	AL, 'A'
	INT	0x10

fin:
	HLT
	JMP	fin

输出一个A字符。

使用nasm kernal.nas -o kernal.com的方式编译,装载到img文件中即可。程序的开始要指定ORG 0xc200, 这样汇编器才能正确把标签名对照到正确的地址。

(三)图形模式切换

切换到图形模式:

	MOV	AL, 0x13
	MOV	AH, 0x00
	INT	0x10

分辨率320*200的VGA图形模式,VRAM的地址在0xa0000~0xaffff。
注意十六位下,用SI/DI寻址只能寻址到0x0000~0xffff的地址,所以要用寄存器寻址。

描画条纹图案:

		MOV		AX,0xA000
		MOV		DS,AX


		MOV		AL, 0x13
		MOV		AH, 0x00
		INT		0x10
		MOV		SI, 0x0000
L1:
		MOV		BX, SI
		AND		BL, 0x0f
		MOV		BYTE[DS:SI], BL
		ADD		SI, 1
		CMP		SI, 0xFFFF
		JBE		L1
fin:
		HLT
		JMP		fin

参考书中第四天的内容写的,不过暂时还未切换32位模式所以只能用汇编写。用[DS:SI]的方式寻址,16位下段号相当于[DS*16+SI],DS代入0xA000,SI代入0x0000,那么[DS:SI]就是[0xA0000]。

上一节是在80*25的字符模式下描画了一个文字A,这次我们尝试着在图形模式下描画文字A,参考第五天中文字显示的代码。

用汇编语言写比较复杂的循环可能是比较麻烦...(

实现如下:

其实主体的结构不难,最难的其实是内存段的处理,访问font_A的时候指定的是代码段寄存器CS,而访问显存需要指定数据段DS,还不能混用,如果给CS赋0xA0000就会出大问题。

[BITS 16]
	ORG	0xc200

	MOV	AL, 0x13
	MOV	AH, 0x00
	INT	0x10

	;font_A
	MOV	CX, 0
	MOV	AX, 0xa000
	MOV	DS, AX
	MOV	SI, 0x0000
	ADD	SI, 8*320
	ADD	SI, 8

loop:
	CMP	CX, 16
	JE	fin
	MOV	BX, CX
	MOV	BH, BYTE[CS:font_A+BX]
	AND	BH, 0x80
	CMP	BH, 0
	JE	L1
	MOV	BYTE[DS:SI+0], 15
L1:
	MOV	BX, CX
	MOV	BH, BYTE[CS:font_A+BX]
	AND	BH, 0x40
	CMP	BH, 0
	JE	L2
	MOV	BYTE[DS:SI+1], 15
L2:
	MOV	BX, CX
	MOV	BH, BYTE[CS:font_A+BX]
	AND	BH, 0x20
	CMP	BH, 0
	JE	L3
	MOV	BYTE[DS:SI+2], 15
L3:
	MOV	BX, CX
	MOV	BH, BYTE[CS:font_A+BX]
	AND	BH, 0x10
	CMP	BH, 0
	JE	L4
	MOV	BYTE[DS:SI+3], 15
L4:
	MOV	BX, CX
	MOV	BH, BYTE[CS:font_A+BX]
	AND	BH, 0x08
	CMP	BH, 0
	JE	L5
	MOV	BYTE[DS:SI+4], 15
L5:
	MOV	BX, CX
	MOV	BH, BYTE[CS:font_A+BX]
	AND	BH, 0x04
	CMP	BH, 0
	JE	L6
	MOV	BYTE[DS:SI+5], 15
L6:
	MOV	BX, CX
	MOV	BH, BYTE[CS:font_A+BX]
	AND	BH, 0x02
	CMP	BH, 0
	JE	L7
	MOV	BYTE[DS:SI+6], 15
L7:
	MOV	BX, CX
	MOV	BH, BYTE[CS:font_A+BX]
	AND	BH, 0x01
	CMP	BH, 0
	JE	L8
	MOV	BYTE[DS:SI+7], 15
L8:
	ADD	CX, 1
	ADD	SI, 320
	JMP	loop

fin:
	HLT
	JMP	fin

font_A:
	DB	0x00,0x18,0x18,0x18,0x18,0x24,0x24,0x24
	DB	0x24,0x7e,0x42,0x42,0x42,0xe7,0x00,0x00

话说在320*200的分辨率下,8*16的字符看上去确实很大==

posted @ 2024-10-19 19:48  计算机知识杂谈  阅读(18)  评论(0编辑  收藏  举报