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中设置的数据段
[cpp]  view plain copy
  1. movl $0x10,%eax  
  2. mov %ax,%ds  
  3. mov %ax,%es  
  4. mov %ax,%fs  
  5. mov %ax,%gs  
 
然后设置系统的堆栈
lss stack_start,%esp   #表示_stack_start ss:esp
其中stack_start在/kernel/sched.c中定义了
然后进入setup_idt子程序
[cpp]  view plain copy
  1. setup_idt:  
  2.     lea ignore_int,%edx  
  3.     movl $0x00080000,%eax  
  4.     movw %dx,%ax        /* selector = 0x0008 = cs */  
  5.     movw $0x8E00,%dx    /* interrupt gate - dpl=0, present */  
  6.     lea idt,%edi  
  7.     mov $256,%ecx  
  8. rp_sidt:  
  9.     movl %eax,(%edi)  
  10.     movl %edx,4(%edi)  
  11.     addl $8,%edi  
  12.     dec %ecx  
  13.     jne rp_sidt  
  14.     lidt idt_descr  
  15.     ret  
 
idt表项的结构如下图
Linux0.11内核--idt(中断描述符表的初始化)head.s分析_第1张图片
这段子程序就是循环设置了256项idt描述符,全部指向ignore_int中断门,以后使用的时候再重新设置
[cpp]  view plain copy
  1. /* This is the default interrupt "handler" :-) */  
  2. int_msg:  
  3.     .asciz "Unknown interrupt/n/r"  
  4. .align 2  
  5. ignore_int:  
  6.     pushl %eax  
  7.     pushl %ecx  
  8.     pushl %edx  
  9.     push %ds  
  10.     push %es  
  11.     push %fs  
  12.     movl $0x10,%eax  
  13.     mov %ax,%ds  
  14.     mov %ax,%es  
  15.     mov %ax,%fs  
  16.     pushl $int_msg  
  17.     call printk  
  18.     popl %eax  
  19.     pop %fs  
  20.     pop %es  
  21.     pop %ds  
  22.     popl %edx  
  23.     popl %ecx  
  24.     popl %eax  
  25.     iret  
 
其中idt标号的地址就是idt表的其实地址  位于head.s的233行
定义如下
[cpp]  view plain copy
  1. .align 8  
  2. idt:    .fill 256,8,0       # idt is uninitialized  
 
其中.align n 伪指令的含义
在x86 ELF格式中,要在8字节处对齐,应该用 .align 8
而在 a.out格式中,要在8字节处对齐,应该用 .align 3       (2^n),现在一般用elf格式。

 

你可能感兴趣的:(Linux0.11内核--idt(中断描述符表的初始化)head.s分析)