1 分割源文件
观察我们昨天写好的bookpack.c主文件,发现它已达到三百多行,这样对不利于我们的维护,为此,我们将其对os功能除了的函数进行分类,独立到一个C文件中。而且bookpack主函数中对于函数的声明部分未免有点过于庞大,我们使用C中的头文件这一概念,独立出一个bookpack.h头文件,对于我们需要使用到的一些功能函数进行声明,这样我们在bookpack.c中只需#include bookpack.h,这样就可以使用到其他c文件中的函数了:
其中独立出来的graphic.c,用于处理图像:
其中用于处理中断的dsctbl.c文件:
bookpack.h头文件:
这时我们的bookpack.c主函数将会是这样:
嗯,整理后就变得十分简洁了。但是Makefile文件只是对于特定的C文件进行编译生成,这样以后我们在不断的加入更多的C文件时又需要频繁修改了,为此我们修改Makefile将适用于所有的C文件:
将链接编译特定的C文件用*号替代就可以对任意的C文件自动编译链接了。
2 中断处理程序的制作
我们需要控制键盘鼠标,否则我们制作处理的"操作系统"就没多大意义了,这里涉及到中断的知识,其中键盘是IRQ1,鼠标是IRQ12,中断程序的制作单单靠C无法实现,我们需要借助汇编的力量,向naskfuc.nas中继续添加几个用于控制键鼠中断的函数吧:
_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
新建一个int.c文件用于处理鼠标键盘输入:
/* 中断关系 */
#include "bootpack.h"
void init_pic(void)
/* PIC初始化 */
{
io_out8(PIC0_IMR, 0xff ); /* 不接受全部分配 */
io_out8(PIC1_IMR, 0xff ); /* 不接受全部分配 */
io_out8(PIC0_ICW1, 0x11 ); /* 边缘触发模式 */
io_out8(PIC0_ICW2, 0x20 ); /* LQ0-7以INT20-27接受 */
io_out8(PIC0_ICW3, 1 << 2); /* PIC1在IQ2连接*/
io_out8(PIC0_ICW4, 0x01 ); /* 无缓冲模式 */
io_out8(PIC1_ICW1, 0x11 ); /* 边缘触发模式 */
io_out8(PIC1_ICW2, 0x28 ); /* LQ8-15由INT28-2f接受 */
io_out8(PIC1_ICW3, 2 ); /* PIC1在IQ2连接 */
io_out8(PIC1_ICW4, 0x01 ); /* 无缓冲模式 */
io_out8(PIC0_IMR, 0xfb ); /* 11111011 PIC1除此之外全部禁止 */
io_out8(PIC1_IMR, 0xff ); /* 11111111 不接受全部分配 */
return;
}
void inthandler21(int *esp)
/* 从PS / 2键盘的插入 */
{
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
boxfill8(binfo->vram, binfo->scrnx, COL8_000000, 0, 0, 32 * 8 - 1, 15);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "INT 21 (IRQ-1) : PS/2 keyboard");
for (;;) {
io_hlt();
}
}
void inthandler2c(int *esp)
/* 从PS / 2鼠标的插入 */
{
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
boxfill8(binfo->vram, binfo->scrnx, COL8_000000, 0, 0, 32 * 8 - 1, 15);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "INT 2C (IRQ-12) : PS/2 mouse");
for (;;) {
io_hlt();
}
}
void inthandler27(int *esp)
/* 从PIC0中的不完全加入对策
在Athlon 66X2机等方面,根据芯片组的情况,在PIC的初始化时,这个插孔只有一次
这个AA制处理函数,对那个分配什么都不做过得过
为什么什么都不做就好了?
→这是由于PIC初始化时的电噪声而产生的。
没有必要认真地处理些什么 */
{
io_out8(PIC0_OCW2, 0x67); /*向PIC通知ISQ-07受理完成 */
return;
}
主函数bookpack.c中调用int中断函数:
/* bootpack主函数*/
#include "bootpack.h"
#include <stdio.h>
void HariMain(void)
{
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
char s[40], mcursor[256];
int mx, my;
init_gdtidt();
init_pic();
io_sti(); /* IDT/PICの因为初始化结束了,所以解除了CPU的中断禁止*/
init_palette();
init_screen8(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);
sprintf(s, "(%d, %d)", mx, my);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s);
io_out8(PIC0_IMR, 0xf9); /* PIC1允许键盘(11111001) */
io_out8(PIC1_IMR, 0xef); /* 允许鼠标(11101111) */
for (;;) {
io_hlt();
}
}
使用make run命令:
我们进入虚拟机键盘输入:
成功调用中断处理键盘输入了。