linux-0.11中保护模式建立过程的分析[2]
来源:互联网 发布:交通数据 编辑:程序博客网 时间:2024/05/01 02:34
在setup.s代码中没有重新设置栈寄存器,所以在setup.s中使用的栈是在bootsect.s中设置好的栈。程序开始的代码重新设置段寄存器ds,因为现在的CS段值是0x9020,而代码的数据段是与代码段重叠的,所以要重新段寄存器ds,让它等于CS的段值。
36 mov ax,#INITSEG ! this is done in bootsect already, but...
37 mov ds,ax
然后setup.s就利用BIOS中断,得到一些与硬件相关的信息,并把这些参数放到某个固定的位置(0x9000:0x0000)以提供给后来的程序使用。在使用完BIOS中断后,那么BIOS的中断描述符表就可以被覆盖了,所以接着setup.s就把system模块搬运绝对地址0x00000处。接下来就是setup.s代码一个很重的任务,为CPU进入32位保护模式运行设置好IDT表和GDT表。与IDT表和GDT表有着密切关系的寄存器是IDTR和GDTR寄存器,它们分别存放着IDT表和GDT表的基地址。
133 lidt idt_48 ! load idt with 0,0
134 lgdt gdt_48 ! load gdt with whatever
! appropriate
205 gdt:
206 .word 0,0,0,0 ! dummy
207
208 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
209 .word 0x0000 ! base address=0
210 .word 0x9A00 ! code read/exec
211 .word 0x00C0 ! granularity=4096, 386
212
213 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
214 .word 0x0000 ! base address=0
215 .word 0x9200 ! data read/write
216 .word 0x00C0 ! granularity=4096, 386
217
218 idt_48:
219 .word 0 ! idt limit=0
220 .word 0,0 ! idt base=0L
221
222 gdt_48:
223 .word 0x800 ! gdt limit=2048, 256 GDT entries
224 .word 512+gdt,0x9 ! gdt base = 0X9xxxx
关于在32位模式的寻址方式可以查阅相关的资料,在这里不多说。我比较关心的是CPU是如何从实模式过度到保护模式的。要进入保护模式就要置位寄存器CR0的PE位。Linux是通过下面的代码做到的:
191 mov ax,#0x0001 ! protected mode (PE) bit
192 lmsw ax ! This is it!
193 jmpi 0,8 ! jmp offset 0 of segment 8 (cs)
也许你会问:在执行完指令 lmsw ax 后,CPU就进入了32位的保护模式,那么紧接着的指令jmpi 0,8在保护模式下不就没办法准确寻址了吗?其实在这里要归功于预取指令的作用,当执行指令lmsw ax时,指令jmpi 0,8已经在实模式下被预先取得。所以说在设置寄存器CR0的PE位后下一条指令必须是段间跳转指令,用来更新CS寄存器的内容,并使得CPU预先取得的指令无效,这样就可以让CPU在进入32位保护模式时可以正确的取指令和寻址。在这里要注意jmpi 0,8这条指令,指令中的偏移地址是0,而段值8已经是保护模式下的段选择子。段值8(0b0000,0000,0000,1000)表示请求特权级0,使用全局描述表中的第一项,该项指出代码的基地址是0。因为在之前,linux已经把SYSTEM模块搬运到0x00000地址处,所以该指令的结果就是让CPU开始去运行SYSTEM模块的代码。到此为止,CPU开始工作在32位的保护模式,但是还没有开启地址的页变换管理。执行完这条跳转指令以后,CPU各寄存器的值如图4:
总结一下,setup.s利用BIOS中断得到了一些硬件信息,并把他们放在指定的位置供内核使用。在不在使用BIOS中断的情况下把system模块搬到0x00000处,然后在设置好IDT表和GDT表的情况下开启了保护模式,为system模块的运行提供了基本的环境。
图4:刚进入32位保护模式时各CPU的值
- linux-0.11中保护模式建立过程的分析[2]
- linux-0.11中保护模式建立过程的分析[1]
- linux-0.11中保护模式建立过程的分析[3]
- linux-0.11中保护模式建立过程的分析[4]
- 从保护模式跳到实模式的过程/
- linux 0.12之boot启动过程从实模式变为保护模式的一些说明
- Linux SSH建立连接过程分析
- Linux-0.11 实模式到保护模式
- 实现OS中BOOTLOADER过程,并进入保护模式的代码
- Linux Kernel 2.6.37 启动过程:漫步进入保护模式
- Linux写代码的夜间模式(保护眼睛),在Linux中安装f.lux
- linux kernel 保护模式
- Linux-8086保护模式
- Webkit初始化以及加载URL过程中各种对象的建立时序以及DOM树的建立详情分析
- 保护模式下 中断处理程序的过程
- SSL连接建立过程分析(2)
- SSL连接建立过程分析(2)
- SSL连接建立过程分析(2)
- OSPF汇总
- 今日开博
- PostgreSQL的Command Prompt(命令提示符)的基本操作
- ACE的安装
- 指针数组vs数组指针
- linux-0.11中保护模式建立过程的分析[2]
- ACE线程管理机制-并发控制(1)
- ACE线程管理机制-并发控制(2)
- site优化
- linux-0.11中保护模式建立过程的分析[3]
- ACE线程管理机制-并发控制(3)
- 数据库读写分离
- linux-0.11中保护模式建立过程的分析[4]
- JavaScript判断浏览器类型及版本