在《基于8086的IBM PC开机过程》中主要讲解了8086CPU时期的BIOS开机例程讲解的,但出现80386(更准确的说应该是80286)后,麻烦就来了,由于80386的保护模式可以使用超过1M的地址空间,如果把冷启动固件(BIOS)编址在0xF000段内,就会把整个地址空间隔离成不连续的两段,一段是0xF000以前的地址,一段是1M以后的地址,这很不方便。intel采用的办法是,在系统复位时,机器执行的第一条指令安排在0xFFFFFFF0,显然这个地址离80386能寻址的最大范围4G还有16 Bytes的地址空间,因而在这里仍然只是存放了一条跳转指令,通过跳转指令跳到BIOS例行程序起始点。好的现在我们知道8086的CPU开机后执行的第一条指令的物理地址是0xFFFF0,这个物理地址的形成是利用CS的值0xF000左移4位然后加上偏移量IP的值0xFFF0形成的;而现在的32位CPU开机后执行的第一条指令的物理地址是0xFFFFFFF0(CS和IP的值和也是0xF000和0xFFF0);那么这个物理地址是如何形成的呢?答案是这样的:我们通常都说32位CPU开机后首先是处于实模式;不过刚开机的时候CPU并不是按照我们通常所说的那种实模式寻址,即:
物理地址=CS×16+IP;而是使用保护模式下的那种寻址方式;一旦CS中的值被改变了,那么CPU就会恢复到我们通常所说的那种实模式的寻址方式下。然而我们知道保护模式寻址需要根据段选择子从GDT或者LDT中找出相应的描述符,然后取出段基址,用段基址加上偏移量才能得到线性地址;不过在执行第一条指令的时候根本不存在GDT和LDT阿;原来从80286开始每个段寄存器都配有一个高速缓冲寄存器,称之为段描述符高速缓冲寄存器,对程序员而言它是不可见的。每当把一个选择子装入到某个段寄存器时,处理器自动从描述符表中取出相应的描述符,把描述符中的信息保存到对应的高速缓冲寄存器中。此后对该段访问时,处理器都使用对应高速缓冲寄存器中的描述符信息,而不用再从描述符表中取描述符。刚开机的时候CPU会把CS对应的段描述符高速缓冲寄存器中的段基址初始化为0xFFFF0000,并且段限长初始化为0xFFFF(64KB)。因此ROM BIOS被映射到了内存物理地址空间中最后一个段中。当BIOS初始化完毕之后远跳转到0x7c00处开始运行实模式程序时就开始按照通常的实模式寻址方式了,按理说这时候最大寻址空间就是1M,为什么仍然能在0xf000段中访问到ROM BIOS中的代码呢?请看下面:我们说的BIOS ROM,包括很多BIOS的ROM,如视频BIOS ROM和SCSI卡BIOS ROM等,当然还包括我们传统意义上的包含冷启动程序代码以及一系列原始中断服务程序的BIOS的ROM,由于技术的发展,这一部分ROM现在变得非常大,如现在一般的传统BIOS ROM就达2M以上,而视频BIOS ROM等都更大,以前习惯上把这些ROM的地址空间安排在640k以上1M以下的空间里(也就是说640k~1M这一段地址指向ROM而不是指向RAM)。但这一点空间是明显安排不下现在的ROM的,又为了不让这一段ROM的地址将RAM的地址隔离成两段,一般都将这段ROM的地址空间安排在CPU所能访问到的地址的最高端。 

     但为什么我们的程序经过内存空间最高端(0xFFFFXXXX~0xFFFFFFF0)这一段reset code(冷启动代码),并跳转到0x0000:7c00之后,却能从内存地址640k~1M的一段空间里看到诸如reset code等只有在BIOS ROM空间里才会存在的东东的蛛丝马迹呢?理论上此时的640k~1M应该是RAM空间啊?没错这一段现在的确是RAM空间,但基于一个这样的事实,那就是一般ROM的读写速度都比RAM的读写速度慢,所以在执行BIOS ROM中的冷启动代码时,该段代码会将一些重要的与以前的BIOS ROM兼容的东西(如冷启动代码本身)拷贝到640k~1M的地址空间,以后要访问这些内容时就直接到640k~1M的地方去拿,这同时还解决了一个很重要的问题,那就是在实模式下默认是访问不了1M以上的空间的,而BIOS ROM又位于1M以上,那么正好通过访问640k~1M的BIOS ROM副本达到访问BIOS ROM的目的,我们同时也可以看到,拷贝到640k~1M中来的原BIOS ROM中的内容,也是与实模式紧密相关的内容(而那些与实模式关系不大的内容一般就不拷贝过来,也没有地方容纳得下),这个过程叫做BIOS地址映射,它不但达到了提高BIOS访问速度的目的(因为实际上是访问RAM),又使RAM的地址空间没有被隔离开,同时还保持了与8086的兼容性(因为8086默认保留640k~1M的空间给BIOS使用)。

      但是现在又有一个问题:通过什么方法把处于接近4G物理地址处的BIOS中关于实模式的内容映射到实际物理地址640K~1M的地方?事情是这样的:在刚加电或者reset时,CPU实际上处于一种特殊“保护模式”状态。因此此时虽然 CS Selector = 0xF000, 但是不能用实模式下的左移4位再加Offset来确定实际地址。此时:CS Base 就是 0xFFFF0000。而此时的EIP就是CS段中偏移值。 而所有其他段寄存器(ES,DS,ES,FS,SS等)值都是0,基地址 base也为0。因此一开始除CS以外其他段寄存器都可以寻址物理地址0--64KB范围,而CS也只能寻址64KB范围,因为其段限长也是64KB。 因此可以看出,EPROM中必定包含一个使用大模式(这是我随便起的名称:))用来操作代码和数据移动到低端(640KB-1MB)。即BIOS ROM中应该有临时在GDT中设置一个长4GB大段的代码。