1.3.5 head.s开始执行(3)
来源:互联网 发布:pathfinder软件价格 编辑:程序博客网 时间:2024/04/27 10:38
1.3.5 head.s开始执行(3)
代码如下:
- //代码路径:boot/head.s
- setup_gdt
- ............
- setup_gdt:
- lgdt gdt_descr
- ret
- _gdt: .quad 0x0000000000000000 /* NULL descriptor */
- .quad 0x00c09a0000000fff /* 16Mb */
- .quad 0x00c0920000000fff /* 16Mb */
- .quad 0x0000000000000000 /* TEMPORARY-don't use */
- .fill 252,8,0 /* space for
LDT's and TSS's etc */
点评
为什么要废除原来的GDT而重新设置一套GDT呢?
原来GDT所在的位置是设计代码时在setup.s里面设置的,将来这个setup模块所在的内存位置会在设计缓冲区时被覆盖。如果不改变位置,GDT的内容将来肯定会被缓冲区覆盖掉,从而影响系统的运行。这样一来,将来整个内存中唯一安全的地方就是现在head.s所在的位置了。
那么有没有可能在执行setup程序时直接把GDT的内容拷贝到head.s所在的位置呢?肯定不能,如果先复制GDT的内容,后移动system模块,它就会被后者覆盖掉;如果先移动system模块,后复制GDT的内容,它又会把head.s对应的程序覆盖掉,而这时head.s还没有执行呢。所以,无论如何,都要重新建立GDT。
全局描述符表GDT的位置和内容发生了变化,特别要注意最后的三位是fff,说明段限长不是原来的8MB,而是现在的16MB。如果后面的代码第一次使用这几个段选择符就是访问8MB以后的地址空间,将会产生段限长超限报警,为了防止这类可能发生的情况,这里再次对一些段选择符进行重新设置,包括DS、ES、FS、GS和SS,方法与图1-26类似,主要是段限长增加了一倍,变为了16MB。上述过程如图1-30所示。
调整DS和ES等寄存器的对应代码如下:
- //代码路径:boot/head.s
- movl $0x10,%eax # reload all the segment registers
- mov %ax,%ds # after changing gdt. CS was already
- mov %ax,%es # reloaded in 'setup_gdt'
- mov %ax,%fs
- mov %ax,%gs
通过测试我们发现,这是一种舍近求远的方法,其实只要在setup中构建第一个GDT表时把控制段限长的7ff直接设置为fff就可以一步到位了,不需要在这里重新设置段选择符。
现在user_stack数据结构的起始位置就是内核栈的栈底,栈顶指针esp指向user_stack数据结构的外边缘,也就是内核栈的栈顶。这样,当后面的程序需要压栈时,就可以最大限度地使用栈空间。栈顶的增长方向是从高地址向低地址的,如图1-31所示。设置esp的代码如下:
图1-31 设置内核栈因为A20地址线是否打开是保护模式与实模式的根本区别,所以,现在要检验A20地址线是否确实打开了。图1-32在左下部给出了直观的标示。
- //代码路径:boot/head.s
- lss _stack_start,%esp
图1-32 检验A20是否打开检验A20是否打开的代码如下:
- //代码路径:boot/head.s
- xorl %eax, %eax
- 1: incl %eax
- movl %eax, 0x000000
- cmpl %eax, 0x100000
- je 1b
点评
A20如果没有打开,则计算机处于实模式下,超过0xFFFFF寻址必然“回滚”。一个特例是0x100000就会回滚到0x000000,也就是说,地址0x100000处存储的值必然和地址0x000000处存储的值完全相同(参见图1-30的描述)。通过在内存0x000000位置写入一个数据,然后比较此处和1MB(即0x100000,注意,已超过实模式寻址范围)处数据是否一致,就可以检验A20地址线是否已打开。
- 1.3.5 head.s开始执行(3)
- 1.3.5 head.s开始执行(5)
- 1.3.5 head.s开始执行(1)
- 1.3.5 head.s开始执行(2)
- 1.3.5 head.s开始执行(4)
- 1.3.5 head.s开始执行(6)
- 1.3.4 为在保护模式下执行head.s做准备
- head.s
- head.s
- html5系列3 : 从头开始-head标签
- head.s分析(5):关闭串口
- head-armv.S分析(转)
- Linux启动过程分析(head.s)
- uclinux-2008R1-RC8(bf561)到VDSP5的移植(3):Head.s
- Compressed 'head.S'
- Linux/boot/head.S
- linux-head.s
- head.S of arch
- java(Android)——内存泄露的一些经典案例
- 银联基于OpenStack的金融私有云建设实践
- Android内核sysfs中switch类使用实例
- 更换phpcms后台编辑器自动添加的<div>标签为<P>标签
- 第6周—项目4 数制转换
- 1.3.5 head.s开始执行(3)
- spring 使用spel
- hdu4267A Simple Problem with Integers 线段树
- Hibernate 不同数据库的连接及SQL方言
- 位,字节,字的区别
- LeetCode(79) Word Search
- ZOJ 1115
- hdu4293Groups dp
- C#实现的等额本息法、按月付息到期还本法、一次性还本付息法