2. CPU

CPU总是周而复始地做同一件事:从内存取指令,然后解释执行它,然后再取下一条指令,再解释执行。CPU最核心的功能单元包括:

上图中画了32条地址线和32条数据线,CPU寄存器也是32位,可以说这种体系结构是32位的,比如x86就是这样的体系结构,目前主流的处理器是32位或64位的。地址线、数据线和CPU寄存器的位数通常是一致的,从上图可以看出数据线和CPU寄存器的位数应该一致,另外有些寄存器(比如程序计数器)需要保存一个内存地址,因而地址线和CPU寄存器的位数也应该一致。处理器的位数也称为字长,字(Word)这个概念用得比较混乱,在有些上下文中指16位,在有些上下文中指32位(这种情况下16位被称为半字Half Word),在有些上下文中指处理器的字长,如果处理器是32位那么一个字就是32位,如果处理器是64位那么一个字就是64位。32位计算机有32条地址线,地址空间(Address Space)从0x00000000到0xffffffff,共4GB,而64位计算机有更大的地址空间。

最后还要说明一点,本节所说的地址线、数据线是指CPU的内总线,是直接和CPU的执行单元相连的,内总线经过MMU和总线接口的转换之后引出到芯片引脚才是外总线,外地址线和外数据线的位数都有可能和内总线不同,例如32位处理器的外地址总线可寻址的空间可以大于4GB,到第 4 节 “MMU”再详细解释。

我们结合表 1.1 “一个语句的三种表示”看一下CPU取指执行的过程。

图 17.3. CPU的取指执行过程

CPU的取指执行过程

  1. eip寄存器指向地址0x80483a2,CPU从这里开始取一条5个字节的指令,然后eip寄存器指向下一条指令的起始地址0x80483a7。

  2. CPU对这5个字节译码,得知这条指令要求从地址0x804a01c开始取4个字节保存到eax寄存器。

  3. 执行指令,读内存,取上来的数是3,保存到eax寄存器。注意,地址0x804a01c~0x804a01f里存储的四个字节不能按地址从低到高的顺序看成0x03000000,而要按地址从高到低的顺序看成0x00000003。也就是说,对于多字节的整数类型,低地址保存的是整数的低位,这称为小端(Little Endian)字节序(Byte Order)。x86平台是小端字节序的,而另外一些平台规定低地址保存整数的高位,称为大端(Big Endian)字节序。

  4. CPU从eip寄存器指向的地址取一条3个字节的指令,然后eip寄存器指向下一条指令的起始地址0x80483aa。

  5. CPU对这3个字节译码,得知这条指令要求把eax寄存器的值加1,结果仍保存到eax寄存器。

  6. 执行指令,现在eax寄存器中的数是4。

  7. CPU从eip寄存器指向的地址取一条5个字节的指令,然后eip寄存器指向下一条指令的起始地址0x80483af。

  8. CPU对这5个字节译码,得知这条指令要求把eax寄存器的值保存到从地址0x804a018开始的4个字节。

  9. 执行指令,把4这个值保存到从地址0x804a018开始的4个字节(按小端字节序保存)。