30天自制操作系统笔记(七八)——源码

下面是七八天的源码:

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:

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为系统的主函数所在的文件:

/* filename:    bootpack.c
 * description: the UcanMain()file
 * author:      Howard
 * date:        2013-11-28
 * version:     v1.0
 */


#include <stdio.h>
#include "bootpack.h"


extern struct FIFO8 keyfifo, mousefifo;

void UcanMain(void)
{
	
	char *vram;
	char s[50], mcursor[256], keybuf[32], mousebuf[128];
	int mx, my;//鼠标的(x,y)
	int xsize, ysize;
	int i;
	struct MOUSE_DEC mdec; /*鼠标解码缩放的数据*/
	
	struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
			 
	init_gdtidt();
	init_pic();
	io_sti();
	
	fifo8_init(&keyfifo, 32, keybuf);
	fifo8_init(&mousefifo, 128, mousebuf);
	io_out8(PIC0_IMR, 0xf9);
	io_out8(PIC1_IMR, 0xef);
	
	init_keyboard();
	
	init_palette();
		
	xsize = (*binfo).scrnx;
	ysize = (*binfo).scrny;
	vram = (*binfo).vram;
	init_screen(binfo->vram, binfo->scrnx, binfo->scrny);
	mx = (binfo->scrnx-16) / 2;
	my = (binfo->scrny-28-16) /2;
	init_mouse_cursor8(mcursor, COL8_008484);
	putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);
	putfonts8_asc(binfo->vram, binfo->scrnx, 8, 8, COL8_FFFFFF, "Hello, world!");
	putfonts8_asc(binfo->vram, binfo->scrnx, 31, 31, COL8_000000, "Ucan23-OS");
	putfonts8_asc(binfo->vram, binfo->scrnx, 30, 30, COL8_FFFFFF, "Ucan23-OS");
	
	sprintf(s, "scrnx = %d", binfo->scrnx);
	putfonts8_asc(binfo->vram, binfo->scrnx, 16, 64, COL8_FFFFFF, s);
	
	sprintf(s, "(%d, %d)", mx, my);
	putfonts8_asc(binfo->vram, binfo->scrnx, mx+16, my+16, COL8_FFFFFF, s);
	
	//io_out8(PIC0_IMR, 0xf9);
	//io_out8(PIC1_IMR, 0xef);
	
	enable_mouse(&mdec);
	
	for (;;){
		io_cli();    /*执行nashfunc.nas里的_io_hlt*/
		if (0==(fifo8_status(&keyfifo)+fifo8_status(&mousefifo))){
			io_stihlt();
		} else {
			if (0!=fifo8_status(&keyfifo)){
				i = fifo8_get(&keyfifo);
				io_sti();
				sprintf(s, "%02X", i);
				boxfill8(binfo->vram, binfo->scrnx, COL8_000000, 0, 120, 15, 135);
				putfonts8_asc(binfo->vram, binfo->scrnx, 0, 120, COL8_FFFFFF, s);
			} else if (0!=fifo8_status(&mousefifo))
			{
				i = fifo8_get(&mousefifo);
				io_sti();
				if (0 != mouse_decode(&mdec, i)){					
					sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
					if ((mdec.btn & 0x01)!=0){
						s[1] = 'L';
					}
					if ((mdec.btn & 0x02)!=0){
						s[3] = 'R';
					}
					if ((mdec.btn & 0x04)!=0){
						s[2] = 'C';
					}
					boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 120, 32+15*8-1,135);
					putfonts8_asc(binfo->vram, binfo->scrnx, 32, 120, COL8_FFFFFF, s);
					
					/*鼠标指针的移动*/
					boxfill8(binfo->vram, binfo->scrnx, COL8_008484, mx, my, mx+15, my+15);/*隐藏鼠标*/
					mx += mdec.x;
					my += mdec.y;
					if (mx<0){
						mx = 0;
					}
					if (my<0){
						my = 0;
					}
					if (mx>binfo->scrnx-16){
						mx = binfo->scrnx-16;
					}
					if (my>binfo->scrny-16){
						my = binfo->scrny-16;
					}
					sprintf(s, "(%3d, %3d)", mx, my);
					boxfill8(binfo->vram, binfo->scrnx, COL8_008484,100,0, 79, 15);
					putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF,s);
					putblock8_8(binfo->vram,binfo->scrnx, 16, 16, mx, my, mcursor, 16);
					
				}
			}		
		}
	}
}

void wait_KBC_sendready(void)
{
	for (;;){
		if (0==(io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY)){
			break;
		}
	}
	return;
}

void init_keyboard(void)
{
	wait_KBC_sendready();
	io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
	wait_KBC_sendready();
	io_out8(PORT_KEYDAT, KBC_MODE);
	return;
}
void enable_mouse(struct MOUSE_DEC *mdec)
{
	wait_KBC_sendready();
	io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
	wait_KBC_sendready();
	io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
	mdec->phase = 0;
	return;
}

int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)
{
	if (0 == mdec->phase){
		/*等待鼠标的0xfa状态*/
		if (0xfa == dat){
			mdec->phase = 1;
		}
		return 0;
	}
	if (1 == mdec->phase){
		/*等待鼠标的第一个字节*/
		if ((dat & 0xc8) == 0x08){
			mdec->buf[0] = dat;
			mdec->phase = 2;
		
		}
		return 0;
	}
	if (2 == mdec->phase){
		/*等待鼠标的第二个字节*/
		mdec->buf[1] = dat;
		mdec->phase = 3;
		return 0;
	} 
	if (3 == mdec->phase){
		mdec->buf[2] = dat;
		mdec->phase = 1;
		mdec->btn = mdec->buf[0] & 0x07;
		mdec->x = mdec->buf[1];
		mdec->y = mdec->buf[2];
		if (0!=(mdec->buf[0] & 0x10)){
			mdec->x |= 0xffffff00;
		}
		if (0!=(mdec->buf[0] & 0x20)){
			mdec->y |= 0xffffff00;
		}
		mdec->y = -mdec->y;
		return 1;
	}
	return -1;
}

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
		GLOBAL	_load_gdtr, _load_idtr
		GLOBAL	_asm_inthandler21, _asm_inthandler27, _asm_inthandler2c
		EXTERN	_inthandler21, _inthandler2c, _inthandler27

[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_in16:		;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
		
_load_gdtr:		;void load_gdtr(int limit, int addr);
		MOV		AX,[ESP+4]		;limit
		MOV 	[ESP+6], AX
		LGDT	[ESP+6]
		RET
		
_load_idtr:		;void load_idtr(int limit, int addr);
		MOV		AX, [ESP+4]
		MOV		[ESP+6], AX
		LIDT	[ESP+6]
		RET
		
_asm_inthandler21:
		PUSH	ES
		PUSH	DS
		PUSHAD
		MOV		EAX, ESP
		PUSH 	EAX
		MOV		AX, SS
		MOV		DS, AX
		MOV		ES,	AX
		CALL	_inthandler21
		POP		EAX
		POPAD
		POP		DS
		POP		ES
		IRETD
		
_asm_inthandler27:
		PUSH	ES
		PUSH	DS
		PUSHAD
		MOV		EAX, ESP	
		PUSH	EAX
		MOV		AX, SS
		MOV		DS, AX
		MOV		ES, AX
		CALL	_inthandler27
		POP		EAX
		POPAD
		POP		DS
		POP		ES
		IRETD
		
_asm_inthandler2c:
		PUSH	ES
		PUSH	DS
		PUSHAD
		MOV		EAX, ESP
		PUSH	EAX
		MOV		AX, SS
		MOV		DS, AX
		MOV		ES, AX
		CALL	_inthandler2c
		POP		EAX
		POPAD
		POP		DS
		POP		ES
		IRETD

graphic.c文件为系统画面显示,绘制画面函数的文件:

/* filename:    graphic.c
 * description: 负责桌面的显示工作
 * author:      Howard
 * date:        2013-11-28
 * version:     v1.0
 */


#include "bootpack.h"

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;
}

void init_screen(char *vram, int xsize, int ysize)
{
	boxfill8(vram, xsize, COL8_008484,  0,         0,          xsize -  1, ysize - 29);
	boxfill8(vram, xsize, COL8_C6C6C6,  0,         ysize - 28, xsize -  1, ysize - 28);
	boxfill8(vram, xsize, COL8_FFFFFF,  0,         ysize - 27, xsize -  1, ysize - 27);
	boxfill8(vram, xsize, COL8_C6C6C6,  0,         ysize - 26, xsize -  1, ysize -  1);

	boxfill8(vram, xsize, COL8_FFFFFF,  3,         ysize - 24, 59,         ysize - 24);
	boxfill8(vram, xsize, COL8_FFFFFF,  2,         ysize - 24,  2,         ysize -  4);
	boxfill8(vram, xsize, COL8_848484,  3,         ysize -  4, 59,         ysize -  4);
	boxfill8(vram, xsize, COL8_848484, 59,         ysize - 23, 59,         ysize -  5);
	boxfill8(vram, xsize, COL8_000000,  2,         ysize -  3, 59,         ysize -  3);
	boxfill8(vram, xsize, COL8_000000, 60,         ysize - 24, 60,         ysize -  3);

	boxfill8(vram, xsize, COL8_848484, xsize - 47, ysize - 24, xsize -  4, ysize - 24);
	boxfill8(vram, xsize, COL8_848484, xsize - 47, ysize - 23, xsize - 47, ysize -  4);
	boxfill8(vram, xsize, COL8_FFFFFF, xsize - 47, ysize -  3, xsize -  4, ysize -  3);
	boxfill8(vram, xsize, COL8_FFFFFF, xsize -  3, ysize - 24, xsize -  3, ysize -  3);
	
	return;
}


void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
{
	int i;
	char *p, d;
	for (i=0; i<16; i++){
		p = vram + (y+i)*xsize +x;
		d = font[i];
		if ((d&0x80) !=0 ){ p[0] =c;}
		if ((d&0x40) !=0 ){ p[1] =c;}
		if ((d&0x20) !=0 ){ p[2] =c;}
		if ((d&0x10) !=0 ){ p[3] =c;}
		if ((d&0x08) !=0 ){ p[4] =c;}
		if ((d&0x04) !=0 ){ p[5] =c;}
		if ((d&0x02) !=0 ){ p[6] =c;}
		if ((d&0x01) !=0 ){ p[7] =c;}
	}
	return;
}

void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
{
	extern char yezfont[4096];
	for (; *s!=0x00; s++){
		putfont8(vram, xsize, x, y, c, yezfont+*s*16);
		x += 8;
	}
	return;
}

void init_mouse_cursor8(char *mouse, char bc)
/* 鼠标初始化函数 */
{
	static char cursor[16][16] = {
		"**************..",
		"*OOOOOOOOOOO*...",
		"*OOOOOOOOOO*....",
		"*OOOOOOOOO*.....",
		"*OOOOOOOO*......",
		"*OOOOOOO*.......",
		"*OOOOOOO*.......",
		"*OOOOOOOO*......",
		"*OOOO**OOO*.....",
		"*OOO*..*OOO*....",
		"*OO*....*OOO*...",
		"*O*......*OOO*..",
		"**........*OOO*.",
		"*..........*OOO*",
		"............*OO*",
		".............***"
	};
	int x, y;

	for (y = 0; y < 16; y++) {
		for (x = 0; x < 16; x++) {
			if (cursor[y][x] == '*') {
				mouse[y * 16 + x] = COL8_000000;
			}
			if (cursor[y][x] == 'O') {
				mouse[y * 16 + x] = COL8_FFFFFF;
			}
			if (cursor[y][x] == '.') {
				mouse[y * 16 + x] = bc;
			}
		}
	}
	return;
}

void putblock8_8(char *vram, int vxsize, int pxsize,
	int pysize, int px0, int py0, char *buf, int bxsize)
{
	int x, y;
	for (y = 0; y < pysize; y++) {
		for (x = 0; x < pxsize; x++) {
			vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
		}
	}
	return;
}

dsctbl.c为负责初始化GDT和IDT的函数文件,其中我们先初始化GDT,这样会给编程带来方便:

/* filename:    dsctbl.c
 * description: 负责GDT和IDT的初始化工作
 * author:      Howard
 * date:        2013-11-28
 * version:     v1.0
 */

#include "bootpack.h"

void init_gdtidt(void)
{
	struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) 0x00270000;
	struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) 0x0026f800;
	int i;
	/*GDT初始化*/
	for (i=0; i<8192; i++){
		set_segmdesc(gdt+i, 0, 0, 0);
	}
	set_segmdesc(gdt+1, 0xffffffff, 0x00000000, 0x4092);
	set_segmdesc(gdt+2, 0x0007ffff, 0x00280000, 0x409a);
	load_gdtr(0xffff, 0x00270000);
	
	for (i=0; i<256; i++){
		set_gatedesc(idt+i, 0, 0, 0);
	}
	load_idtr(0x7ff, 0x0026f800);
	/*idt处理函数*/
	set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
	set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32);
	set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);
	return;
}

void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
	if (limit>0xfffff){
		ar |= 0x8000;
		limit /= 0x1000;
	}
	sd->limit_low	 = limit & 0xffff;
	sd->base_low	 = base & 0xffff;
	sd->base_mid	 	 = (base >> 16) & 0xff;
	sd->access_right = ar & 0xff;
	sd->limit_high	 = ((limit>>16) & 0x0f) | ((ar >> 8) & 0xf0);
	sd->base_high	 = (base >> 24) & 0xff;
	return;
}
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar)
{
	gd->offset_low	 = offset & 0xffff;
	gd->selector	 = selector;
	gd->dw_count	 = (ar>>8) & 0xff;
	gd->access_right = ar & 0xff;
	gd->offset_high	 = (offset>>16) & 0xffff;
	return;
}

bootpack.h为我们系统个文件函数和变量的声明:

/* filename:    bootpack.h
 * description: 函数的声明与变量的定义
 * author:      Howard
 * date:        2013-11-28
 * version:     v1.0
 */


/*ucan23.nas*/
struct BOOTINFO{
	char cyls;
	char leds;
	char vmode;
	char reserve;
	short scrnx;
	short scrny;
	char *vram;
};
#define ADR_BOOTINFO 	 0x00000ff0

/*naskfunc.nas*/
/*告诉C编译器,有函数在别的文件里*/
void io_hlt(void);
void io_cli(void);
void io_sti(void);
void io_stihlt(void);
int io_in8(int port);
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 asm_inthandler21(void);
void asm_inthandler27(void);
void asm_inthandler2c(void);
void init_screen(char *vram, int xsize, int ysize);
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);
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);
void putblock8_8(char *vram, int vxsize, int pxsize,
	int pysize, int px0, int py0, char *buf, int bxsize);
void init_mouse_cursor8(char *mouse, char bc);

#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



struct SEGMENT_DESCRIPTOR{
	short limit_low, base_low;
	char base_mid, access_right;
	char limit_high, base_high;
};

struct GATE_DESCRIPTOR{
	short offset_low, selector;
	char dw_count, access_right;
	short offset_high;
};

void init_gdtidt(void);
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);
#define ADR_IDT			0x0026f800
#define LIMIT_IDT		0x000007ff
#define ADR_GDT			0x00270000
#define LIMIT_GDT		0x0000ffff
#define ADR_BOTPAK		0x00280000
#define LIMIT_BOTPAK	0x0007ffff
#define AR_DATA32_RW	0x4092
#define AR_CODE32_ER	0x409a
#define AR_INTGATE32	0x008e

/*int.c*/

void init_pic(void);
void inthandler21(int *esp);
void inthandler2c(int *esp);
void inthandler27(int *esp);
#define  PIC0_ICW1				0x0020
#define  PIC0_OCW2				0x0020
#define  PIC0_IMR				0x0021
#define  PIC0_ICW2				0x0021
#define  PIC0_ICW3				0x0021
#define  PIC0_ICW4				0x0021
#define  PIC1_ICW1				0x00a0
#define  PIC1_OCW2				0x00a0
#define  PIC1_IMR				0x00a1
#define  PIC1_ICW2				0x00a1
#define  PIC1_ICW3				0x00a1
#define  PIC1_ICW4				0x00a1
#define PORT_KEYDAT				0x0060
#define PORT_KEYSTA				0x0064
#define PORT_KEYCMD				0x0064
#define KEYSTA_SEND_NOTREADY	0x02
#define KEYCMD_WRITE_MODE		0x60
#define KBC_MODE				0x47

struct MOUSE_DEC {
	unsigned char buf[3], phase;
	int x, y, btn;
};/*存放鼠标解码数据的结构体*/

void wait_KBC_sendready(void);
void init_keyboard(void);
#define KEYCMD_SENDTO_MOUSE 	0xd4
#define MOUSECMD_ENABLE			0xf4
void enable_mouse(struct MOUSE_DEC *mdec);
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat);
/*struct KEYBUF{
	unsigned char data[32];
	int next_r, next_w, len;
};
*/
/*fifo.c*/

struct FIFO8{
	unsigned char *buf;
	int p, q, size, free, flags;
};

void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf);
int fifo8_put(struct FIFO8 *fifo, unsigned char data);
int fifo8_get(struct FIFO8 *fifo);
int fifo8_status(struct FIFO8 *fifo);

int.c文件为中断处理文件:

/* filename:    int.c
 * description: the int operations
 * author:      Howard
 * date:        2013-11-28
 * version:     v1.0
 */

#include "bootpack.h"

void init_pic(void)
{
	io_out8(PIC0_IMR, 0xff);
	io_out8(PIC1_IMR, 0xff);

	io_out8(PIC0_ICW1, 0x11);
	io_out8(PIC0_ICW2, 0x20);
	io_out8(PIC0_ICW3, 1 << 2);
	io_out8(PIC0_ICW4, 0x01);
	
	io_out8(PIC1_ICW1, 0x11);
	io_out8(PIC1_ICW2, 0x28);
	io_out8(PIC1_ICW3, 2);
	io_out8(PIC1_ICW4, 0x01);
	
	io_out8(PIC0_IMR, 0xfb);
	io_out8(PIC1_IMR, 0xff);
	
	return;

}

struct FIFO8 keyfifo, mousefifo;

void inthandler21(int *esp)
{
	/*ps/2键盘中断*/
	//struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
	unsigned char data;
	io_out8(PIC0_OCW2, 0x61);
	data = io_in8(PORT_KEYDAT);
	
	fifo8_put(&keyfifo, data);
	/*if (keybuf.len<32){
		keybuf.data[keybuf.next_w] = data;
		keybuf.len ++;
		keybuf.next_w ++;
		if (keybuf.next_w == 32) {
			keybuf.next_w = 0;
		}
	}
	*/
	
	return;
}

void inthandler2c(int *esp)
{
	/*ps/2鼠标中断*/
	unsigned char data;
	io_out8(PIC1_OCW2, 0x64); /*通知PIC1 IRQ-12的受理已经完成*/
	io_out8(PIC0_OCW2, 0x62); /*通知PIC0 IRQ-02的受理已经完成*/
	data = io_in8(PORT_KEYDAT);
	fifo8_put(&mousefifo, data);
	return;
}

void inthandler27(int *esp)
{
	io_out8(PIC0_OCW2, 0x67);
	return;
}

fifo.c文件为缓冲区操作文件:

#include "bootpack.h"

#define FLAGS_OVERRUN		0x0001

void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
{
	fifo->size = size;
	fifo->buf = buf;
	fifo->free = size;
	fifo->flags = 0;
	fifo->p = 0;
	fifo->q = 0;
	return;
}

int fifo8_put(struct FIFO8 *fifo, unsigned char data)
{
	/*向FIFO传送数据并保存*/
	if (0==fifo->free){
		/*溢出*/
		fifo->flags |= FLAGS_OVERRUN;
		return -1;
	}
	fifo->buf[fifo->p] = data;
	fifo->p ++;
	if (fifo->p == fifo->size){
		fifo->p = 0;
	}
	fifo->free --;
	return;
}

int fifo8_get(struct FIFO8 *fifo)
{
	/*从FIFO读取一个数据*/
	int data;
	if (fifo->free == fifo->size){
		/*缓冲区为空,没有数据*/
		return -1;
	}
	data = fifo->buf[fifo->q];
	fifo->q ++;
	if (fifo->q == fifo->size){
		fifo->q = 0;
	}
	fifo->free ++;
	
	return data;
}
int fifo8_status(struct FIFO8 *fifo)
{
	/*返回缓冲区中还有多少数据*/
	return (fifo->size - fifo->free);
}

中断操作所需要的汇编函数:

[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[OPTIMIZE 1]
[OPTION 1]
[BITS 32]
	EXTERN	_load_gdtr
	EXTERN	_load_idtr
	EXTERN	_asm_inthandler21
	EXTERN	_asm_inthandler27
	EXTERN	_asm_inthandler2c
[FILE "dsctbl.c"]
[SECTION .text]
	GLOBAL	_init_gdtidt
_init_gdtidt:
	PUSH	EBP
	MOV	EBP,ESP
	PUSH	ESI
	PUSH	EBX
	MOV	ESI,2555904
	MOV	EBX,8191
L6:
	PUSH	0
	PUSH	0
	PUSH	0
	PUSH	ESI
	ADD	ESI,8
	CALL	_set_segmdesc
	ADD	ESP,16
	DEC	EBX
	JNS	L6
	PUSH	16530
	MOV	ESI,2553856
	PUSH	0
	MOV	EBX,255
	PUSH	-1
	PUSH	2555912
	CALL	_set_segmdesc
	PUSH	16538
	PUSH	2621440
	PUSH	524287
	PUSH	2555920
	CALL	_set_segmdesc
	ADD	ESP,32
	PUSH	2555904
	PUSH	65535
	CALL	_load_gdtr
	POP	EAX
	POP	EDX
L11:
	PUSH	0
	PUSH	0
	PUSH	0
	PUSH	ESI
	ADD	ESI,8
	CALL	_set_gatedesc
	ADD	ESP,16
	DEC	EBX
	JNS	L11
	PUSH	2553856
	PUSH	2047
	CALL	_load_idtr
	PUSH	142
	PUSH	16
	PUSH	_asm_inthandler21
	PUSH	2554120
	CALL	_set_gatedesc
	PUSH	142
	PUSH	16
	PUSH	_asm_inthandler27
	PUSH	2554168
	CALL	_set_gatedesc
	ADD	ESP,40
	PUSH	142
	PUSH	16
	PUSH	_asm_inthandler2c
	PUSH	2554208
	CALL	_set_gatedesc
	LEA	ESP,DWORD [-8+EBP]
	POP	EBX
	POP	ESI
	POP	EBP
	RET
	GLOBAL	_set_segmdesc
_set_segmdesc:
	PUSH	EBP
	MOV	EBP,ESP
	PUSH	EBX
	MOV	EDX,DWORD [12+EBP]
	MOV	ECX,DWORD [16+EBP]
	MOV	EBX,DWORD [8+EBP]
	MOV	EAX,DWORD [20+EBP]
	CMP	EDX,1048575
	JBE	L17
	SHR	EDX,12
	OR	EAX,32768
L17:
	MOV	WORD [EBX],DX
	MOV	BYTE [5+EBX],AL
	SHR	EDX,16
	SAR	EAX,8
	AND	EDX,15
	MOV	WORD [2+EBX],CX
	AND	EAX,-16
	SAR	ECX,16
	OR	EDX,EAX
	MOV	BYTE [4+EBX],CL
	MOV	BYTE [6+EBX],DL
	SAR	ECX,8
	MOV	BYTE [7+EBX],CL
	POP	EBX
	POP	EBP
	RET
	GLOBAL	_set_gatedesc
_set_gatedesc:
	PUSH	EBP
	MOV	EBP,ESP
	PUSH	EBX
	MOV	EDX,DWORD [8+EBP]
	MOV	EAX,DWORD [16+EBP]
	MOV	EBX,DWORD [20+EBP]
	MOV	ECX,DWORD [12+EBP]
	MOV	WORD [2+EDX],AX
	MOV	BYTE [5+EDX],BL
	MOV	WORD [EDX],CX
	MOV	EAX,EBX
	SAR	EAX,8
	SAR	ECX,16
	MOV	BYTE [4+EDX],AL
	MOV	WORD [6+EDX],CX
	POP	EBX
	POP	EBP
	RET
最后为我们的Makefile文件:

OBJS_BOOTPACK = bootpack.obj naskfunc.obj yezfont.obj graphic.obj dsctbl.obj \
				int.obj fifo.obj

TOOLPATH = ../tolset/z_tools/
INCPATH	 = ../tolset/z_tools/haribote/

MAKE	 = $(TOOLPATH)make.exe -r
NASK	 = $(TOOLPATH)nask.exe
CC1		 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM	 = $(TOOLPATH)obj2bim.exe
MAKEFONT = $(TOOLPATH)makefont.exe
BIN2OBJ  = $(TOOLPATH)bin2obj.exe
BIM2HRB	 = $(TOOLPATH)bim2hrb.exe
RULEFILE = $(TOOLPATH)haribote/haribote.rul
EDIMG	 = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
COPY	 = copy
DEL		 = del

default:
	$(MAKE) img
ucan23ipl.bin: ucan23ipl.nas Makefile
	$(NASK) ucan23ipl.nas ucan23ipl.bin ucan23ipl.lst

ucan23.bin: ucan23.nas Makefile
	$(NASK) ucan23.nas ucan23.bin ucan23.lst
#bootpack.gas: bootpack.c Makefile
#	$(CC1) -o bootpack.gas bootpack.c
	
#bootpack.nas: bootpack.gas Makefile
#	$(GAS2NASK) bootpack.gas bootpack.nas
	
#bootpack.obj: bootpack.nas Makefile
#	$(NASK) bootpack.nas bootpack.obj bookpack.lst

#naskfunc.obj: naskfunc.nas Makefile
#	$(NASK) naskfunc.nas naskfunc.obj naskfunc.lst

yezfont.bin: yezfont.txt Makefile
	$(MAKEFONT) yezfont.txt yezfont.bin
	
yezfont.obj: yezfont.bin Makefile
	$(BIN2OBJ) yezfont.bin yezfont.obj _yezfont
	
#graphic.gas: graphic.c Makefile
#	$(CC1) -o graphic.gas graphic.c
	
#graphic.nas: graphic.gas Makefile
#	$(GAS2NASK) graphic.gas graphic.nas
	
#graphic.obj: graphic.nas Makefile
#	$(NASK) graphic.nas graphic.obj graphic.lst 
	
#dsctbl.gas: dsctbl.c Makefile
#	$(CC1) -o dsctbl.gas dsctbl.c
	
#dsctbl.nas: dsctbl.gas Makefile
#	$(GAS2NASK) dsctbl.gas dsctbl.nas
	
#dsctbl.obj: dsctbl.nas Makefile
#	$(NASK) dsctbl.nas dsctbl.obj dsctbl.lst
	
#bootpack.bim: bootpack.obj naskfunc.obj yezfont.obj graphic.obj dsctbl.obj Makefile
#	$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
#	bootpack.obj naskfunc.obj yezfont.obj graphic.obj dsctbl.obj

bootpack.bim: $(OBJS_BOOTPACK) Makefile
	$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
	$(OBJS_BOOTPACK)
	
bootpack.hrb: bootpack.bim Makefile
	$(BIM2HRB) bootpack.bim bootpack.hrb 0
	
ucan23.sys: ucan23.bin bootpack.hrb Makefile
	copy /B ucan23.bin+bootpack.hrb ucan23.sys
	
ucan23.img: ucan23ipl.bin ucan23.sys Makefile
	$(EDIMG) imgin:../tolset/z_tools/fdimg0at.tek \
	wbinimg src:ucan23ipl.bin len:512 from:0 to:0 \
	copy from:ucan23.sys to:@: \
	imgout:ucan23.img
	
%.gas: %.c Makefile
	$(CC1) -o $*.gas $*.c
	
%.nas: %.gas Makefile
	$(GAS2NASK) $*.gas $*.nas
	
%.obj: %.nas Makefile
	$(NASK) $*.nas $*.obj $*.lst
	

asm:
	$(MAKE) ucan23ipl.bin
	
img:
	$(MAKE) ucan23.img
	
run:
	$(MAKE) img
	$(COPY) ucan23.img ..\tolset\z_tools\qemu\fdimage0.bin
	$(MAKE) -C ../tolset/z_tools/qemu
	
install:
	$(MAKE) img
	$(IMGTOL) w a: ucan23.img
	
clean:
	-$(DEL) *.bin
	-$(DEL) *.lst
	-$(DEL) *.gas
	-$(DEL) *.obj
	-$(DEL) bootpack.nas
	-$(DEL) bootpack.map
	-$(DEL) bootpack.bim
	-$(DEL) bootpack.hrb
	-$(DEL) ucan23.sys
	
src_only:
	$(MAKE) clean
	-$(DEL) ucan23.img



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值