| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1852 人关注过本帖
标题:一步步写操作系统之第三步:初步建立中断异常处理机制
只看楼主 加入收藏
miaowangjian
Rank: 2
等 级:论坛游民
帖 子:34
专家分:30
注 册:2010-1-29
结帖率:100%
收藏
 问题点数:0 回复次数:3 
一步步写操作系统之第三步:初步建立中断异常处理机制
建立中断异常处理机制,主要就是对8259A的初始化,建立中断描述符表。因为要对十来个已定义的异常进行处理,再加上16个外部中断的处理,代码量就显得很庞大了。
因为一时间也想不出更好的处理方案,所以就照搬《自己动手写操作系统》里的那一套方法用着先

具体的初始化流程为:
 kernel -> init_prot()  
     //在 init_prot()  调用init_8259A(),对8259A进行初始化,与以前的代码一样的,只是换成了c形式了。
     //调用init_8259A()后 就是重复init_idt_desc()函数对ide表进行初始化话,前十多个是异常处理,后16个是外部中断处理,最后是自定义中断
     //值得注意的是为外部中断处理函数建立了一个函数处理表,如此可以在之后灵活的设置修改中断的最终处理函数。

建立中断异常处理机制后(尽管是最简单的),就可以对其进行简单测试。

在kernel.c的main函数里,分别取消以下三个异常测试项的注释符,就可以看到异常信息显示在屏幕上。
  //测试异常
  //int 3        //测试调试断点异常
  //jmp 0x40:0   //测试常规保护错误异常
  //ud2            //测试无效操作码异常


对外部中断的测试:
  //测试外部中断
  //enable_irq(KEYBOARD_IRQ);  //开键盘中断
  //enable_irq(CLOCK_IRQ);  //开时钟中断

注意:因为一下子添加了很多代码,超出了最初在boot.c里设定加载内核4个扇区大小的限制,因此需要将加载的扇区数调大一些。

code:kernel.c(改)
程序代码:
//文件:kernel.c 
//功能:内核程序,目前功能为测试print.c里的几个输出函数 
//运行:run.exe自动会编译boot.c与生成img并调用Bochs运行此程序。 
//作者:miao 
//时间:2010-5-17 

#define YCBIT 32  //告诉编译器,以32位格式编译程序 
#define YCORG 0x0 //此值会对在编译时对变量函数等产生地址基址偏移量,简单起便,设置为0 
#include "global.h" 
#include "kernel.h" 
#include "print.h" 
#include "klib.h" 
#include "i8259.h" 

void init(); 

//内核入口点 
asm void main() 
{ 
  lgdt  cs:GdtPtr           //加载新的GDTR 

  mov   eax, SelectorVideo 
  mov   gs, ax              //视频段选择子(目的) 
  mov   eax, SelectorData32 //令32位代码段的变量(printPlace)可以读写 
  mov   ds, ax 

  call  init        //初始化函数 

  //测试异常 
  //int 3        //测试调试断点异常 
  //jmp 0x40:0   //测试常规保护错误异常 
  //ud2            //测试无效操作码异常 
   
  sti    //开中断 
  jmp  kernel_main 
} 

void init() 
{ 
  disp_str("================ init start =================\n"); 
  disp_str(" init idt -------------------------------- "); 
  init_prot(); //初始化IDT 
  disp_str("ok\n"); 
  disp_str("================ init end ===================\n"); 
} 

int kernel_main() 
{ 
  //测试外部中断 
  //enable_irq(KEYBOARD_IRQ);  //开键盘中断 
  //enable_irq(CLOCK_IRQ);  //开时钟中断 
   
  while(1); 
  return 0; 
} 

#include "print.c" 
#include "klib.c" 
#include "i8259.c"

code:klib.h(新)
程序代码:
//文件:klib.h 
//功能:klib头文件,内核需要用到的公共函数的声明等 
//作者:miao 
//时间:2010-5-16 

//向指定端口写入数据 
asm void out_byte(t_port port, t_8 value); 
//从指定端口读取数据 
asm t_8 in_byte(t_port port);  

code:klib.c(新)
程序代码:
//文件:klib.c 
//功能:定义内核需要用到的公共函数 
//作者:miao 
//时间:2010-5-16 

//向指定端口写入数据 
asm void out_byte(t_port port, t_8 value) 
{ 
  mov   edx, [esp + 4]    //port 
  mov   al, [esp + 4 + 4] //value 
  out   dx, al 
  nop   //一点延迟 
  nop 
  ret 
} 
//从指定端口读取数据 
asm t_8 in_byte(t_port port) 
{ 
  mov   edx, [esp + 4] //port 
  xor   eax, eax 
  in    al, dx 
  nop   //一点延迟 
  nop 
  ret 
}
code:i8259.h(新)
程序代码:
//文件:i8259.h 
//功能:i8259头文件,放置初始化8259A、以及设置中断需要用到的宏、数据结构定义、全局变量以及函数的声明等 
//作者:miao 
//时间:2010-5-16 

//8259A 中断控制端口 
#define  INT_M_CTL     0x20  //主:中断控制器输入输出端口 
#define  INT_M_CTLMASK 0x21  //主:通过此端口禁止指定的中断号 
#define  INT_S_CTL     0xA0  //从:次级中断控制器输入输出端口 
#define  INT_S_CTLMASK 0xA1  //从:通过此端口禁止指定的中断号 

//中断(异常)向量号 从0到255,共256个,前面0~13已定义,20~31Intel保留未使用,32~255用户自定义 
#define  INT_VECTOR_DIVIDE       0x0  //除法错 
#define  INT_VECTOR_DEBUG        0x1  //调试异常 
#define  INT_VECTOR_NMI          0x2  //非屏蔽中断 
#define  INT_VECTOR_BREAKPOINT   0x3  //调试断点 
#define  INT_VECTOR_OVERFLOW     0x4  //溢出 
#define  INT_VECTOR_BOUNDS       0x5  //越界 
#define  INT_VECTOR_INVAL_OP     0x6  //无效操作码 
#define  INT_VECTOR_COPROC_NOT   0x7  //设备不可用 
#define  INT_VECTOR_DOUBLE_FAULT 0x8  //双重错误 
#define  INT_VECTOR_COPROC_SEG   0x9  //协处理器段越界 
#define  INT_VECTOR_INVAL_TSS    0xA  //无效TSS 
#define  INT_VECTOR_SEG_NOT      0xB  //段不存在 
#define  INT_VECTOR_STACK_FAULT  0xC  //堆栈段错误 
#define  INT_VECTOR_PROTECTION   0xD  //常规保护错误 
#define  INT_VECTOR_PAGE_FAULT   0xE  //页错误 
//                               0xF  //Intel保留 
#define  INT_VECTOR_COPROC_ERR   0x10 //浮点错 
//                               0x14~0x1F //Intel保留未使用 
//0x20~0x2F,作为8259A的16个外部中断用 
#define  INT_VECTOR_IRQ0         0x20 //主:0x20~0x27 
#define  INT_VECTOR_IRQ8         0x28 //从:0x28~0x2F 
//                               0x30~0xFF //暂时不是用 

//硬件中断向量(打开或禁用某个外部中断时用) 
#define  CLOCK_IRQ     0 
#define  KEYBOARD_IRQ  1 

//386中断门类型值 
#define  DA_386IGate       0x8E    

//中断(异常)所具有的权限 
#define  PRIVILEGE_KRNL  0 
#define  PRIVILEGE_USER  3 

//8259A,主8个,从8个,一共有16个硬件中断 
#define NR_IRQ 16 

typedef void  (*t_pf_irq_handler)(int irq); //定义中断请求处理函数类型 
typedef void (*t_pf_int_handler)();         //定义硬件中断处理函数类型 

//为16个硬件中断创建一个函数指针表,每个硬件中断发生时调用对应的处理函数 
t_pf_irq_handler irq_table[NR_IRQ]; 

//门描述符 
struct GATE 
{ 
  t_16  offset_low;//Offset Low 
  t_16  selector;  //Selector 
  t_8   dcount;    //该字段只在调用门描述符中有效。 
                   //如果在利用调用门调用子程序时引起特权级的转换和堆栈的改变, 
                   //需要将外层堆栈中的参数复制到内层堆栈。 
                   //该双字计数字段就是用于说明这种情况发生时,要复制的双字参数的数量。 
  t_8  attr;       //P(1) DPL(2) DT(1) TYPE(4) 
  t_16 offset_high;//Offset High 
}; 

#define IDT_SIZE 64 
GATE idt[IDT_SIZE];//中断描述符表,最多可以定义256个,目前暂时申请64个 
t_8 idt_ptr[6];    //共6个字节0~15:Limit,16~47:Base 用作sidt以及lidt的参数 

//发生异常时,显示对应的异常错误信息 
char err_description[][64] =  
{ 
    "#DE Divide Error", 
    "#DB RESERVED", 
    "—  NMI Interrupt", 
    "#BP Breakpoint", 
    "#OF Overflow", 
    "#BR BOUND Range Exceeded", 
    "#UD Invalid Opcode (Undefined Opcode)", 
    "#NM Device Not Available (No Math Coprocessor)", 
    "#DF Double Fault", 
    "    Coprocessor Segment Overrun (reserved)", 
    "#TS Invalid TSS", 
    "#NP Segment Not Present", 
    "#SS Stack-Segment Fault", 
    "#GP General Protection", 
    "#PF Page Fault", 
    "—  (Intel reserved. Do not use.)", 
    "#MF x87 FPU Floating-Point Error (Math Fault)", 
    "#AC Alignment Check", 
    "#MC Machine Check", 
    "#XF SIMD Floating-Point Exception"
}; 

void init_prot();                 //初始化IDT函数 
asm void disable_irq(int irq);    //关闭特定的中断 
asm void enable_irq(int irq);     //打开特定的中断 
void put_irq_handler(int irq, t_pf_irq_handler handler);//向特定的中断注册处理函数

code:i8259.c(新)
程序代码:
//文件:i8259.c
//功能:初始化8259A、以及设置中断相关的函数 
//作者:miao 
//时间:2010-5-16 

//外部中断默认调用的函数 
void spurious_irq(int irq) 
{ 
  disp_str("spurious_irq: "); 
  disp_int(irq); 
  disp_str("\n"); 
} 

void init_8259A() 
{ 
  out_byte(INT_M_CTL,  0x11);      // 主 8259, ICW1 
  out_byte(INT_S_CTL,  0x11);      // 从  8259, ICW1 
  out_byte(INT_M_CTLMASK,  INT_VECTOR_IRQ0);  //主8259,ICW2.设置'主8259'的中断入口地址为 0x20 
  out_byte(INT_S_CTLMASK,  INT_VECTOR_IRQ8);  //从8259,ICW2.设置'从8259'的中断入口地址为 0x28 
  out_byte(INT_M_CTLMASK,  0x4);   // 主 8259, ICW3. IR2 对应 '从8259' 
  out_byte(INT_S_CTLMASK,  0x2);   // 从  8259, ICW3. 对应 '主8259' 的 IR2 
  out_byte(INT_M_CTLMASK,  0x1);   // 主 8259, ICW4 
  out_byte(INT_S_CTLMASK,  0x1);   // 从  8259, ICW4 
  //默认一开始屏蔽掉所有外部中断 
  out_byte(INT_M_CTLMASK,  0xFF);  // 主 8259, OCW1 
  out_byte(INT_S_CTLMASK,  0xFF);  // 从  8259, OCW1 

  int i; 
  for(i=0;i<NR_IRQ;i++) 
    irq_table[i]  = spurious_irq;  //为16个硬件中断处理函数指针表初始化一个默认的调用函数 
} 

//初始化386中断门 
void init_idt_desc(unsigned char vector, t_8 desc_type, t_pf_int_handler handler, unsigned char privilege) 
{ 
  GATE *p_gate  = &idt[vector]; 
  t_32  base  = (t_32)handler; 
  p_gate->offset_low = base & 0xFFFF; 
  p_gate->selector = SelectorCode32; 
  p_gate->dcount = 0; 
  p_gate->attr = desc_type | (privilege << 5); 
  p_gate->offset_high = (base >> 16) & 0xFFFF; 
} 

//异常处理函数,显示错误信息 
void exception_handler(int vec_no, int err_code, int eip, int cs, int eflags) 
{ 
  int i; 
  int text_color = 0xA0; 

  disp_pos = 0;  //从顶格开始显示错误信息 
   
  disp_color_str("Exception! --> ", text_color); 
  disp_color_str(err_description[vec_no], text_color); 
  disp_color_str("\nEFLAGS:", text_color); 
  disp_int(eflags); 
  disp_color_str(" CS:", text_color); 
  disp_int(cs); 
  disp_color_str(" EIP:", text_color); 
  disp_int(eip); 

  if(err_code != 0xFFFFFFFF) 
  { 
    disp_color_str("Error code:", text_color); 
    disp_int(err_code); 
  } 
} 

asm void exception() 
{ 
  call    exception_handler //显示错误信息 
  add     esp, 4*2     //让栈顶指向 EIP,堆栈中从顶向下依次是:EIP、CS、EFLAGS 
  hlt 
} 

//中断和异常 -- 异常,设置错误代码和中断号 
asm void divide_error() 
{ 
  push  0xFFFFFFFF  //没有错误代码 
  push  0           //vector_no  = 0 
  jmp     exception 
} 
asm void single_step_exception() 
{ 
  push  0xFFFFFFFF  //没有错误代码 
  push  1           //vector_no  = 1 
  jmp     exception 
} 
asm void nmi() 
{ 
  push  0xFFFFFFFF  //没有错误代码 
  push  2           //vector_no  = 2 
  jmp     exception 
} 
asm void breakpoint_exception() 
{ 
  push  0xFFFFFFFF  //没有错误代码 
  push  3           //vector_no  = 3 
  jmp     exception 
} 
asm void overflow() 
{ 
  push  0xFFFFFFFF  //没有错误代码 
  push  4           //vector_no  = 4 
  jmp     exception 
} 
asm void bounds_check() 
{ 
  push  0xFFFFFFFF  //没有错误代码 
  push  5           //vector_no  = 5 
  jmp     exception 
} 
asm void inval_opcode() 
{ 
  push  0xFFFFFFFF  //没有错误代码 
  push  6           //vector_no  = 6 
  jmp     exception 
} 
asm void copr_not_available() 
{ 
  push  0xFFFFFFFF  //没有错误代码 
  push  7           //vector_no  = 7 
  jmp     exception 
} 
asm void double_fault() 
{ 
  push  8           //vector_no  = 8 
  jmp     exception 
} 
asm void copr_seg_overrun() 
{ 
  push  0xFFFFFFFF  //没有错误代码 
  push  9           //vector_no  = 9 
  jmp     exception 
} 
asm void inval_tss() 
{ 
  push  10          //vector_no  = A 
  jmp     exception 
} 
asm void segment_not_present() 
{ 
  push  11          //vector_no  = B 
  jmp     exception 
} 
asm void stack_exception() 
{ 
  push  12          //vector_no  = C 
  jmp     exception 
} 
asm void general_protection() 
{ 
  push  13          //vector_no  = D 
  jmp     exception 
} 
asm void page_fault() 
{ 
  push  14          //vector_no  = E 
  jmp     exception 
} 
asm void copr_error() 
{ 
  push  0xFFFFFFFF  //没有错误代码 
  push  16          //vector_no  = 10h 
  jmp     exception 
} 

#define EOI 0x20 
//中断和异常 -- 硬件中断 
#define hwint_master(irq_No)                                                 \ 
  in      al, INT_M_CTLMASK       /* ┓                    */                \ 
  or      al, (1 << irq_No)       /* ┣ 屏蔽当前中断       */                \ 
  out     INT_M_CTLMASK, al       /* ┛                    */                \ 
  mov     al, EOI                 /* ┓置EOI位             */                \ 
  out     INT_M_CTL, al           /* ┛                    */                \ 
  sti     /* CPU在响应中断的过程中会自动关中断,这句之后就允许响应新的中断*/ \ 
  push    irq_No                             /* ┓                   */      \ 
  call    dword [&irq_table + 4 * irq_No]    /* ┣ 中断处理程序      */      \ 
  pop     ecx                                /* ┛                   */      \ 
  cli                                                                        \ 
  in      al, INT_M_CTLMASK        /* ┓                   */                \ 
  and     al, ~(1 << irq_No)       /* ┣ 恢复接受当前中断  */                \ 
  out     INT_M_CTLMASK, al        /* ┛                   */                \ 
  iretd                                                                      \ 
  ret                                                                        \ 

#pragma align(16) 
asm void hwint00()  //Interrupt routine for irq 0 (the clock). 
{ 
  hwint_master(0) 
} 

#pragma align(16) 
asm void hwint01()  //Interrupt routine for irq 1 (keyboard) 
{   
  hwint_master(1) 
} 

#pragma align(16) 
asm void hwint02()  //Interrupt routine for irq 2 (cascade!) 
{ 
  hwint_master(2) 
} 

#pragma align(16) 
asm void hwint03()  //Interrupt routine for irq 3 (second serial) 
{ 
  hwint_master(3) 
} 

#pragma align(16) 
asm void hwint04()  //Interrupt routine for irq 4 (first serial) 
{ 
  hwint_master(4) 
} 

#pragma align(16) 
asm void hwint05()  //Interrupt routine for irq 5 (XT winchester) 
{ 
  hwint_master(5) 
} 

#pragma align(16) 
asm void hwint06()  //Interrupt routine for irq 6 (floppy) 
{ 
  hwint_master(6) 
} 

#pragma align(16) 
asm void hwint07()  //Interrupt routine for irq 7 (printer) 
{ 
  hwint_master(7) 
} 

#define  hwint_slave(irq_No) \ 
  push   irq_No \ 
  call   spurious_irq \ 
  add    esp, 4 \ 
  hlt \ 

#pragma align(16) 
asm void hwint08()  //Interrupt routine for irq 8 (realtime clock). 
{ 
  hwint_slave(8) 
} 

#pragma align(16) 
asm void hwint09()  //Interrupt routine for irq 9 (irq 2 redirected) 
{ 
  hwint_slave(9) 
} 

#pragma align(16) 
asm void hwint10()  //Interrupt routine for irq 10 
{ 
  hwint_slave(10) 
} 

#pragma align(16) 
asm void hwint11()  //Interrupt routine for irq 11 
{ 
  hwint_slave(11) 
} 

#pragma align(16) 
asm void hwint12()  //Interrupt routine for irq 12 
{ 
  hwint_slave(12) 
} 

#pragma align(16) 
asm void hwint13()  //Interrupt routine for irq 13 (FPU exception) 
{ 
  hwint_slave(13) 
} 

#pragma align(16) 
asm void hwint14()  //Interrupt routine for irq 14 (AT winchester) 
{ 
  hwint_slave(14) 
} 

#pragma align(16) 
asm void hwint15()  //Interrupt routine for irq 15 
{ 
  hwint_slave(15) 
} 

//初始化IDT 
void init_prot() 
{ 
  init_8259A(); 

  // 全部初始化成中断门(没有陷阱门) 
  //            中断向量                中断门类型值 处理函数              权限 
  //异常 
  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); 
  //自定义中断 
  //init_idt_desc(INT_VECTOR_SYS_CALL,    DA_386IGate, sys_call,             PRIVILEGE_USER); 
   
  *(t_16*)(&idt_ptr[0]) = IDT_SIZE * sizeof(GATE); 
  *(t_32*)(&idt_ptr[2]) = (t_32)&idt + ProtecAddr; 
  asm{lidt  idt_ptr} //加载idt 
} 
//关闭特定的中断 
asm void disable_irq(int irq) 
{ 
  mov   ecx, [esp + 4]    //irq 
  pushf 
  cli 
  mov   ah, 1 
  rol   ah, cl            //ah = (1 << (irq % 8)) 
  cmp   cl, 8 
  jae   disable_8         //disable irq >= 8 at the slave 8259 
disable_0: 
  in    al, INT_M_CTLMASK 
  test  al, ah 
  jnz   dis_already       //already disabled? 
  or    al, ah 
  out   INT_M_CTLMASK, al //set bit at master 8259 
  popf 
  mov   eax, 1            //disabled by this function 
  ret 
disable_8: 
  in    al, INT_S_CTLMASK 
  test  al, ah 
  jnz   dis_already       //already disabled? 
  or    al, ah 
  out   INT_S_CTLMASK, al //set bit at slave 8259 
  popf 
  mov   eax, 1            //disabled by this function 
  ret 
dis_already: 
  popf 
  xor   eax, eax          //already disabled 
  ret 
} 
//打开特定的中断 
asm void enable_irq(int irq) 
{ 
  mov   ecx, [esp + 4]    ; irq 
  pushf 
  cli 
  mov   ah, ~1 
  rol   ah, cl             //ah = ~(1 << (irq % 8)) 
  cmp   cl, 8 
  jae   enable_8           //enable irq >= 8 at the slave 8259 
enable_0: 
  in    al, INT_M_CTLMASK 
  and   al, ah 
  out   INT_M_CTLMASK, al  //clear bit at master 8259 
  popf 
  ret 
enable_8: 
  in    al, INT_S_CTLMASK 
  and   al, ah 
  out   INT_S_CTLMASK, al  //clear bit at slave 8259 
  popf 
  ret 
} 
//向特定的中断注册处理函数 
void put_irq_handler(int irq, t_pf_irq_handler handler) 
{ 
  disable_irq(irq); 
  irq_table[irq] = handler; 
}  




[ 本帖最后由 miaowangjian 于 2010-5-31 16:16 编辑 ]
搜索更多相关主题的帖子: 操作系统 机制 
2010-05-17 05:32
chengstone
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
帖 子:562
专家分:226
注 册:2004-4-3
收藏
得分:0 
好 不错 不错

qq:69558139
2010-05-17 10:52
miaowangjian
Rank: 2
等 级:论坛游民
帖 子:34
专家分:30
注 册:2010-1-29
收藏
得分:0 
发现代码里的文件头注释写错了
帖子中的:
code:i8259.c(新)
程序代码:
//文件:klib.c
//功能:初始化8259A、以及设置中断相关的函数
//作者:miao
//时间:2010-5-16 
应该为:
code:i8259.c(新)
程序代码:
code:i8259.c(新)
程序代码:
//文件:i8259.c
//功能:初始化8259A、以及设置中断相关的函数
//作者:miao
//时间:2010-5-16 

因为这个错误,在
    一步步写操作系统之第四步:创建键盘中断处理模块和初步搭建程序执行系统
中,提示对i8259.c(的修改,写成了对 klib.c的修改。

现已经在帖子里改过来了。

2010-05-31 16:27
djchx
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2010-8-18
收藏
得分:0 
顶一下,我是刚开始学,见到各位大哥这么认真的发帖子,无非是更利于我这样的菜鸟能学到东西,谢谢了,
2010-08-18 09:07
快速回复:一步步写操作系统之第三步:初步建立中断异常处理机制
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.024255 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved