Linux内核中断描述符表,Linux0.11内核--idt(中断描述符表的初始化)head.s分析

head.s被编译成system模块的最前面部分,故而称为头部。

这段程序处于地址的绝对0处,首先是加载各个数据段寄存器,重新设置中断描述符表 idt,共 256 项,并使各个表项均指向一个只报错误的哑中断

程序。然后重新设置全局描述符表 gdt。接着使用物理地址 0 与 1M 开始处的内容相比较的方法,检测 A20 地址线是否已真的开启(如果没有开

启,则在访问高于 1Mb 物理内存地址时 CPU 实际只会访问(IP MOD,如果检测下来发现没有开启,则进入死循环。然后程序测试 PC 机是否含有数

学1Mb)地址处的内容)协处理器芯片(80287、80387 或其兼容芯片),并在控制寄存器 CR0 中设置相应的标志位。接着设置管理内存的分页处

理机制,将页目录表放在绝对物理地址 0 开始处(也是本程序所处的物理内存位置,因此这段程序将被覆盖掉),紧随后面放置共可寻址 16MB 内存

的 4 个页表,并分别设置它们的表项。最后利用返回指令将预先放置在堆栈中的/init/main.c 程序的入口地址弹出,去运行 main()程序。

下面看一下idt表的初始化。

首先设置ds,es,fs,gs选择符为setup.s中设置的数据段

movl $0x10,%eax

mov %ax,%ds

mov %ax,%es

mov %ax,%fs

mov %ax,%gs

然后设置系统的堆栈

lss stack_start,%esp   #表示_stack_start ss:esp

其中stack_start在/kernel/sched.c中定义了

然后进入setup_idt子程序

setup_idt:

lea ignore_int,%edx

movl $0x00080000,%eax

movw %dx,%ax/* selector = 0x0008 = cs */

movw $0x8E00,%dx/* interrupt gate - dpl=0, present */

lea idt,%edi

mov $256,%ecx

rp_sidt:

movl %eax,(%edi)

movl %edx,4(%edi)

addl $8,%edi

dec %ecx

jne rp_sidt

lidt idt_descr

ret

idt表项的结构如下图

2924737e860934e1ff12addbd79a19ae.gif

这段子程序就是循环设置了256项idt描述符,全部指向ignore_int中断门,以后使用的时候再重新设置

/* This is the default interrupt "handler" :-) */

int_msg:

.asciz"Unknown interrupt/n/r"

.align 2

ignore_int:

pushl %eax

pushl %ecx

pushl %edx

push %ds

push %es

push %fs

movl $0x10,%eax

mov %ax,%ds

mov %ax,%es

mov %ax,%fs

pushl $int_msg

call printk

popl %eax

pop %fs

pop %es

pop %ds

popl %edx

popl %ecx

popl %eax

iret

其中idt标号的地址就是idt表的其实地址  位于head.s的233行

定义如下

.align 8

idt:    .fill 256,8,0       # idt is uninitialized

其中.align n 伪指令的含义

在x86 ELF格式中,要在8字节处对齐,应该用 .align 8

而在a.out格式中,要在8字节处对齐,应该用 .align 3       (2^n),现在一般用elf格式。0b1331709591d260c1c78e86d0c51c18.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值