计算机指令
从软件工程师的角度来看,CPU是执行计算机指令的逻辑机器。计算机指令可以看作是CPU能够理解的语言,也称为机器语言。
不同的CPU能理解的语言不同。例如,个人电脑使用Intel的CPU,苹果手机使用ARM的CPU。这两种CPU支持的语言不同。这些不同CPU支持的语言被称为不同的指令集。
不同的CPU有不同的指令集,对应不同的汇编语言和机器码。为了简化机器码的理解,我们选择了最简单的MIPS指令集来说明机器码的生成过程。MIPS是由MIPS技术公司在80年代中期设计的CPU指令集。不久前,MIPS公司将整个指令集和芯片架构完全开源。
MIPS指令是一个32位的整数,其中高6位是操作码,表示具体的指令类型,剩下的26位有三种格式:R、I和J。
- R指令通常用于算术和逻辑操作,包括读取和写入寄存器的地址。对于逻辑位移操作,还需要位移操作的位移量。最后的功能码表示具体的指令。
- I指令通常用于数据传输、条件分支和运算时使用的非变量或常数。它没有位移量和操作码,也没有第三个寄存器,而是将这三部分直接合并成一个地址值或常数。
- J指令是跳转指令,高6位之外的26位是跳转后的地址。
ini
// test.c
int main()
{
int a = 1;
int b = 2;
a = a + b;
}
为了在Linux操作系统上运行这段代码,我们需要将整个程序编译成汇编语言的代码。然后使用汇编器将汇编代码翻译成机器码。这些机器码由0和1组成的机器语言表示。每条机器码都是一条计算机指令。这些16进制数字就是CPU可以识别的计算机指令。 汇编代码实际上就是给程序员看的机器码。由于难以理解8b 45 f8这样的机器码,人类更容易记住用英文表示的指令,如add、mov等。
从高级语言到汇编代码,再到机器码,是将开发的程序转变为CPU可以执行的计算机指令的过程。
CPU如何执行指令
CPU 内部处理过程
下图展示了一般程序(以 C 语言为例,java语言类似)的运行流程。了解程序的运行流程是掌握程序运行机制的基础和前提。
在这个流程中,中央处理器 (CPU) 的主要任务是解释和执行最终转换成机器语言的指令。CPU 由两个主要部分构成,包括控制单元和算术逻辑单元 (ALU)。 控制单元负责从内存中提取指令,并对其进行解码和执行。 算术逻辑单元 (ALU) 则负责处理算术和逻辑运算。
CPU被称为计算机的心脏和大脑,它由许多晶体管组成的电子部件构成,与内存一起协同工作。CPU接收数据输入,执行指令并处理信息。它还与输入/输出(I/O)设备进行通信,这些设备向CPU发送数据并从CPU接收数据。 从功能的角度来看,CPU的内部由寄存器、控制器、运算器和时钟四个部分组成,并且这些部分之间通过电信号进行相互连接。
- 寄存器是一种高速存储器,用于暂时存储指令、数据和中间结果。
- 控制器负责从内存中提取指令,并将其解码为操作信号,以控制其他部件的工作。
- 运算器则负责执行算术和逻辑运算,包括加法、减法、乘法、除法和比较等操作。
- 时钟是CPU的主时钟,用于同步各个部件的操作,确保它们按照正确的顺序和时序运行。通过这些部分的协同工作,CPU能够高效地执行各种计算任务。
CPU可以被分为三个主要部分,即运算单元、数据单元和控制单元。 运算单元主要负责进行各种计算操作,如加法、位移等。然而,运算单元并不知道应该计算哪些数据,也不知道计算结果应该存放在哪里。 如果每次计算的数据都需要通过总线传输到内存中,这将导致非常低效。因此,数据单元的存在就变得必要了。数据单元包括CPU内部的缓存和寄存器组,虽然空间较小,但速度非常快,可以暂时存储数据和计算结果。 有了数据存放的地方和计算的地方,还需要一个指挥中心来决定具体要进行哪些计算操作,这就是控制单元。控制单元充当统一的指挥中心,它可以获取下一条指令,并执行该指令。这条指令将指导运算单元从数据单元中取出特定的数据,进行计算,并将结果放回数据单元的相应位置。通过这样的指令执行过程,CPU能够高效地进行各种计算任务。
CPU的控制单元包含一个指令指针寄存器,它存储着下一条指令在内存中的地址。控制单元的工作是不断地将代码段中的指令加载进来,并将其放入指令寄存器中。
每条指令可以分为两个部分:操作类型(如加法或位移)和操作数据。为了执行这条指令,控制单元将操作类型传递给运算单元,将操作数据传递给数据单元。
数据单元根据数据的地址从数据段中读取数据,并将其存储在数据寄存器中,以便参与运算。运算单元执行完运算后,将结果暂时存储在数据单元的数据寄存器中。最后,通过指令将数据写回内存中的数据段。
或许你会好奇,上述的操作都是针对进程 A 的指令进行的,那进程 B 呢?CPU 内部有两个专门保存当前处理进程的代码段起始地址和数据段起始地址的寄存器。当执行进程 A 的指令时,这些寄存器保存着进程 A 的信息。而当切换到进程 B 时,CPU 会更新这些寄存器的值,这样就能执行进程 B 的指令了。这个切换过程被称为进程切换(Process Switch)。
另外,你可能也会注意到,CPU 和内存之间的数据传输是通过总线进行的。总线主要有两类数据,一类是地址数据,即指示我想要访问内存中的哪个位置的数据。这类总线被称为地址总线(Address Bus)。另一类是真正的数据,即要传输的数据。这类总线被称为数据总线(Data Bus)。
地址总线的位数决定了能够访问的内存地址范围有多广。例如,如果地址总线只有两位,那么 CPU 就只能识别 00、01、10、11 这四个位置,超过这个范围就无法区分。地址总线位数越多,能够访问的位置就越多,CPU 能够管理的内存范围也就越广。例如,32位的地址总线可以寻址2的32次方(约为4GB)个内存位置。因此,32位的地址总线可以识别并访问的内存位置范围是从0到2的32次方减1。
需要注意的是,地址总线的位数与CPU的数据位数是不同的。CPU的数据位数决定了它一次能够处理的数据量,而地址总线的位数决定了它能够寻址的内存位置范围。
而数据总线的位数决定了每次能够传输多少个数据。例如,如果数据总线只有两位,那么 CPU 每次只能传输两位数据。如果要传输八位数据,就需要进行四次传输。数据总线位数越多,每次传输的数据量就越大,访问速度也就越快。
总结
计算机指令是CPU能够理解的语言,也称为机器语言。不同的CPU支持不同的指令集,对应不同的汇编语言和机器码。MIPS指令集是一种常用的指令集。
CPU执行指令的过程包括指令的解码和执行。CPU内部由控制单元、算术逻辑单元和数据单元组成,它们协同工作来执行指令。控制单元负责指令的解码和操作信号的生成,算术逻辑单元负责执行计算操作,数据单元用于存储数据和计算结果。
CPU和内存之间的数据传输通过地址总线和数据总线进行。地址总线决定了CPU能够寻址的内存位置范围,数据总线决定了每次能够传输的数据量。