新手学linux之-----------------asm.s

/*
 *  linux/kernel/asm.s
 *
 *  (C) 1991  Linus Torvalds
 */

/*
 * asm.s contains the low-level code for most hardware faults.
 * page_exception is handled by the mm, so that isn't here. This
 * file also handles (hopefully) fpu-exceptions due to TS-bit, as
 * the fpu must be properly saved/resored. This hasn't been tested.
 */

 
 //这里定义了一些low-level中断 int0-int16 (int 17-int 31 Intel保留的中断号) 大部分硬件中断
.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
.globl _double_fault,_coprocessor_segment_overrun
.globl _invalid_TSS,_segment_not_present,_stack_segment
.globl _general_protection,_coprocessor_error,_irq13,_reserved
 
//XCHG 交换(Exchange)
//XCHG OP1,OP2;将OP1和OP2的数据对换
//操作 X=OP1 OP1=OP2 OP2=X 补充说明:XCHG不影响标志位,OP中不能有段寄存器。
//LEA OPRD1,OPRD2 
//功能: 将源操作数给出的有效地址传送到指定的的寄存器中.
_divide_error:
//note: do开头的函数是asm.s中断处理函数调用的c函数 在trap.c中定义
//下一篇博客 将分析trap.c
    pushl $_do_divide_error        //int 0 除零错误 将要调用的函数地址入栈
no_error_code:
    xchgl %eax,(%esp)            //取函数的入口地址
    pushl %ebx                    //其他相关寄存器的入栈
    pushl %ecx
    pushl %edx
    pushl %edi
    pushl %esi
    pushl %ebp
    push %ds
    push %es
    push %fs
    //将出错码和中断返回地址入栈作为函数调用_do_divide_error的参数。
    pushl $0        # "error code" 出错码
    lea 44(%esp),%edx            //do_divide_error(long esp,long error_code) 可见传的esp变量时要求
    pushl %edx                    //出错位置 以便打印  下面的jmp error_code也是同一个意思
    //初始化段选择子
    movl $0x10,%edx
    mov %dx,%ds
    mov %dx,%es
    mov %dx,%fs
    call *%eax                //调用操作数指定地址处的函数
    addl $8,%esp            //跳到%fs处
    pop %fs
    pop %es
    pop %ds
    popl %ebp
    popl %esi
    popl %edi
    popl %edx
    popl %ecx
    popl %ebx
    popl %eax
    iret

//int1 debug调试中断 当eflags中的TF标志置位时发生中断
_debug:
    pushl $_do_int3        # _do_debug
    jmp no_error_code

//int2 非屏蔽中断调用入口点 当接收到一个nmi信号 CPU就会产生此中断
_nmi:
    pushl $_do_nmi
    jmp no_error_code

//断点指令的入口
_int3:
    pushl $_do_int3
    jmp no_error_code

//CPU OF位置位就会产生此中断
_overflow:
    pushl $_do_overflow
    jmp no_error_code

_bounds:
    pushl $_do_bounds
    jmp no_error_code

//int 6无效操作入口
_invalid_op:
    pushl $_do_invalid_op
    jmp no_error_code
//int 9 协处理器的出错
_coprocessor_segment_overrun:
    pushl $_do_coprocessor_segment_overrun
    jmp no_error_code

//int 15 Intel保留的中断的入口
_reserved:
    pushl $_do_reserved
    jmp no_error_code

//当协处理器执行完一个操作时 就会发出IRQ13中断的信号 以通知CPU操作完成
//在这里重点说明一下 8259A的中断结束方式 (要想深入一点了解 请参考 微机原理与接口技术)
//分为自动AEOI方式 和非自动结束方式 其实后者又可以分为 普通EOI方式和特殊SEOI方式 
//这里用到的是普通EOI方式
//中断结束处理其实就是对中断服务器ISR中的对应为的处理 当一个中断得到响应是 8259A
//使ISR寄存器的对应位置置1 表明对应的外设正在服务 并为中断判优提供依据 中断结束时
//必须是ISR寄存器的对应位置置0 否则中断判优惠不正常 什么时刻使ISR中对应位置置0 就产生 不同的中断结束方式
/*普通EOI方式
8259A 结束中断的方式
mov al,0x20
out 0x20,al
EOI结束命令必须放在返回指令之前
说明:采用的多级级联的方式 那么从片也要发送EOI信号
*/
_irq13:
    pushl %eax
    xorb %al,%al
    outb %al,$0xF0        //用于清忙锁存器 通过写该端口 本中断将消除CPU的BUSY延续信号 并重新激活80387的
                        //扩展请求引脚PEREQ
    movb $0x20,%al        //主片
    outb %al,$0x20
    jmp 1f                //延迟一段时间
1:    jmp 1f
1:    outb %al,$0xA0        //从片
    popl %eax
    jmp _coprocessor_error

//中断嵌套 产生中断 linux中不允许中断嵌套
_double_fault:
    pushl $_do_double_fault
error_code:
    xchgl %eax,4(%esp)        # error code <-> %eax
    xchgl %ebx,(%esp)        # &function <-> %ebx
    pushl %ecx
    pushl %edx
    pushl %edi
    pushl %esi
    pushl %ebp
    push %ds
    push %es
    push %fs
    pushl %eax                # error code
    lea 44(%esp),%eax        # offset
    pushl %eax                //程序返回入口地址
    movl $0x10,%eax            //段选择子的改变
    mov %ax,%ds
    mov %ax,%es
    mov %ax,%fs
    call *%ebx
    addl $8,%esp        //不要入栈的2个作为c函数的参数 供c语言使用 参考do_divide_error
    pop %fs
    pop %es
    pop %ds
    popl %ebp
    popl %esi
    popl %edi
    popl %edx
    popl %ecx
    popl %ebx
    popl %eax
    iret
//int10 无效的任务状态栈
_invalid_TSS:
    pushl $_do_invalid_TSS
    jmp error_code
//int11 段不存在
_segment_not_present:
    pushl $_do_segment_not_present
    jmp error_code
//int12 堆栈错误 是int11 和 int13的特殊情况
_stack_segment:
    pushl $_do_stack_segment
    jmp error_code
//int13 一般保护错误
_general_protection:
    pushl $_do_general_protection
    jmp error_code
//int7 设备不存在异常 定义在sys_call.s中  在接下来的两篇博客会介绍
//int14 页错误 page.s中  在memroy.c中 我们已经提及过了
//int16 协处理器错误 sys_call.s
//int 0x20 时钟中断 (最重要的一个中断) 定义在sys_call.s中
//系统调用int 0x80 sys_call.s        相当于BIOS下函数的调用















你可能感兴趣的:(新手学linux之-----------------asm.s)