计算机启动之后,BIOS会初始化计算机,然后计算机开始自动读取磁盘,磁盘读取一个扇区(512字节),当读到某个磁盘0磁道1扇区扇区的最后的结束地址是0xaa55,BIOS就会认为它是一个引导扇区,然后就会把这512字节的内容装载到内存地址0000:7c00处,然后跳转到0000:7c00处将控制权交给这段引导代码,这样BIOS的任务就结束了,操作系统也成功被引导起来了。作为一个引导扇区,它至少有这样3个条件:1.大小只能为512字节(少了可以填充成0,多了则不行)。2.结束地址为0xaa55。3.加载到0000:7c00处。
在IA32下计算机启动之后,CPU有两种工作模式:实模式、保护模式。在实模式下,物理地址=段值x16+偏移,并且段值和偏移都是16位的,从这个公式可以看出段值是具有实际意义的,它作为了地址的一部分。因为实模式下的数据总线只有16位,也就是一次最多能取2^16=64KB,这就是为什么实模式下每个段最大只有64KB,并且它的地址总线为20位,因此能寻址的能力是2^20=1MB,既然有1MB的寻值能力,但是一次只能读取64KB的数据,所以才引入了分段机制。
但是在保护模式下,段值虽然还是16位,但是意义发生了改变,它变成了一个索引,指向一个数据结构的表项,表项中存着段的起始地址、界限和属性等信息,这个数据结构的名字叫GDT(Global Descriptor Table),表项被称为描述符。GDT提供了段式存储机制,由段寄存器和描述符共同实现,而每个描述符都对应了一个段。段寄存器需要对应到相应的段,只需要通过选择子就可实现,选择子其实就是一系列描述符的索引,在段寄存器中存储对应的索引就行了,它的存储结构如图所示。
在保护模式下,寻址的能力得到了极大的提升,图中RPL占2位,表示段选择子的特权级,TI表示是全局描述符GDT还是局部描述符LDT,索引值有13位,也就是有2^13=8192个段描述符,TI又分GDT和LDT,也就是一共有8192*2=16384个段描述符,可以指定16384个段,每个段的偏移地址值为32位,一个段能达到2^32=4GB,所有段加上就能达到16384*4GB=64TB这么大的寻址能力。
总之,保护模式下的寻址和实模式下有点类似,只是保护模式下的段值指向了GDT中的描述符,通过描述符定位到相应的段,再通过偏移,转换成线性地址,如果没有分页机制,那么该线性地址就是真正的物理地址。
从实模式要转到保护模式,需要以下几个步骤:
第一步就要初始化准备好GDT;
接下来,需要把GDT的物理地址加载到寄存器gdtr中;
然后关闭中断,这是因为保护模式和实模式的中断处理机制不相同;
接着将寄存器cr0的PE位置1,0表示实模式,1表示保护模式;
最后跳转到保护模式。
具体代码参见《ORANGE‘S:一个操作系统的实现》