下面是七八天的源码:
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.youkuaiyun.com/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