menu

实模式

实模式

8086的寻址方式 8086为16位CPU,它的所有寄存器和寄存器之间的数据总线都是16位的,而其外部数据总线却是20位。如何用16位的数据总线访问20位(1M的地址空间):段式寻址 以CS:IP为例,段式寻址需要使用一个寄存器作为段寄存器比如CS代码段寄存器,使用另外一个寄存器比如IP指令指针寄存器作为偏移寄存器。 如何计算其物理地址: 首先将段寄存器的16位地址向左移动4位,然后将左移4位后的段地址与偏移地址相加就可以得到一个20位的物理地址(也可以理解成最开始的段寄存器的地址默认后面还有4位,只是都省略成0,这样就可以放在16位寄存器中了。)

实模式的寻址方式 实模式(Real mode) 是Intel 80286和之后的80x86兼容CPU的操作模式,所有的80x86CPU的开机状态都是实模式。实模式的特性是一个20位的存储器地址空间(即1MB的存储器)可以被寻址。为了兼容,也为了解决最开始的启动问题,Intel将所有80x86系列的CPU(包括最新型号的64位CPU)的硬件都设计为加电即进入16位实模式状态运行。在实模式状态下寄存器是16位的,地址总线是20位的,也就是说实模式下寻址空间为1MB。因此与8086这个16位机器一样,为了实现20位寻址依然采取段式寻址方式。

开机时的第一个操作就是执行BIOS程序,CPU的硬件逻辑被设计为加电瞬间强行将CS的值设置为0XF000,IP的值设置为0XFFF0,这样CS:IP 的地址就是CS值左移四位变成0xF0000后加上IP的偏移地址也就是0xF0000+0XFFF0 也就是0xFFFF0,而0xFFFF0这个地址也就是BIOS程序的地址,CPU将开始执行这个地址的BIOS代码,从而开始BIOS的启动。

8086段式寻址的发展历程 8086处理器引入了一个重要概念–段。(目标,想要的结果)8086处理器的寻址目标是1M大的内存空间,于是它的地址总线扩展到了20位。但是,一个问题摆在了Intel设计人员面前,(问题)虽然地址总线宽度是20位的,但是CPU中“算术逻辑运算单元(ALU)”的宽度,即数据总线却只有16位,也就是可直接加以运算的指针长度是16位的。如何填补这个空隙呢?可能的解决方案有多种,例如,可以像一些8位CPU中那样,增设一些20位的指令专用于地址运算和操作,但是那样又会造成CPU内存结构的不均匀。又例如,当时的PDP-11小型机也是16位的,但是其内存管理单元(MMU)可以将16位的地址映射到24位的地址空间。受此启发,(解决方案)Intel设计了一种在当时看来不失为巧妙的方法,即分段的方法。

为了支持分段,Intel在8086 CPU中设置了四个段寄存器:CS、DS、SS和ES,分别用于可执行代码段、数据段、堆栈段及其他段。每个段寄存器都是16位的,对应于地址总线中的高16位。每条“访内”指令中的内部地址也都是16位的,但是在送上地址总线之前,CPU内部自动地把它与某个段寄存器中的内容相加。因为段寄存器中的内容对应于20位地址总线中的高16位(就是把段寄存器左移4位),所以相加时实际上是内存总线中的高12位与段寄存器中的16位相加,而低4位保留不变,这样就形成一个20位的实际地址,也就实现了从16位内存地址到20位实际地址的转换,或者叫“映射”。段式内存管理带来了显而易见的优势,程序的地址不再需要硬编码了,调试错误也更容易定位了,更可贵的是支持更大的内存地址。程序员开始获得了自由。

技术的发展不会就此止步。intel的80286处理器于1982年问世了,它的地址总线位数增加到了24位,因此可以访问到16M的内存空间。更重要的是从此开始引进了一个全新理念–保护模式。这种模式下内存段的访问受到了限制。访问内存时不能直接从段寄存器中获得段的起始地址了,而需要经过额外转换和检查。为了和过去兼容,80286内存寻址可以有两种方式,一种是先进的保护模式,另一种是老式的8086方式,被成为实模式。系统启动时处理器处于实模式,只能访问1M空间,经过处理可进入保护模式,访问空间扩大到16M,但是要想从保护模式返回到实模式,你只有重新启动机器。还有一个致命的缺陷是80286虽然扩大了访问空间,但是每个段的大小还是64k,程序规模仍受到限制。因此这个先天低能儿注定寿命不会很久。很快它就被天资卓越的兄弟–80386代替了。

80386是一个32位的CPU,也就是它的ALU数据总线是32位的,同时它的地址总线与数据总线宽度一致,也是32位,因此,其寻址能力达到4GB。对于内存来说,似乎是足够了。从理论上说,当数据总线与地址总线宽度一致时,其CPU结构应该简洁明了。但是,80386无法做到这一点。作为X86产品系列的一员,80386必须维持那些段寄存器的存在,还必须支持实模式,同时又要能支持保护模式,这给Intel的设计人员带来很大的挑战。Intel选择了在段寄存器的基础上构筑保护模式,并且保留段寄存器16位。在保护模式下,它的段范围不再受限于64K,可以达到4G。这一下真正解放了软件工程师,他们不必再费尽心思去压缩程序规模,软件功能也因此迅速提升。

从8086的16位到80386的32位处理器,这看起来是处理器位数的变化,但实质上是处理器体系结构的变化,从寻址方式上说,就是从“实模式”到“保护模式”的变化。从80386以后,Intel的CPU经历了80486、Pentium、PentiumII、PentiumIII等型号,虽然它们在速度上提高了好几个数量级,功能上也有不少改进,但基本上属于同一种系统结构的改进与加强,而无本质的变化,所以我们把80386以后的处理器统称为IA32(32 Bit Intel Architecture)。

当时,搭配的操作系统是86-DOS。这个操作系统需要的内存最少是32KB。我们知道,内存地址从0x0000开始编号,32KB的内存就是0x0000~0x7FFF。

8088芯片本身需要占用0x0000~0x03FF,用来保存各种中断处理程序的储存位置。(主引导记录本身就是中断信号INT 19h的处理程序。)所以,内存只剩下0x0400~0x7FFF可以使用。

为了把尽量多的连续内存留给操作系统,主引导记录就被放到了内存地址的尾部。由于一个扇区是512字节,主引导记录本身也会产生数据,需要另外留出512字节保存。所以,它的预留位置就变成了: 0x7FFF - 512 - 512 + 1 = 0x7C00

计算机启动后,32KB内存的使用情况如下。 +——————— 0x0 | Interrupts vectors +——————— 0x400 | BIOS data area +——————— 0x5?? | OS load area +——————— 0x7C00 | Boot sector +——————— 0x7E00 | Boot data/stack +——————— 0x7FFF | (not used) +——————— (…)