博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
操作系统开发系列—12.f.在内核中添加中断处理 ●
阅读量:4932 次
发布时间:2019-06-11

本文共 2930 字,大约阅读时间需要 9 分钟。

因为CPU只有一个,同一时刻要么是客户进程在运行,要么是操作系统在运行,如果实现进程,需要一种控制权转换机制,这种机制便是中断。

要做的工作有两项:设置8259A和建立IDT。

/*======================================================================*                            init_8259A *======================================================================*/PUBLIC void init_8259A(){	/* Master 8259, ICW1. */	out_byte(INT_M_CTL,	0x11);	/* Slave  8259, ICW1. */	out_byte(INT_S_CTL,	0x11);	/* Master 8259, ICW2. 设置 '主8259' 的中断入口地址为 0x20. */	out_byte(INT_M_CTLMASK,	INT_VECTOR_IRQ0);	/* Slave  8259, ICW2. 设置 '从8259' 的中断入口地址为 0x28 */	out_byte(INT_S_CTLMASK,	INT_VECTOR_IRQ8);	/* Master 8259, ICW3. IR2 对应 '从8259'. */	out_byte(INT_M_CTLMASK,	0x4);	/* Slave  8259, ICW3. 对应 '主8259' 的 IR2. */	out_byte(INT_S_CTLMASK,	0x2);	/* Master 8259, ICW4. */	out_byte(INT_M_CTLMASK,	0x1);	/* Slave  8259, ICW4. */	out_byte(INT_S_CTLMASK,	0x1);	/* Master 8259, OCW1.  */	out_byte(INT_M_CTLMASK,	0xFF);	/* Slave  8259, OCW1.  */	out_byte(INT_S_CTLMASK,	0xFF);}

out_byte的函数体位于kliba.asm中

global	out_byteglobal	in_byte; ========================================================================;                  void out_byte(u16 port, u8 value);; ========================================================================out_byte:	mov	edx, [esp + 4]		; port	mov	al, [esp + 4 + 4]	; value	out	dx, al	nop	; 一点延迟	nop	ret; ========================================================================;                  u8 in_byte(u16 port);; ========================================================================in_byte:	mov	edx, [esp + 4]		; port	xor	eax, eax	in	al, dx	nop	; 一点延迟	nop	ret

现在,该是把这些中断和异常的处理程序统统添加上的时候了。

global	divide_errorglobal	single_step_exceptionglobal	nmiglobal	breakpoint_exceptionglobal	overflowglobal	bounds_check...	lidt	[idt_ptr]...; 中断和异常 -- 异常divide_error:	push	0xFFFFFFFF	; no err code	push	0		; vector_no	= 0	jmp	exceptionsingle_step_exception:	push	0xFFFFFFFF	; no err code	push	1		; vector_no	= 1	jmp	exceptionnmi:	push	0xFFFFFFFF	; no err code	push	2		; vector_no	= 2	jmp	exceptionbreakpoint_exception:	push	0xFFFFFFFF	; no err code	push	3		; vector_no	= 3	jmp	exceptionoverflow:	push	0xFFFFFFFF	; no err code	push	4		; vector_no	= 4	jmp	exception...exception:	call	exception_handler	add	esp, 4*2	; 让栈顶指向 EIP,堆栈中从顶向下依次是:EIP、CS、EFLAGS	hlt

异常发生时堆栈的变化情况是,中断或异常发生时eflags、cs、eip已经被压栈,如果有错误码的话,错误码也已经被压栈。

所以我们对异常处理的总体思想是,如果有错误码,则直接把向量号压栈,然后执行一个函数exception_handler;如果没有错误码,则先在栈中压入一个0xFFFFFFFF,再把向量号压栈并随后执行exception_handler。

函数exception_hanlder()的原型是这样的:

void exception_handler(int vec_no,int err_code,int eip,int cs,int eflags);

由于C调用约定是调用者恢复堆栈,所以不用担心exception_handler会破坏堆栈中的eip、cs以及eflags。

现在我们已经有了异常处理函数,该是设置IDT的时候了。设置IDT的代码放进函数init_prot()中,它也位于protect.c中。protect.c通篇几乎只调用一个函数,就是init_idt_desc(),它用来初始化一个门描述符。其中用到的函数指针类型是这样定义的:

typedef	void	(*int_handler)	();

在init_prot()中,所有描述符都被初始化成中断门。DA_386IGate表示中断门。

Intel为我们准备了一个指令叫做ud2,能够产生一个#UD异常。

编译:

make image

运行结果如下:

 

 

转载于:https://www.cnblogs.com/joey-hua/p/5418380.html

你可能感兴趣的文章
javafx for android or ios ?
查看>>
Android初级教程理论知识(第七章服务)
查看>>
maven安装与创建多模块项目
查看>>
详解Java反射各种应用
查看>>
利用Google API快速生成QR二维码
查看>>
Python-正则表达式和re模块
查看>>
POJ 3045 Cow Acrobats (贪心)
查看>>
[BZOJ4317]Atm的树
查看>>
找水王---2
查看>>
nginx1.3.9和1.4.0 的 chunked 溢出漏洞
查看>>
攻下隔壁女神的路由器(转)
查看>>
杭电acm刷题顺序
查看>>
关于fixedsys字体 FSEX300.ttf FSEX300-L.ttf FSEX301-L2.ttf
查看>>
hnust 档案管理
查看>>
Redis 并发, 锁, 竞争锁问题.
查看>>
FPGA中的平方根
查看>>
老湿不给你力啊:各种加密解密
查看>>
IE浏览器下同一网页多图片显示的瓶颈与优化[原创]
查看>>
Foundation框架—集合
查看>>
获取同一程序集中的实现类对应的多个接口
查看>>