博客网址:www.shicoder.top
微信:kj11011029
欢迎加群聊天 :452380935
这一次我们来对异常进行说明
下面是异常和中断号,我们知道一共有256个中断号,其中0-31,一共32个是异常,本次就来实现异常,同样,其实异常就是函数。
我们修改下handler.asm
如下
[bits 32]
; 中断处理函数入口
extern handler_table
section .text
%macro INTERRUPT_HANDLER 2
interrupt_handler_%1:
%ifn %2
push 0x20222202
%endif
push %1; 压入中断向量号,跳转到中断入口
jmp interrupt_entry
%endmacro
interrupt_entry:
mov eax, [esp]
; 调用中断处理函数,handler_table 中存储了中断处理函数的指针
call [handler_table + eax * 4]
; 对应 push %1,调用结束恢复栈
add esp, 8
iret
INTERRUPT_HANDLER 0x00, 0; divide by zero
INTERRUPT_HANDLER 0x01, 0; debug
INTERRUPT_HANDLER 0x02, 0; non maskable interrupt
INTERRUPT_HANDLER 0x03, 0; breakpoint
INTERRUPT_HANDLER 0x04, 0; overflow
INTERRUPT_HANDLER 0x05, 0; bound range exceeded
INTERRUPT_HANDLER 0x06, 0; invalid opcode
INTERRUPT_HANDLER 0x07, 0; device not avilable
INTERRUPT_HANDLER 0x08, 1; double fault
INTERRUPT_HANDLER 0x09, 0; coprocessor segment overrun
INTERRUPT_HANDLER 0x0a, 1; invalid TSS
INTERRUPT_HANDLER 0x0b, 1; segment not present
INTERRUPT_HANDLER 0x0c, 1; stack segment fault
INTERRUPT_HANDLER 0x0d, 1; general protection fault
INTERRUPT_HANDLER 0x0e, 1; page fault
INTERRUPT_HANDLER 0x0f, 0; reserved
INTERRUPT_HANDLER 0x10, 0; x87 floating point exception
INTERRUPT_HANDLER 0x11, 1; alignment check
INTERRUPT_HANDLER 0x12, 0; machine check
INTERRUPT_HANDLER 0x13, 0; SIMD Floating - Point Exception
INTERRUPT_HANDLER 0x14, 0; Virtualization Exception
INTERRUPT_HANDLER 0x15, 1; Control Protection Exception
INTERRUPT_HANDLER 0x16, 0; reserved
INTERRUPT_HANDLER 0x17, 0; reserved
INTERRUPT_HANDLER 0x18, 0; reserved
INTERRUPT_HANDLER 0x19, 0; reserved
INTERRUPT_HANDLER 0x1a, 0; reserved
INTERRUPT_HANDLER 0x1b, 0; reserved
INTERRUPT_HANDLER 0x1c, 0; reserved
INTERRUPT_HANDLER 0x1d, 0; reserved
INTERRUPT_HANDLER 0x1e, 0; reserved
INTERRUPT_HANDLER 0x1f, 0; reserved
; 下面的数组记录了每个中断入口函数的指针
section .data
global handler_entry_table
handler_entry_table:
dd interrupt_handler_0x00
dd interrupt_handler_0x01
dd interrupt_handler_0x02
dd interrupt_handler_0x03
dd interrupt_handler_0x04
dd interrupt_handler_0x05
dd interrupt_handler_0x06
dd interrupt_handler_0x07
dd interrupt_handler_0x08
dd interrupt_handler_0x09
dd interrupt_handler_0x0a
dd interrupt_handler_0x0b
dd interrupt_handler_0x0c
dd interrupt_handler_0x0d
dd interrupt_handler_0x0e
dd interrupt_handler_0x0f
dd interrupt_handler_0x10
dd interrupt_handler_0x11
dd interrupt_handler_0x12
dd interrupt_handler_0x13
dd interrupt_handler_0x14
dd interrupt_handler_0x15
dd interrupt_handler_0x16
dd interrupt_handler_0x17
dd interrupt_handler_0x18
dd interrupt_handler_0x19
dd interrupt_handler_0x1a
dd interrupt_handler_0x1b
dd interrupt_handler_0x1c
dd interrupt_handler_0x1d
dd interrupt_handler_0x1e
dd interrupt_handler_0x1f
其中有一段代码如下
%macro INTERRUPT_HANDLER 2
interrupt_handler_%1:
%ifn %2
push 0x20222202
%endif
push %1; 压入中断向量号,跳转到中断入口
jmp interrupt_entry
%endmacro
是宏函数,比如针对INTERRUPT_HANDLER 0x00, 0
,宏函数展开后就是
interrupt_handler_0x00:
push 0x20222202
push 0x00
jmp interrupt_entry
针对INTERRUPT_HANDLER 0x08, 1
,展开为
interrupt_handler_0x08:
push 0x08
jmp interrupt_entry
为什么要有些push 0x20222202?
因为有些异常,系统会自动压入错误码,针对第二个参数为1的,就会自动压入,因此针对第二个参数为0的,我们手动压入,此时的0x20222202是我们自己设置的
最后我们在interrupt_init
中初始化256个中断描述符表
// 一共128个大小的中断描述符表,然后从0开始,0x20个异常中断描述符
#define ENTRY_SIZE 0x20
gate_t idt[IDT_SIZE];
pointer_t idt_ptr; // 本身这个变量是针对全局描述符表,因为中断描述符表的指针一样,所以公用
// extern void interrupt_handler();
handler_t handler_table[IDT_SIZE];
extern handler_t handler_entry_table[ENTRY_SIZE];
static char *messages[] = {
"#DE Divide Error\0",
"#DB RESERVED\0",
"-- NMI Interrupt\0",
"#BP Breakpoint\0",
"#OF Overflow\0",
"#BR BOUND Range Exceeded\0",
"#UD Invalid Opcode (Undefined Opcode)\0",
"#NM Device Not Available (No Math Coprocessor)\0",
"#DF Double Fault\0",
" Coprocessor Segment Overrun (reserved)\0",
"#TS Invalid TSS\0",
"#NP Segment Not Present\0",
"#SS Stack-Segment Fault\0",
"#GP General Protection\0",
"#PF Page Fault\0",
"-- (Intel reserved. Do not use.)\0",
"#MF x87 FPU Floating-Point Error (Math Fault)\0",
"#AC Alignment Check\0",
"#MC Machine Check\0",
"#XF SIMD Floating-Point Exception\0",
"#VE Virtualization Exception\0",
"#CP Control Protection Exception\0",
};
// 异常情况执行的函数
void exception_handler(int vector)
{
char *message = NULL;
if (vector < 22)
{
message = messages[vector];
}
else
{
message = messages[15];
}
printk("Exception : [0x%02X] %s \n", vector, messages[vector]);
// 阻塞
while (true)
;
}
void interrupt_init()
{
// 初始化0x20个异常处理函数
for (size_t i = 0; i < ENTRY_SIZE; i++)
{
gate_t *gate = &idt[i];
// gate->offset0 = (u32)interrupt_handler & 0xffff;
// gate->offset1 = ((u32)interrupt_handler >> 16) & 0xffff;
handler_t handler = handler_entry_table[i];
gate->offset0 = (u32)handler & 0xffff;
gate->offset1 = ((u32)handler >> 16) & 0xffff;
gate->selector = 1 << 3; // 代码段
gate->reserved = 0; // 保留不用
gate->type = 0b1110; // 中断门
gate->segment = 0; // 系统段
gate->DPL = 0; // 内核态
gate->present = 1; // 有效
}
for (size_t i = 0; i < ENTRY_SIZE; i++)
{
handler_table[i] = exception_handler;
}
idt_ptr.base = (u32)idt;
idt_ptr.limit = sizeof(idt) - 1;
asm volatile("lidt idt_ptr\n");
}
可能大家看代码不懂,我先说下具体的思路,现在有一个大小为256的中断描述符表,在这里我们初始化异常的相关函数,因此初始化0x20个,首先对于每一个,其对应的函数地址为handler_entry_table[i]
,也就是interrupt_handler_0x1b
这些,而每个interrupt_handler_0x1b
都是call [handler_table + eax * 4]
,其实handler_table是一个表,也是0x20个,因此每一个异常都去调用interrupt_handler_0xxx
,然后interrupt_handler_0xxx
调用handler_table
,因此有了下面的代码
for (size_t i = 0; i < ENTRY_SIZE; i++)
{
handler_table[i] = exception_handler;
}
只不过这里都是将每个异常的真实执行函数exception_handler
都是一样的,都是打印一句话,我们来看下具体实现
// 异常情况执行的函数
void exception_handler(int vector)
{
char *message = NULL;
if (vector < 22)
{
message = messages[vector];
}
else
{
message = messages[15];
}
printk("Exception : [0x%02X] %s \n", vector, messages[vector]);
// 阻塞
while (true)
;
}
这样就基本实现了异常的处理机制
测试邮箱
怎么收藏这篇文章?
看的我热血沸腾啊https://www.237fa.com/
想想你的文章写的特别好https://www.ea55.com/
想想你的文章写的特别好www.jiwenlaw.com
《死亡之旅》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/132183.html
《爱情牛排》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/7111.html
《爱情牛排》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/7111.html
《异变1983》科幻片高清在线免费观看:https://www.jgz518.com/xingkong/74892.html
《昂山素季》爱情片高清在线免费观看:https://www.jgz518.com/xingkong/106693.html
《江湖浪子1961》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/129636.html
《暗界之主》短片剧高清在线免费观看:https://www.jgz518.com/xingkong/26038.html
《白头神探2?:恐怖的气味》动作片高清在线免费观看:https://www.jgz518.com/xingkong/30464.html
《圣罗兰庆典终章》记录片高清在线免费观看:https://www.jgz518.com/xingkong/87340.html
《魂断加尔各答》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/5818.html
《我的燃情岁月》国产剧高清在线免费观看:https://www.jgz518.com/xingkong/34210.html
《异能男友》爱情片高清在线免费观看:https://www.jgz518.com/xingkong/17035.html
《暗界之主》短片剧高清在线免费观看:https://www.jgz518.com/xingkong/26038.html
《爱情牛排》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/7111.html
《白头神探2?:恐怖的气味》动作片高清在线免费观看:https://www.jgz518.com/xingkong/30464.html
《异变1983》科幻片高清在线免费观看:https://www.jgz518.com/xingkong/74892.html
《圣罗兰庆典终章》记录片高清在线免费观看:https://www.jgz518.com/xingkong/87340.html
《江湖浪子1961》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/129636.html
《异能男友》爱情片高清在线免费观看:https://www.jgz518.com/xingkong/17035.html
《暗界之主》短片剧高清在线免费观看:https://www.jgz518.com/xingkong/26038.html
《朱蒙》韩国剧高清在线免费观看:https://www.jgz518.com/xingkong/124120.html