作者:兰毛zg | 来源:互联网 | 2023-07-26 10:09
1.分割源文件(06_dayharib03a) bookpack.c 拆分为以下三个文件: graphic.c:绘画处理 dsctbl.c:GD
1.分割源文件(06_day/harib03a)
bookpack.c 拆分为以下三个文件:
graphic.c:绘画处理
dsctbl.c : GDT,IDT等的处理
bootpack.c 其他处理
2.整理 makefile(06_day/harib03b)
前一节c 语言文件变多,原有文件增加多个单个文件的处理脚本,以后每增加新的C文件,都要去修改 MaleFile,不利于维护,现在将两种类型单个文件的处理抽象成两个一般规则:
%.gas : %.c MakeFile
$(cc1) -o $*.gas $*.c
%.nas : %.gas MakeFile
$(GAS2NASK) $*.gas $*.nas
Make.exe 首先寻找普通规则,再去找一般规则
3.整理头文件
将前述三个C文件中重复声明的函数和变量抽出来,生成一个bookpack.h文件,然后,各个c文件加上#include "bootpack.h"
4.naskfunc.nas里的_load_gdtr函数:
_load_gdtr: ;void load_gdtr(int limit,int addr)
MOV AX,[ESP + 4] ;limit
MOV [ESP+6],AX ;作者使用了技巧,[ESP + 8]存放的是地址
LGDT [ESP+6] ;给GDTR赋值,从指定地址(此处[ESP+6])读取六字节
RET
GDTR寄存器:48b(6字节),低16b是段上限‘
5.GDT结构和初始化代码的再次说明:
1) struct SEGMENT_DESCRIPTOR {
//只定义了与本书内容相关部分
short limit_low, //段上限低16b
short base_low; //段基址的低16b
char base_mid,//段基址的中8b,与前面低16b的组成段基址的低24b;
char access_right; //高4b称为扩展访问权
char limit_high, //段上限高8b
char base_high; //段基址的高8b
}; //GDT 8字节内容
2) void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
if (limit > 0xfffff) {
ar |= 0x8000; /* G_bit = 1 如果为1,则limit的单位是页,一页4kb*/
limit /= 0x1000;
}
sd->limit_low = limit & 0xffff;
sd->base_low = base & 0xffff; //段基址的低16b
sd->base_mid = (base >> 16) & 0xff; //段基址的中8b,与前面低16b的组成段基址的低24b
sd->access_right = ar & 0xff;
sd->limit_high = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);
sd->base_high = (base >> 24) & 0xff;
return;
}
3)ar的解释:
高4b:称为扩展访问权,"GD00",G指的是G bit,为1的话,段大小的单位不是字节,是页,一页4kb;D指段模式,1指32b,0代表16b
低8b:
0x00:未使用
0x92:系统专用,可读写,不可执行
0x9a:系统专用,可执行,可读不可写
0xf2:程序用,可读写,不可执行
0xfa:程序用,可执行,可读不可写
6.初始化PIC(06_day/harib03d)
PIC:可编程中断器
要移动鼠标,必须使用中断,欲用中断,先必须初始化GDT和IDT