操作系统实践之设置中断

来源:互联网 发布:js 动态加载js 编辑:程序博客网 时间:2024/05/24 03:33

  在保护模式下设置中断的步骤如下:

  初始化8259A中断控制器,设置IDT的内容

PUBLIC void init_8259A()
{
 out_byte(INT_M_CTL, 0x11)  // Master 8259, ICW1.
 out_byte(INT_S_CTL, 0x11)  // Slave  8259, ICW1.
 out_byte(INT_M_CTLMASK, INT_VECTOR_IRQ0)// Master 8259, ICW2. 

 out_byte(INT_S_CTLMASK, INT_VECTOR_IRQ8)// Slave  8259, ICW2.

 out_byte(INT_M_CTLMASK, 0x4)  
 out_byte(INT_S_CTLMASK, 0x2)  

 out_byte(INT_M_CTLMASK, 0x1)  // Master 8259, ICW4.
 out_byte(INT_S_CTLMASK, 0x1)  // Slave  8259, ICW4.

 out_byte(INT_M_CTLMASK, 0xFE)// Master 8259, OCW1. 
 out_byte(INT_S_CTLMASK, 0xFF)// Slave  8259, OCW1. 
 

  以上设置IDT中的中断门

    init_idt_desc(INT_VECTOR_DIVIDE,    DA_386IGate, divide_error,        PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_DEBUG,        DA_386IGate, single_step_exception,    PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_NMI,        DA_386IGate, nmi,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_BREAKPOINT,    DA_386IGate, breakpoint_exception,    PRIVILEGE_USER);
    init_idt_desc(INT_VECTOR_OVERFLOW,    DA_386IGate, overflow,            PRIVILEGE_USER);
    init_idt_desc(INT_VECTOR_BOUNDS,    DA_386IGate, bounds_check,        PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_INVAL_OP,    DA_386IGate, inval_opcode,        PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_COPROC_NOT,    DA_386IGate, copr_not_available,    PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_DOUBLE_FAULT,    DA_386IGate, double_fault,        PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_COPROC_SEG,    DA_386IGate, copr_seg_overrun,        PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_INVAL_TSS,    DA_386IGate, inval_tss,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_SEG_NOT,    DA_386IGate, segment_not_present,    PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_STACK_FAULT,    DA_386IGate, stack_exception,        PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_PROTECTION,    DA_386IGate, general_protection,    PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_PAGE_FAULT,    DA_386IGate, page_fault,        PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_COPROC_ERR,    DA_386IGate, copr_error,        PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ0 0,    DA_386IGate, hwint00,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ0 1,    DA_386IGate, hwint01,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ0 2,    DA_386IGate, hwint02,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ0 3,    DA_386IGate, hwint03,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ0 4,    DA_386IGate, hwint04,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ0 5,    DA_386IGate, hwint05,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ0 6,    DA_386IGate, hwint06,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ0 7,    DA_386IGate, hwint07,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ8 0,    DA_386IGate, hwint08,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ8 1,    DA_386IGate, hwint09,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ8 2,    DA_386IGate, hwint10,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ8 3,    DA_386IGate, hwint11,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ8 4,    DA_386IGate, hwint12,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ8 5,    DA_386IGate, hwint13,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ8 6,    DA_386IGate, hwint14,            PRIVILEGE_KRNL);
    init_idt_desc(INT_VECTOR_IRQ8 7,    DA_386IGate, hwint15,            PRIVILEGE_KRNL);

中断处理函数divide_error-copr_error,hwint00-hwint15在kernel.asm中定义

   外部中断hwint00-hwint15是通过宏定义的

%macro hwint_master 1
 push %1
 call spurious_irq
 add esp, 4
 mov al, 20h
 out 20h, al
 iretd
%endmacro

  可以看出实际上中断函数什么都没有做,只是调用了一个显示的方法,然后返回,其中mov al,20h;out 20h,al是发送给8259A的以便继续相应中断。这段话在时钟中断下工作的很好,可以不断的显示中断信息,但是对于键盘就不行了,只显示了一次信息就不再相应中断了,起初我百思不得其解,后来还是在书中找到了答案,在第7章中有说明,必须把键盘扫描码从8042控制器中取出,键盘才能继续响应操作。

0 0