CPU的第一条指令


我们知道,CPU的指令寄存器叫EIP,存放着下一条指令的地址。问题是,当计算机通电后,EIP的值是多少呢?它又是如何被设置的呢?

答案是,在80386以后,这个值是FFFFFFF0,被硬编码在CPU中,属于CPU内部的一部分。可以想象CPU内有一个电路,在通电后这个电路会往EIP寄存器输入这个固定的值。同时被设置的还有段寄存器CS。

CS的值是F000,IP的值是FFF0,所以 CS:IP = F000:FFF0 ,即 FFFF0,此处即1MB-16Bytes。这里被称作「Reset vector」,通常是一条JUMP指令,跳转到BIOS程序入口开始执行。

bootMemoryRegions

注意,这部分是重点,因为一般非专业人士都是从BIOS开始讲起,而其实,从BIOS开始就没什么好讲的,CS专业学生都知道的。而这一部分涉及硬件的,书本上一般不会有。

 

BIOS


BIOS会做一些硬件检查的操作,称为「Power-on Self Test」(POST),这期间,如果硬件出现问题,BIOS会停机并发出蜂鸣,在屏幕上打印出一些信息。

接着,BIOS会按照设备的顺序查找哪个设备可以用于启动。这些设备包括硬盘、CD-ROM、软盘等等。(这些设备的启动顺序是可以人为通过BIOS提供的设置界面修改的)

设备的前512个字节,被称为「Master Boot Record」(主引导记录),可启动设备的最后两个字节必须是0x550xAA

masterBootRecord

一旦发现可启动设备,这512字节就被拷贝入内存7C00处执行。由于字节所限,这个MBR代码,一般是做「拷贝」操作:把磁盘的另一个程序拷贝进内存执行。这个程序早期直接是内核,而现在则一般是像GRUB这种「Boot Loader」。

 

没有GRUB的年代


在没有GRUB、LILO这类「Boot Loader」的年代里,MBR里的代码通常是做以下这件事的:把操作系统内核拷贝到内存的某个地方,并开始执行。计算机控制权交给操作系统。

具体可参考早期的Linux内核代码

 

有GRUB的年代


「Boot Loader」 是独立于操作系统而存在,这里以GRUB为例。

一旦用户选定操作系统,GRUB 就从文件系统中将内核载入内存执行,此时,计算机的控制权正式由操作系统接管。

 

参考链接


  1. Intel 64 and IA-32 Architecture Software Developer’s Manual - PDF

    Intel. May 2012. Section 9.1.4 First Instruction Executed, p.

    1. Retrieved August 23, 2012.

    The first instruction that is fetched and executed following a hardware reset is located at physical address FFFFFFF0h. This address is 16 bytes below the processor’s uppermost physical address. The EPROM containing the software-initialization code must be located at this address.

  2. 《Operating Systems》 by Sibsankar Haldar & Alex Alagarsamy Aravind

    The inital default values of CPU registers are hard-coded in the processor. These values never change.

  3. How Computer Boots

    The moment after a computer is powered on, it is practically useless because the RAM chips contain random data and no operating system is running. To begin the boot, a special hardware circuit raises the logical value of the RESET pin of the CPU. After RESET is thus asserted, some registers of the processor (including cs and eip) are set to fixed values, and the code found at physical address 0xfffffff0 is executed.