第9章 设置ISR(中断处理函数)

中断处理有三个阶段

  1. 进入阶段:栈保存(带出错码的中断、不带出错码的中断)
  2. 处理阶段:中断处理
  3. 退出阶段:恢复栈

80×86中有特权级的概念,不同的特权级有不同的栈,所以中断发生时要保存中断前的栈地址。 特权级

查看intel使用手册

intel使用手册

interrupt.s源代码文件(参考linux 0.11源代码)

.global divide_error,debug_exception,nmi,breakpoint,overflow,bound,invalid_opcode
    .global coprocessor_not_available,double_fault,coprocessor_segment_overrun,invalid_tss
    .global segment_not_present,stack_exception,protection_exception,page_fault
    .global intel_reserved,coprecessor_error,default_isr,timer
    .include "kernel.inc"


divide_error:
    pushl $do_divide_error
no_error_code:
    xchgl   %eax,   (%esp)    # &function-> %eax, 原%eax放到栈中
    pushl   %ebx
    pushl   %ecx
    pushl   %edx
    pushl   %edi
    pushl   %esi
    pushl   %ebp
    push    %ds
    push    %es
    push    %fs
    pushl   $0            # 填充错误码,作为中断处理函数的参数
    lea        52(%esp),    %edx    #当前堆栈地址加上52后,放到edx中
    pushl   %edx        #压edx入栈,这样中断处理函数就能获取到被压入栈的寄存器的值
    movl    $DATA_SEL,    %edx
    mov        %dx,    %ds
    mov        %dx,    %es
    mov        %dx,    %fs
    call    *%eax        #调用中断处理函数
    addl    $8,        %esp    
    pop        %fs
    pop        %es
    pop        %ds
    popl    %ebp
    popl    %esi
    popl    %edi
    popl    %edx
    popl    %ecx
    popl    %ebx
    popl    %eax
    iret

invalid_tss:
    pushl   $do_invalid_tss
error_code:
    xchgl   %eax,   4(%esp)    # error code -> %eax, 原eax放到栈中
    xchgl   %ebx,   (%esp)    # &function -> %ebx,原ebx放到栈中
    pushl   %ecx
    pushl   %edx
    pushl   %edi
    pushl   %esi
    pushl   %ebp
    pushl   %ds
    pushl   %es
    pushl   %fs
    pushl   %eax        # 压入错误码,作为中断处理函数的参数
    lea        52(%esp),    %eax    # 当前堆栈地址加上52后,放到eax中
    pushl   %eax        # 压eax入栈,这样中断处理函数就能获取到被压入栈的寄存器的值
    movl    $DATA_SEL,    %eax
    mov        %ax,    %ds
    mov        %ax,    %es 
    mov        %ax,    %fs
    call    *%ebx
    addl    $8,        %esp
    pop        %fs
    pop        %es
    pop        %ds
    popl    %ebp
    popl    %esi
    popl    %edi
    popl    %edx
    popl    %ecx
    popl    %ebx
    popl    %eax
    iret



debug_exception:
    pushl   $do_debug_exception
    jmp        no_error_code

nmi:
    pushl   $do_nmi
    jmp        no_error_code

breakpoint:
    pushl   $do_breakpoint
    jmp        no_error_code

overflow:
    pushl   $do_overflow
    jmp        no_error_code

bound:
    pushl   $do_bound
    jmp        no_error_code

invalid_opcode:
    pushl   $do_invalid_opcode
    jmp        no_error_code

coprocessor_not_available:
    pushl   $do_coprocessor_not_available
    jmp        no_error_code


coprocessor_segment_overrun:
    pushl   $do_coprocessor_segment_overrun
    jmp        no_error_code

intel_reserved:
    pushl   $do_intel_reserved
    jmp        no_error_code

coprecessor_error:
    pushl   $do_coprocessor_error
    jmp        no_error_code

timer:
    pushl   $do_timer
    jmp        no_error_code


 
double_fault:
    pushl   $do_double_fault
    jmp        error_code


invaild_tss:
    pushl   $do_invalid_tss
    jmp        error_code

segment_not_present:
    pushl   $do_segment_not_present
    jmp        error_code

stack_exception:
    pushl   $do_stack_exception
    jmp        error_code

protection_exception:
    pushl   $do_protection_exception
    jmp        error_code

page_fault:
    pushl   $do_page_fault
    jmp        error_code


default_isr:
    pushl   $do_default_isr
    jmp        no_error_code

interrupt.h源代码文件

#ifndef    _INTERRUPT_H_
#define    _INTERRUPT_H_

//在中断处理函数中,每个寄存器在栈中的下标
#define    OLD_SS_REG    2
#define    OLD_ESP_REG    1
#define    OLD_EFLAGS_REG 0
#define    OLD_CS_REG    -1
#define    OLD_EIP_REG    -2
#define    EAX_REG    -3
#define    EBX_REG    -4
#define    ECX_REG    -5
#define    EDX_REG    -6
#define    EDI_REG    -7
#define    ESI_REG    -8
#define    EBP_REG    -9
#define    DS_REG    -10
#define    ES_REG    -11
#define    FS_REG    -12



 extern    void default_isr(void);  //该函数定义在idt.c文件中
 extern    void divide_error(void);
 extern    void debug_exception(void);
 extern    void nmi(void);
 extern    void breakpoint(void);
 extern    void overflow(void);
 extern    void bound(void);
 extern    void invalid_opcode(void);
 extern    void coprocessor_not_available(void);
 extern    void double_fault(void);
 extern    void coprocessor_segment_overrun(void);
 extern    void invalid_tss(void);
 extern    void segment_not_present(void);
 extern    void stack_exception(void);
 extern    void protection_exception(void);
 extern    void page_fault(void);
 extern    void intel_reserved(void);
 extern    void coprecessor_error(void);
 extern    void timer(void);



 extern void    sys_call(void);
#endif

Leave a Reply

Your email address will not be published. Required fields are marked *