1.3.5 head.s开始执行(4)

来源:互联网 发布:php文件管理插件 简洁 编辑:程序博客网 时间:2024/04/20 13:19

1.3.5 head.s开始执行(4)

确定A20地址线已经打开之后,head程序如果检测到数学协处理器存在,则将其设置为保护模式工作状态,图1-33给出了示意。

 图1-33 检测数学协处理器

小贴士

x87协处理器:为了弥补x86系列在进行浮点运算时的不足,Intel于1980年推出了x87系列数学协处理器,那时还是一个外置的、可选的芯片(笔者当时的80386计算机上就没有安装80387协处理器)。1989年,Intel发布了486处理器,自此之后,CPU一般都内置了协处理器。这样,对于486以前的计算机而言,操作系统检验x87协处理器是否存在就非常必要了。

检测数学协处理器对应的代码如下:

  1. //代码路径:boot/head.s  
  2.  
  3. movl %cr0,%eax  
  4. ......  
  5. call check_x87  
  6.  
  7. check_x87:  
  8. ......  
  9. ret 

head程序将为调用main函数做最后的准备,这是head程序执行的最后阶段,也是main函数执行前的最后阶段。

执行代码如下:

  1. //代码路径:boot/head.s  
  2. jmp after_page_tables  
  3.  
  4. after_page_tables:  
  5. pushl $0  
  6. pushl  $0  
  7. pushl  $0 

Linus在代码中的原注释是“These are the parameters to main :-)”,但实际上我们并没有看到,也没有测试到main函数使用这三个参数,具体如图1-34下方的标示。

 图1-34 将envp、argv、argc压栈

head程序将L6标号和main函数入口地址压栈,栈顶为main函数地址,目的是使head程序执行完后通过ret指令就可以直接执行main函数,具体请见图1-35下方的标示。

 图1-35 将main函数入口地址和L6标号压栈

如果main函数退出,就会返回到这里的标号L6处继续执行下去,并产生死循环。

执行代码如下:

  1. //代码路径:boot/head.s  
  2. pushl $L6  
  3. pushl $_main 

这些压栈动作完成后,head程序将跳转至setup_paging:去执行,开始创建分页机制。

首先会将页目录表和4个页表放在物理内存的起始位置。从内存起始位置开始的5页空间内容全部清零(每页4KB),为初始化页目录和页表做准备。注意,这个动作起到了用一个页目录表和4个页表覆盖head程序自身所占内存空间的作用。图1-36下方给出了直观的示意图。

 图1-36 将页目录表和页表放在内存起始位置
上述动作的执行代码如下:

  1. //代码路径:boot/head.s  
  2. jmp setup_paging  
  3.  
  4. setup_paging:  
  5. movl $1024*5,%ecx  
  6. xorl %eax,%eax  
  7. xorl %edi,%edi  
  8. cld;rep;stosl 

点评

将页目录表和4个页表放在物理内存的起始位置,这个动作的意义重大,是操作系统能够掌控全局、掌控进程在内存中安全运行的基石之一,后续章节会逐步论述。

head程序将页目录表和4个页表所占物理内存空间清0后,设置页目录表的前4项,使之分别指向4个页表,如图1-37左下方所示。

 图1-37 使页目录表的前4项指向4个页表
0 0
原创粉丝点击