计算机启动过程内存布局


    1981年IBM PC机刚推出时系统只带有640KB的RAM主存储器(简称内存)。由于所采用的8088/8086 CPU只有20根地址线,因此内存寻址范围最高为1024KB(1MB)。 在当时DOS操作系统流行年代,640K或者1MB内存容量基本上能满足普通应用程序的运行。随着计算机软件和硬件技术的高速发展,目前的计算机通常都配置有512MB或者更多的物理内存容量, 并且都采用Intel 32位CPU,即都是PC/AT计算机。因此CPU的物理内存寻址范围已经高达4GB(通过采用CPU的新特性,系统甚至可以寻址64GB的物理内存容量)。
    但是为了与原来的PC机在软件上兼容,系统1MB以下物理内存使用分配上任然保持与原来的PC机基本一致,只是原来系统ROM中的基本输入输出程序BIOS一直处于CPU能寻址的内存最高端位置处, 而BIOS原来所在的位置将在计算机开机初始化时被用作BIOS的影子(Shadow)区域,即BIOS代码任然会被复制到这个区域中。

    pc机内存使用区域图

    当计算机上电初始化时,物理内存被设置成从地址0开始的连续区域。除了地址从0xA0000-0x100000(640K到1M共384K)和0xFFFFE0000-0xFFFFFFFF(4G处的最后64K) 范围以外的所有内存都可用作系统内存。这两个特定范围被用于I/O设备和BIOS 程序。假如我们的计算机中有16MB的物理内存,那么在Linux 0.1x系统中: 0-640K将被用作存放内核代码和数据。Linux内核不使用BIOS功能,也不使用BIOS设置的中断向量表。
    640K-1M之间的384K仍然保留用作图中指明的用途。其中地址从0xA0000开始的128K用作显示内存缓冲区,随后部分用于其他控制卡的ROM BIOS或其映射区域。 而0xF0000-1M范围用于高端操作系统ROM BIOS的映射区。
    1M-16M将被内核用于作为可分配的主内存区。另外高速缓冲区和内存虚拟盘也会占用内核代码和数据后面的一部分内存区域,该区域通常会跨越640K-1M的区域。

    存放在ROM中的系统BIOS程序主要用于计算机开机时执行系统各部分的自检,建立起操作系统需要使用的各种配置表,例如中断向量表、硬盘参数表。
    并且把处理器和系统其余部分初始化到一个已知状态,而且还为DOS等操作系统提供硬件设备接口服务。但是由于BIOS提供的这些服务不具备可重入性(即其中程序不可并发运行), 并且从访问效率方面考虑,因此除了在初始化时会利用BIOS提供一些系统参数以外,Linux操作系统在运行时并不使用BIOS中的功能。

    flash、rom、bios位置和复制映射区域

    当计算机系统上电开机或者按了机箱上的复位按钮时,CPU会自动把代码段寄存器CS设置为0xF000,其段基地址则被设置为0xFFFF0000,段长度设置为64KB。而IP被设置为 0xFFF0,因此此时CPU代码指针指向0xFFFFFFF0处,即4G空间的最后64K的最后16字节处。由上面的内存使用区域图可知,这里正是系统ROM BIOS存放的位置。并且BIOS 会在这里存放一条跳转指令JMP,跳转到BIOS代码中64KB范围内的某一条指令开始执行。
    由于目前PC/AT微机中BIOS容量大多有1MB到2MB,并存储在闪存(Flash Memory) ROM中,因此为了能够执行或访问BIOS中超过64KB范围并且又远远不在0-1M 地址空间中的其他BIOS代码或数据,BIOS程序会首先使用一种称为32位大模式(Big Mode)技术把数据段寄存器的访问范围设置成4G(而非原来的64K),这样cpu就可以在0到4G 范围内执行和操作数据。此后,BIOS在执行了一系列硬件检测和初始化操作之后,就会把与原来PC机兼容的64KB BIOS代码和数据复制到内存低端1M末端的64K处, 然后跳转到这个地方并且让CPU进入真正的实地址模式下工作。最后BIOS就会从硬盘或其他块设备把操作系统引导程序bootloader加载到内存0x7C00处,并跳转到这个地方继续执行引导程序。

    对于很多人来讲0x7C00这个地址是很神秘的,不知道这是干什么的。但是对于了解过x86平台下BIOS启动过程的人,对这个地址再熟悉不过了。
    BIOS就是将MBR读入0x7C00地址,然后进行后续的引导的。操作系统或是bootloader开发者必须假设他们的汇编代码被加载并从0x7C00处开始执行。
    对于这个地址,它不属于Intel x86平台规范的,而是属于BIOS规范中定义的内容。0x7C00第一次出现在IBM PC 5150的BIOS处理int 19(19号中断)的时候, IBM PC 5150是x86(32位)IBM PC/AT系列的祖先,这款PC于1981年发布,使用了intel 8088(16位)的处理器和16KB的RAM内存,BIOS和微软的基本指令均放在该内存中。 当打开电源,BIOS开始自检,然后出发19号中断,在处理19号中断时,BIOS检测电脑是否具有软盘、硬盘或是固定磁盘,如果有任何可以使用的磁盘, BIOS就把磁盘的第一个扇区(512B)加载到内存的0x7C00地址处。
    0x7C00地址第一次出现在IBM PC 5150的ROM bios中,在此之前使用的地址是0×200。使用该地址的原因主要有:
    当时8086中断向量使用地址为0×0-0x3FF;86-DOS从0×400处被加载;而它不使用0×200-0x3FF这段中断向量地址。 因此这段0×200-0x3FF地址不能被其他程序使用,Tim Paterson(86-DOS开发者)选择0×200作为MBR加载地址。
    他们想留下32kb内更多的空间给操作系统来加载自己;8086/8088使用0×0-0x3FF作为中断向量,然后BIOS数据紧随之后; 引导扇区是512字节,但是用于引导程序的栈或数据区域需要多于512字节; 因此0x7C00,32kb(rong:0x8000=32kb=32768b 0x7C00=31744b)中的最后1kb(rong:0x7C00=31744b32768-31744=1024)被选中。
    一旦操作系统被引导并开始,引导扇区将一直不会被使用直到重启,因此操作系统和应用程序可以自由的使用32KB的最后1kb空间。

    在PC/AT机中,除需要使用内存和ROM BIOS以外,还使用只有很少存储容量的(只有64或128字节)CMOS (Complementary Metal Oxide Semiconductor,互补金属氧化物半导体) 存储器来存放计算机的实时时钟信息和系统硬件配置信息。这部分内存通常和实时时钟芯片(Real Time Chip)做在一块集成块中。CMOS内存的地址空间在基本内存地址空间之外, 需要使用 I/O 指令来访问。

    initroot编辑整理,转载请注明出处 www.initroot.com

    100次点赞 100次阅读