3.3 初始化 pyos 的中断向量表
从中断初始化的代码中我们可以清楚的看见,pyos在进行完8259A的初始化后,调用InitInterruptTable()对中断向量表进行了初始化,这可是本篇的核心内容,我们这就来看看这个核心函数:
/* 中断描述符结构 */
struct struct_pyos_InterruptItem{
unsigned short Offset_0_15 ; // 偏移量的0~15位
unsigned short SegSelector ; // 段选择符
unsigned char UnUsed ; // 未使用,须设为全零
unsigned char Saved_1_1_0 : 3 ; // 保留,需设为 110
unsigned char D : 1 ; // D 位
unsigned char Saved_0 : 1 ; // 保留,需设为0
unsigned char DPL : 2 ; // 特权位
unsigned char P : 1 ; // P 位
unsigned short Offset_16_31 ; // 偏移量的16~31位
} ;
/* IDTR所用结构 */
struct struct_pyos_Idtr{
unsigned short IdtLengthLimit ;
struct_pyos_InterruptItem* IdtAddr ;
} ;
static struct_pyos_InterruptItem m_Idt[ 256 ] ; // 中断描述符表项
static struct_pyos_Idtr m_Idtr ; // 中断描述符寄存器所用对象
extern "C" void pyos_asm_interrupt_handle_for_default() ; // 默认中断处理函数
/* 初始化中断向量表 */
void class_pyos_Interrupt::InitInterruptTable()
{
/* 设置中断描述符,指向一个哑中断,在需要的时候再填写 */
struct_pyos_InterruptItem tmp ;
tmp.Offset_0_15 = ( unsigned int )pyos_asm_interrupt_handle_for_default ;
tmp.Offset_16_31 = ( unsigned int )pyos_asm_interrupt_handle_for_default >> 16 ;
tmp.SegSelector = 0x8 ; // 代码段
tmp.UnUsed = 0 ;
tmp.P = 1 ;
tmp.DPL = 0 ;
tmp.Saved_1_1_0 = 6 ;
tmp.Saved_0 = 0 ;
tmp.D = 1 ;
for( int i = 0 ; i < 256 ; ++i ){
m_Idt[ i ] = tmp ;
}
m_Idtr.IdtAddr = m_Idt ;
m_Idtr.IdtLengthLimit = 256 * 8 - 1 ; // 共 256项,每项占8个字节
// 内嵌汇编,载入 ldt
__asm__( "lidt %0" : "=m"( m_Idtr ) ) ; //载入GDT表
}
程序首先说明了两个结构,一个用来描述中断描述符,一个用来描述中断描述符寄存器。大家可以对照前面的描述看看这两个结构中的成员分别对应硬件系统中的哪一位。之后,程序建立了一个中断描述符数组m_Idt,它共有256项,这是因为CPU可以处理256个中断。程序还建立了一个中断描述符寄存器所用的对象。随后,程序开始为这些变量赋值。
从程序中我们可以看出,pyos现在是将每个中断描述符都设成一样的,均指向一个相同的中断处理程序:pyos_asm_interrupt_handle_for_default(),在一个实际的操作系统中,在最初初始化的时候,也常常是这样做的,这个被称之为“默认中断处理程序”的中断服务程序通常是一个什么也不干的“哑中断处理程序”或者是一个只是简单报错的处理程序。而要等到实际需要时,才使用相应的处理程序替换它。
程序在建立“中断描述符表”后,用lidt指令将中断描符述表寄存器所用的内容载入了中断描述符寄存器(IDTR)中,对于“中断描述符表”的初始化就完成了,下面我们可以来看看,pyos_asm_interrupt_handle_for_default()这个程序到底做了些什么事:
3.4 中断处理程序的编写
pyos_asm_interrupt_handle_for_default:
;保护现场
pushad
;调用相应的C++处理函数
call pyos_interrupt_handle_for_default
;告诉硬件中断处理完毕,即发送 EOI 消息
mov al , 0x20
out 0x20 , al
out 0xa0 , al
;恢复现场
popad
;返回
iret
这个程序是在一个名为“interrupt.asm”的汇编文件中,显然,它是一个汇编语言写的源程序。为什么这里又要用汇编语言编写而不直接用C++内嵌汇编编写呢,比如写成下面这样:
void pyos_asm_interrupt_handle_for_default()
{
__asm__( "pushad" ) ;
/* do something */
__asm__( "popad" ) ;
__asm__( "iret" ) ;
}
本文详细介绍了如何在pyos中初始化中断向量表,并通过内嵌汇编语言编写中断处理程序。重点在于理解中断描述符表的结构,以及如何使用lidt指令载入IDTR,完成中断向量表的初始化。
5195

被折叠的 条评论
为什么被折叠?



