30天自制操作系统:第五天:文字显示与GDT/IDT初始化

第五天:文字显示与GDT/IDT初始化

1.从内存中读出保存的值.

昨天程序中300x200都是直接写入程序,本来应该从asmhead.nas先前保存的值中取,不然当画面模式改变时,系统就挂了.

所以得修改bootpack.c文件代码从asmhead.nas写入的内存中取值.

2.显示字符

原理:将每一个bit当成一个黑点,那么,字符a就可以当成下图所示:

30天自制操作系统:第五天:文字显示与GDT/IDT初始化


那么字符a要显示赋值给显卡的话,用字符数组表示就变成:

static char font_A[16]=
{0x00,0x18, 0x18, 0x18, 0x18,
0x24, 0x24, 0x24, 0x24, 0x7e,
0x42, 0x42,0x42, 0xe7, 0x00, 0x00
};

3.增加字体

作者自己写了一个字体生成小工具,可以将图像字符转成16进制数据.


30天自制操作系统:第五天:文字显示与GDT/IDT初始化

这个很简单,有c语言基础的一看就知道这个工具是怎么写的了.

生成的字体数据存到hankaku[4096]数组中,后边程序会调用.

4.显示鼠标指针

将鼠标大小定为16x16,先准备16x16的内存,然后写入鼠标指针的数据.

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

然后分别对* 0 . 进行颜色替换.

5.GDT和IDT初始化.

有分段,分页和中断的概念,自己百度吧.

GDT(全局段号记录表):

为了表示一个段,需要一下信息:

• 段的大小是多少.

• 段的起始地址在哪里.

• 段的管理属性(禁止写入,禁止执行,系统专用等).

cpu 用8个字节(64位)来表示这些信息. 表示段的寄存器只有16位,而且由于cpu设计上的原因,段寄存器的低3位不能使用,因此只有13位,能够处理的就只有位于0~8191的区域了. 因此能够定义8192个段, 而设定8192个段需要8192x8=65536(64kb), 将这64kb存到内存中表示,就是GDT.

IDT(中断记录表):

idt记录了0~255的中断号码与调用函数的对应关系.

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)
{
//随便选了内存地址0x00270000~0x0027ffff设为GDT.只是因为未被使用.
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);
}
//段号为1的段的属性为0x4092 , 歧视地址是0, 大小是0xffffffff,刚好是4GB.表示cpu所能管理的全部内存.
set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, 0x4092);
set_segmdesc(gdt + 2, 0x0007ffff, 0x00280000, 0x409a); //段号为2的段的属性为0x409a
//c语言不给能GDTR赋值.调用汇编给GDTR赋值.
load_gdtr(0xffff, 0x00270000);
/* IDT的初始化 */
for (i = 0; i < 256; i++) {
set_gatedesc(idt + i, 0, 0, 0);
}
load_idtr(0x7ff, 0x0026f800);
return;
}
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
if (limit > 0xfffff) {
ar |= 0x8000; /* G_bit = 1 */
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;
}

6.至此,就把GDT和IDT写入到内存中. 执行结果如下:


30天自制操作系统:第五天:文字显示与GDT/IDT初始化

展开阅读全文

页面更新:2024-05-24

标签:初始化   用字   赋值   黑点   数组   下图   先前   显卡   字符   图像   画面   操作系统   字体   内存   文字   程序   数据   科技

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top