30天自制操作系统笔记(四)

首先我们先展示一下第四天的成果:

图一:显示纯色


图二:显示格子


图三:使用调色板显示格子


图四:画正方形


最后的图为一个小界面:


第四天的内容其实不难,但是由于前三天写的代码部分有问题,导致今天调试了一天才找到问题所在问题的更正已经在下面的源文件中指出。

代码中唯一没有指出的是Makefile文件中的溢出小错误,将文件名字写错啦具体为:

naskfunc.obj: naskfunc.nas Makefile  
    $(NASK) naskfunc.nas naskfunc.obj naskfunc.lst
应该改为:

ucan23.sys: ucan23.bin bootpack.hrb Makefile
	copy /B ucan23.bin+bootpack.hrb ucan23.sys

下面是程序的源码:naskfunc.nas

; naskfunc
; TAB=4

[FORMAT "WCOFF"]				 
[INSTRSET "i486p"]				 
[BITS 32]						 
[FILE "naskfunc.nas"]			 

		GLOBAL	_io_hlt,_write_mem8
		GLOBAL	_io_cli, _io_sti, _io_stihlt
		GLOBAL	_io_in8, _io_in16, _io_in32
		GLOBAL	_io_out8, _io_out16, _io_out32
		GLOBAL	_io_load_eflags, _io_store_eflags

[SECTION .text]

_io_hlt:	; void io_hlt(void);
		HLT
		RET

_write_mem8:	; void write_mem8(int addr, int data);
		MOV		ECX,[ESP+4]		;  
		MOV		AL,[ESP+8]		;  
		MOV		[ECX],AL
		RET

_io_cli:	;void io_cli(void);
		CLI
		RET
		
_io_sti:	;void io_sti(void);
		STI
		RET
	
_io_stihlt:		;void io_stihlt(void);
		STI
		HLT
		RET
	
_io_in8:			;int io_in8_(int port);
		MOV		EDX, [ESP+4]	;port
		MOV		EAX, 0
		IN		AL, DX
		RET
		
_io_in18:		;int io_in16(int port);
		MOV		EDX, [ESP+4]
		MOV		EAX, 0
		IN		AX, DX
		RET
		
_io_in32:		;io_in32(int port);
		MOV		EDX, [ESP+4]
		IN		EAX, DX
		RET
		
_io_out8:		;io_out8(int port, int data);
		MOV		EDX, [ESP+4] 	;PORT
		MOV		AL, [ESP+8]		;DATA
		OUT		DX, AL
		RET
		
_io_out16:		;io_out16(int port, int data);
		MOV		EDX, [ESP+4]
		MOV		EAX, [ESP+8]
		OUT		DX, AX
		
_io_out32:		;io_out32(int port, int data);
		MOV		EDX, [ESP+4]
		MOV		EAX, [ESP+8]
		OUT		DX, EAX
		RET

_io_load_eflags:	;io_load_eflags(int eflags);
		PUSHFD
		POP		EAX
		RET
		
_io_store_eflags:	;io_store_eflags(int eflags);
		MOV		EAX, [ESP+4]
		PUSH	EAX
		POPFD
		RET
文件ucan23ipl.nas修正后的代码:

; ucan23-os
; TAB-4
; 本程序前一版本存在的错误将CMP		DH, 2写成了CMP		CH, 2
CYLS	EQU		10
		ORG	0x7c00	;指明程序的装载地址
; 以下这段是标准FAT12格式软盘专用的代码
	JMP		entry
	DB		0x90
	DB		"UCAN23LD"	;启动区的名称可以是任意的字符串(8字节)
	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		"UCAN23-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
	MOV		DH, 0
	MOV		CL, 2
readloop:	
	MOV		SI, 0 ;记录失败次数的寄存器
retry:
	MOV		AH, 0x02
	MOV		AL, 1
	MOV		BX, 0
	MOV		DL, 0x00
	INT		0x13
	JNC		next
	ADD		SI, 1
	CMP		SI, 5
	JAE		error
	MOV		AH, 0x00
	MOV		DL, 0x00
	INT		0x13
	JMP		retry
	;JMP		error
	
next:
	MOV		AX, ES
	ADD		AX, 0x0020
	MOV		ES, AX
	ADD		CL, 1
	CMP		CL, 18
	JBE		readloop
	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
	JMP		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	;2个换行
	DB		"Hello, world(ucan23)"
	DB		0x0a
	DB		"This is my first OS"
	DB		0x0a
	DB		"Copyright GPL"
	DB		0x0a
	DB		"Author: ucan23(Howard)"
	DB		0x0a
	DB		"Blog:http://blog.sina.com/rjxx007"
	DB		0x0a
	DB		"Blog:http://blog.csdn.net/ucan23"
	DB		0x0a
	DB		0
	
	RESB	0x7dfe-$
	DB		0x55, 0xaa

bootpack.c文件源码

/*告诉C编译器,有一个函数在别的文件里*/
void io_hlt(void);
void io_cli(void);
void io_out8(int port, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);
void write_mem8(int addr, int data);


void init_palette(void);
void set_palette(int start, int end, unsigned char *rgb); /*调色板函数*/
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);

#define COL8_000000		0
#define COL8_FF0000		1
#define COL8_00FF00		2
#define COL8_FFFF00		3
#define COL8_0000FF		4
#define COL8_FF00FF		5
#define COL8_00FFFF		6
#define COL8_FFFFFF		7
#define COL8_C6C6C6		8
#define COL8_840000		9
#define COL8_008400		10
#define COL8_848400		11
#define COL8_000084		12
#define COL8_840084		13
#define COL8_008484		14
#define COL8_848484		15

void UcanMain(void)
{
	//int i;
	char *p;
	init_palette();
	p = (char *) 0xa0000;
	/*for (i=0x0000; i<=0xffff; i++){
		//write_mem8(i,i&0x0f);
		//write_mem8(i,9);
		//p = (char *)i;
		//*p = i & 0x0f;
		//*((char *)i) = i & 0x0f;
		(p[i]) = i & 0x0f;
	}
	*///END FOR
	
	boxfill8(p, 320, COL8_FF0000, 20, 20, 120, 120);
	boxfill8(p, 320, COL8_00FF00, 70, 50, 170, 150);
	boxfill8(p, 320, COL8_0000FF, 120, 80, 220, 180);
	
	for (;;){
		io_hlt();    /*执行nashfunc.nas里的_io_hlt*/
	}
}

void init_palette(void)
{
	/*初始化调色板函数的实现*/
	static unsigned char table_rgb[16*3] = {
		0x00, 0x00, 0x00, 	/*  0:黑*/
		0xff, 0x00, 0x00,	/*  1:亮红 */
		0x00, 0xff, 0x00,	/*  2:亮绿 */
		0xff, 0xff, 0x00,	/*  3:亮黄 */
		0x00, 0x00, 0xff,	/*  4:亮蓝 */
		0xff, 0x00, 0xff,	/*  5:亮紫 */
		0x00, 0xff, 0xff,	/*  6:浅亮蓝 */
		0xff, 0xff, 0xff,	/*  7:白 */
		0xc6, 0xc6, 0xc6,	/*  8:亮灰 */
		0x84, 0x00, 0x00,	/*  9:暗红 */
		0x00, 0x84, 0x00,	/* 10:暗绿 */
		0x84, 0x84, 0x00,	/* 11:暗黄 */
		0x00, 0x00, 0x84,	/* 12:暗青 */
		0x84, 0x00, 0x84,	/* 13:暗紫 */
		0x00, 0x84, 0x84,	/* 14:浅暗蓝 */
		0x84, 0x84, 0x84	/* 15:暗灰 */
	};
	set_palette(0, 15, table_rgb);
	
	return;
}

void set_palette(int start, int end, unsigned char *rgb)
{
	int i, eflags;
	eflags = io_load_eflags();
	io_cli();
	io_out8(0x03c8, start);
	for (i=start; i<=end; i++){
		io_out8(0x03c9, rgb[0]/4);
		io_out8(0x03c9, rgb[1]/4);
		io_out8(0x03c9, rgb[2]/4);
		rgb += 3;
	}
	io_store_eflags(eflags);
	
	return;
}

void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
{
	int x,y;
	
	for (y=y0; y<=y1; y++){
		for (x=x0; x<=x1; x++){
			vram[y*xsize+x] = c;
		}
	}
	
	return;
}

ucan23.nas文件源码

; ucan23-os boot asm
; TAB=4
; 此程序前一个版本存在的错误:将skip写成了ship
; 将[INSTRSET "i486p"]写成了[INSTREST "i486p"]
; 将waitkbdout写成了waitkdbout
BOTPAK	EQU		0x00280000
DSKCAC	EQU		0x00100000
DSKCAC0	EQU		0x00008000

; 有关BOOT_INFO
CYLS	EQU		0x0ff0
LEDS	EQU		0x0ff1
VMODE	EQU		0x0ff2
SCRNX	EQU		0x0ff4
SCRNY	EQU		0x0ff6
VRAM	EQU 	0x0ff8
		
		ORG		0xc200
		
		MOV		AL, 0x13
		MOV		AH, 0x00
		INT		0x10
		MOV 	BYTE [VMODE], 8
		MOV		WORD [SCRNX], 320
		MOV		WORD [SCRNY], 200
		MOV		DWORD [VRAM], 0x000a0000

; 用BIOS获取LED指示灯的状态
		MOV		AH, 0x02
		INT		0x16          ; keyboard BIOS
		MOV		[LEDS], AL
		
		MOV		AL, 0xff
		OUT		0x21, AL
		NOP
		OUT		0xa1, AL
		
		CLI
		
		CALL	waitkbdout
		MOV		AL, 0xd1
		OUT		0x64, AL
		CALL	waitkbdout
		MOV		AL, 0xdf
		OUT		0x60, AL
		CALL	waitkbdout
		
[INSTRSET "i486p"]

		LGDT	[GDTR0]
		MOV		EAX,CR0
		AND		EAX, 0x7fffffff
		OR		EAX, 0x00000001
		MOV		CR0, EAX
		JMP		pipelineflush
pipelineflush:
		MOV		AX, 1*8
		MOV		DS, AX
		MOV 	ES, AX
		MOV		FS, AX
		MOV		GS, AX
		MOV 	SS, AX
		
		
		MOV		ESI, bootpack
		MOV		EDI, BOTPAK
		MOV		ECX, 512*1024/4
		CALL	memcpy
		
		
		MOV		ESI, 0x7c00
		MOV		EDI, DSKCAC
		MOV		ECX, 512/4
		CALL	memcpy
		
		
		MOV		ESI, DSKCAC0+512
		MOV		EDI, DSKCAC+512
		MOV		ECX, 0
		MOV		CL, BYTE [CYLS]
		IMUL	ECX, 512*18*2/4
		SUB		ECX, 512/4
		CALL	memcpy
		
		MOV		EBX, BOTPAK
		MOV		ECX, [EBX+16]
		ADD		ECX, 3
		SHR		ECX, 2
		JZ		skip
		MOV		ESI, [EBX+20]
		ADD		ESI, EBX
		MOV		EDI, [EBX+12]
		CALL	memcpy
		
skip:
		MOV		ESP, [EBX+12]
		JMP		DWORD 2*8:0x0000001b
		
waitkbdout:
		IN		AL, 0x64
		AND		AL, 0x02
		JNZ		waitkbdout
		RET
		
memcpy:
		MOV		EAX, [ESI]
		ADD		ESI, 4
		MOV		[EDI], EAX
		ADD		EDI, 4
		SUB		ECX, 1
		JNZ		memcpy
		RET
		
		ALIGNB	16
GDT0:
		RESB 	8
		DW		0xffff,0x0000,0x9200,0x00cf
		DW		0xffff,0x0000,0x9a28,0x0047
		
		DW		0

GDTR0:
		DW		8*3-1
		DD		GDT0
		
		ALIGNB	16
		
bootpack:


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值