在前面我们已经介绍了x64架构的处理器所支持的各种工作模式。当处理器加电或者复位之后,处理器工作在实地址模式下。从实地址模式可以切换到保护模式,从保护模式可以返回实地址模式。
进一步地,从保护模式可以进入IA-32e模式,从IA-32e模式也可以返回保护模式。如图3-1所示,在开机或者重启后,64位处理器工作在实地址模式下。将控制寄存器CR0的PE位置1,处理器进入保护模式。在保护模式下,通过开启IA-32e模式、开启物理地址扩展PAE功能,然后开启分页,就进入了IA-32e模式。
图3-1 64位x86处理器各工作模式之间的切换
需要注意的是,如果在保护模式下已经开启了分页,则必须先关闭分页功能。这是因为保护模式下用的是传统的分页方式,而IA-32e模式必须使用4级或者5级分页,所以只能先关闭分页,初始化4级或者5级分页,最后再开启或者重新开启分页,从而最终激活IA-32e模式。
刚进入IA-32e模式时,是进入IA-32e的兼容模式。这是因为在保护模式下代码段描述符和代码段寄存器的L位是保留的,必须置0。因此,进入IA-32e模式后,代码段寄存器的L位依然是0,自然就工作在兼容模式下。
通过执行一个描述符的L位是1的代码段,可以从兼容模式切换到64位模式;如果再执行一个L位是0的代码段,则切换到兼容模式。
要想从IA-32e模式返回保护模式,必须工作在兼容模式下,这是为了保证代码段寄存器的L位是0。换句话说,如果处理器工作在64位模式下,必须先切换到兼容模式。在兼容模式下,关闭分页,再关闭IA-32e模式,就回到了保护模式。
从这一章开始,我们将完整地演示从加电开机一直到进入64位模式的整个过程,其总体执行流程如下。
首先,开机或者重启之后,执行我们的程序。在我们的程序中,先判断当前处理器是否为x64架构的处理器,如果不是,则显示信息并停机。本书是讲64位的处理器,所以你的处理器必须是64位的,这是基本要求。
如果是64位的处理器,则我们获取处理器的物理地址线数量和虚拟地址位数。这个虚拟地址位数通常是48,未来将支持57位的虚拟地址。
接下来,我们创建全局描述符表GDT并安装必要的段描述符,然后进入保护模式。进入保护模式后,创建初始的4级分页结构,因为IA-32e模式要求必须开启分页,而且必须使用4级或者5级分页机制。
做好了准备工作之后,我们进入IA-32e模式。最开始的时候,一定是在兼容模式下执行,所以我们最终会从兼容模式进入64位模式。