注册 登录
编程论坛 操作系统内核开发

求助:关于IDT和中断的设置问题

kd83kdi93 发布于 2013-10-08 22:50, 5150 次点击
先跳入32位保护模式后进入这个c函数

void show()
{
   
    char ss[]="Asd";
    bootinfo.p = (bit_8 *)0xa0000;   
    bootinfo.xsize = 320;

    initpalette();  //设置调色板
    initscreen();   //初始化窗口
    showstr(bootinfo.p,bootinfo.xsize,5,5,COLOR_3,ss);   //显示文字Asd   
   
    initGDT();      
    initIDT();
    initPIC();
                    
    io_sti();
  }
关键是initGDT initIDT initPIC  这三个函数分别是初始化GDT 、 IDT 和PIC   我不知道把设置PIC放在最后对不对, 我在initGDT和initIDT中都重新加载了新的GDT和IDT加载函数是用汇编写的,in_out8是把一个值写入一个端口,这些函数细节如下

load_gdtr:
mov edx,[esp+4]
lgdt [edx]
ret

load_idtr:
mov edx,[esp+4]
lidt [edx]
ret

io_out8:
mov edx,[esp+4]
mov al,[esp+8]
out dx,al
ret
然后这三个c函数
#define AR_DATA32_RW        0x4092
#define AR_CODE32_ER        0x409a
#define AR_INTGATE32        0x008e

void initGDT()
{
        
    setdesc(GDT_NEW + 1, 0xffffffff,   0x00000000, AR_CODE32_ER);
    setdesc(GDT_NEW + 2, 0xffffffff,   0x00000000, AR_DATA32_RW);
    *((bit_16 *)&GDTR_NEW) = 0xffff;
    *((bit_32 *)(&GDTR_NEW[2])) = (bit_32)&GDT_NEW;
    load_gdtr((bit_32)&GDTR_NEW);
    return;
}

void setdesc(DESCRIPTOR * p,bit_32 limit,bit_32 base,bit_16 access)
{
    if(limit > 0xfffff)
    {
        access |= 0x8000;
        limit /= 0x1000;
    }
    p -> base_low = base & 0xffff;
    p -> base_mid = (base >> 16) & 0xff;
    p -> base_high = (base >> 24) & 0xff;
    p -> access = access & 0xff;
    p -> limit_low = limit & 0xffff;
    p -> limit_high = ((limit >> 16) & 0x0f) | ((access >> 8) & 0xf0);

    return;
}

void setgate(GATE * p,bit_32 offset,bit_16 selector,bit_16 access)
{
    p -> offset_low = offset & 0xffff;
    p -> offset_high = (offset >> 16) & 0xffff;
    p -> selector = selector;
    p -> access = access & 0xff;
    p -> count = (access >> 8) & 0xff;

    return;
}

void initIDT()
{
   
    setgate(&IDT_NEW[0x21],(bit_32)asm_inthandler21,1 * 8,AR_INTGATE32);
   
    *((bit_16 *)(&IDTR_NEW)) = sizeof(GATE) * 256 - 1;
    *((bit_32 *)(&IDTR_NEW[2])) = (bit_32)(&IDT_NEW);
    load_idtr((bit_32)&IDTR_NEW);
   
   
    return;
}


#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
void initPIC()
{
    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;
}


void inthandler21(bit_32 * esp)
{
    char ss[]="keyboard";
    showstr(bootinfo.p,bootinfo.xsize,25,25,COLOR_3,ss);
    return;
}

1 回复
#2
ditg2020-06-25 16:19
有一种实现方法:实模式初始化IDT和GDT后设置PIC,保护模式只用设置setgate
1