本文主要是针对非计算机行业或是计算机小白,主要介绍了计算机是如何工作的,为什么写一下代码,计算机就可以实现我们想要实现的功能。

CPU如何运作
CPU内部的算术逻辑单元(Arithmetic and Logic Unit,ALU)是处理器最核心的部件,相当于CPU的大脑。理解了ALU的工作流程基本上也就理解了计算机的工作流程。ALU由算术单元和逻辑单元组成,算术单元主要负责数学运算,如加、减、乘等;逻辑单元主要负责逻辑运算,如与、或、非等。ALU只是纯粹的运算单元,要想完成一个指令运行的整个流程,还需要控制单元的协助。控制单元根据程序计数器PC中的地址,会不断地从内存RAM中取指令,放到指令寄存器中并进行译码,将指令中的操作码和操作数分别送到ALU,执行相应的运算。

示例
以两个整数A、B相加的指令为例,控制单元通过指令译码电路会将该指令分解为操作码和操作数,再根据操作数地址从内存RAM中加载(Load)数据A和B,传送到ALU的输入端,然后将操作运算类型(操作码)即加法也告诉ALU。ALU有了输入数据和操作类型,就可以直接进行相应的运算了,并输出运算结果。为了效率考虑,运算结果一般会先保存到寄存器中,然后由控制单元将该数据从寄存器存储(Store)到内存RAM中。执行到这一步,一个完整的加法指令执行流程结束,控制单元会继续取下一条指令,然后翻译指令、运行指令,周而复始。CPU内部有个程序计数器(Program Counter,PC),系统上电后默认初始化为0,控制单元会根据这个PC寄存器中的地址到对应的内存RAM中取指令,然后PC寄存器中的地址自动加一。通过这种操作,控制单元就可以不停地从内存RAM中取指令、翻译指令、运行指令,程序就可以源源不断地运行下去了。

早期CPU的工作频率和内存RAM相比,差距不是一般的大。控制单元从RAM中加载数据到CPU,或者将CPU内部的数据存储到RAM中,一般要经过多个时钟读写周期才能完成:找地址、取数据、配置、输出数据等。运算速度再快的CPU,也只能傻傻地干等几个时钟周期,等数据传输成功后才可以接着执行下面的指令。内存带宽的瓶颈会拖CPU的后腿,影响CPU的性能。为了提高性能,防止RAM拖后腿,CPU一般都会在内部配置一些寄存器,用来保存CPU在计算过程中的各种临时结果和状态值。ALU在运算过程中,当运算结果为0、为负、数据溢出时,也会有一些Flags标志位输出,这些标志位对控制单元特别有用,如一些条件跳转指令,其实就是根据运算结果的这些标志位进行跳转的。CPU跳转指令的实现其实也很简单:根据ALU的运算结果和输出的Flags标志位,直接修改PC寄存器的地址即可,控制单元会自动到PC指针指向的内存地址取指令、翻译指令和运行指令。跳转指令的实现,改变了程序按顺序逐步执行的线性结构,可以让程序执行更加灵活,可以实现更加复杂的程序逻辑,如程序的分支结构、循环结构等。

CPU所支持的加、减、乘、与、或、非、跳转、Load/Store、IN/OUT等基本指令,一般称为指令集。任何复杂的运算都可以分解为指令集中的基本指令。在软件层面上,我们可以把这些有限的基本指令进行不同的组合,实现各种不同的功能:播放视频、播放音乐、图片显示、网络传输。我们也可以基于这些基本指令实现新的指令,以除法运算为例,如果CPU在硬件电路上不支持除法指令,我们就可以基于CPU指令集中的原生加、减、移位等指令来模拟除法的实现,生成新的除法指令。

这种由基本指令组成的不同组合,我们称为程序。为了编程方便,我们给每个二进制指令起一个别名,使用一个助记符表示,这些助记符就是汇编语言,由助记符组成的指令序列就是汇编程序。汇编语言的可读性虽然比二进制的机器指令好了很多,但是当汇编程序很大、程序的逻辑很复杂时,维护也会变得无比艰难,这时候高级语言就开始问世了,如C、C++、Java等。高级语言的读写更符合人类习惯,更适合开发和阅读,编写好的高级语言程序通过编译器,就可以翻译成CPU所能识别的二进制机器指令。