1.2 CPU是寄存器的集合体
CPU的四个构成部分中,程序员只需要了解寄存器即可,其余三个都不用太过关注。那么,为什么必须要了解寄存器呢?这是因为程序是把寄存器作为对象来描述的。
首先我们来看一下代码清单1-1。这是用汇编语言(assembly)编写的程序的一部分。汇编语言采用助记符(memonic)来编写程序,每一个原本是电气信号的机器语言指令都会有一个与其相应的助记符,助记符通常为指令功能的英语单词的简写。例如,mov和add分别是数据的存储(move)和相加(addition)的简写。汇编语言和机器语言基本上是一一对应的。这一点和C语言、Java语言等高级编程语言有很大不同,这也是我们使用汇编语言来说明CPU运行的原因。通常我们将汇编语言编写的程序转化成机器语言的过程称为汇编;反之,机器语言程序转化成汇编语言程序的过程则称为反汇编。
代码清单1-1 汇编语言编写的程序示例
mov eax, dword ptr [ebp-8] …把数值从内存复制到eax add eax, dword ptr [ebp-0Ch] …eax的数值和内存的数值相加 mov dword ptr [ebp-4], eax …把eax的数值(上一步的相加结果)存储在内存中
通过阅读汇编语言编写的代码,能够了解转化成机器语言的程序的运行情况。从代码清单1-1的汇编语言程序示例中也可以看出,机器语言级别的程序是通过寄存器来处理的。也就是说,在程序员看来“CPU是寄存器的集合体”。至于控制器、运算器和时钟,程序员只需要知道CPU中还有这几部分就足够了。
代码清单1-1中,eax和ebp表示的都是寄存器。通过阅读刚才的示例代码,想必大家对程序使用寄存器来实现数据的存储和加法运算这一情况应该有所了解了。汇编语言是80386以上的CPU所使用的语言。eax和ebp是CPU内部的寄存器的名称。内存的存储场所通过地址编号来区分,而寄存器的种类则通过名字来区分。
上文可能有些难以理解,不过不用担心,因为我们并不要求大家必须掌握CPU的所有寄存器种类和汇编语言,大家只需对CPU是怎么处理程序的有一个大致印象即可。也就是说,使用高级语言编写的程序会在编译后转化成机器语言,然后再通过CPU内部的寄存器来处理。例如,a=1+2这样的高级语言的代码程序在转化成机器语言后,就是利用寄存器来进行相加运算和存储处理的。
不同类型的CPU,其内部寄存器的数量、种类以及寄存器存储的数值范围都是不同的。不过,根据功能的不同,我们可以将寄存器大致划分为八类,如表1-1所示。可以看出,寄存器中存储的内容既可以是指令也可以是数据。其中,数据分为“用于运算的数值”和“表示内存地址的数值”两种。数据种类不同,存储该数值的寄存器也不同。CPU中每个寄存器的功能都是不同的。用于运算的数值放在累加寄存器中存储,表示内存地址的数值则放在基址寄存器和变址寄存器中存储。代码清单1-1的程序中用到的eax和ebp分别是累加寄存器和基址寄存器。
表1-1 寄存器的主要种类和功能
对程序员来说,CPU是什么呢?如图1-3所示,CPU是具有各种功能的寄存器的集合体。其中,程序计数器、累加寄存器、标志寄存器、指令寄存器和栈寄存器都只有一个,其他的寄存器一般有多个。程序计数器和标志寄存器比较特殊,这一点在后面的章节中会详细说明。另外,存储指令的指令寄存器等寄存器,由于不需要程序员做多关注,因此图1-3中没有提到。
图1-3 程序员眼中的CPU(CPU是寄存器的集合体)