05day 文字显示 GDT/IDT初始化

来源:互联网 发布:android 爱奇艺源码 编辑:程序博客网 时间:2024/05/28 11:48

我们想向屏幕上输出ABC 123

void HariMain(void){    struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;    extern char hankaku[4096];    init_palette();    init_screen(binfo->vram, binfo->scrnx, binfo->scrny);    putfont8(binfo->vram, binfo->scrnx,  8, 8, COL8_FFFFFF, hankaku + 'A' * 16);    putfont8(binfo->vram, binfo->scrnx, 16, 8, COL8_FFFFFF, hankaku + 'B' * 16);    putfont8(binfo->vram, binfo->scrnx, 24, 8, COL8_FFFFFF, hankaku + 'C' * 16);    putfont8(binfo->vram, binfo->scrnx, 40, 8, COL8_FFFFFF, hankaku + '1' * 16);    putfont8(binfo->vram, binfo->scrnx, 48, 8, COL8_FFFFFF, hankaku + '2' * 16);    putfont8(binfo->vram, binfo->scrnx, 56, 8, COL8_FFFFFF, hankaku + '3' * 16);    for (;;) {        io_hlt();    }}

输出字体函数如下

void putfont8(char *vram, int xsize, int x, int y, char c, char *font){    int i;    char *p, d /* data */;    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 hankaku[4096];    for (; *s != 0x00; s++) {        putfont8(vram, xsize, x, y, c, hankaku + *s * 16);        x += 8;    }    return;}

不管怎么说 我觉得书的作者做的画面还是蛮帅的。。

使用stdio.hh 的 sprintf

    sprintf(s, "scrnx = %d", binfo->scrnx);    putfonts8_asc(binfo->vram, binfo->scrnx, 16, 64, COL8_FFFFFF, s);

以上代码存在于主函数中。
我们也可以在屏幕上见到结果。


显示鼠标指针
这并不是什么难事,问题是我们应该怎么能够移动它。
首先要了解GDT IDT,其实他们都是有关CPU的设定。

在32位下 为了表示一个段,需要有一下信息: 段的大小,起始地址,段的管理属性。CPU用8个字节来表示这些信息,而用于指定段的寄存器只有16位,由于CPU设计上的原因,段寄存器的低3位不能使用,所以我们能使用的只有13位,能够处理 0~8191的区域。

GDT 就是全局段号记录表 (global segment descriptor table),我们将有关段的信息整齐的排列在内粗你的某个地方,然后将内存的其实地址和有效谁定个数放在CPU内被称作为GDTR的特殊寄存器中,设定就完成了。

IDT 就是 interrupt descriptor table ,就是中断记录表。当CPU遇到外部状况变化或者是内部偶然错误就会切换过去处理突发事件。这就是中断功能的实现。

{    struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;    char s[40], mcursor[256];    int mx, my;    init_gdtidt();    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);    for (;;) {        io_hlt();    }}

主函数中init_gdtidt。

看init_gdtidt

    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){    struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) 0x00270000;//0x270000~0x27ffff    struct GATE_DESCRIPTOR    *idt = (struct GATE_DESCRIPTOR    *) 0x0026f800;//0x26f800~0x26ffff    int i;    /* GDT初始化 */    for (i = 0; i < 8192; i++) {        set_segmdesc(gdt + i, 0, 0, 0);    }    set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, 0x4092);//段号1 起始地址0    set_segmdesc(gdt + 2, 0x0007ffff, 0x00280000, 0x409a);//段号2 其实地址0x280000 长度0x7ffff 也就是512kb 这正好是为我们的bootpack.hrb准备的     load_gdtr(0xffff, 0x00270000);//通过汇编语言给GDTR赋值    /* 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;}
0 0
原创粉丝点击