1.计算机只会做简单的指令
计算机不会思考,不会举一反三。它只认得一件东西——指令,而且是极其简单、极其死板的指令。
让计算机计算3+2,就是把 2 放到某个存储单元,把3放到另一个存储单元里,然后执行一次加法指令,把结果放到第三个存储单元,再复杂的运算,都会分解为最基础的加法指令。
CPU把每一条指令的执行,拆成了取指、译码、执行、访存、写回五个固定步骤,每个步骤由专门的硬件单元负责,像工厂流水线一样重叠推进。第一条指令刚走到“执行”环节,第二条已经在“译码”,第三条已经完成“取指”,理想状态下每个时钟周期就能输出一条完整指令的结果。如图1所示。

图 1 CPU执行指令的过程
举个例子:计算1+2+3+4,计算机需要完成四次数据搬运、三次加法运算,一步不差地依次执行所有指令。但恰恰就是这样一套机械的操作,依靠海量简单指令有序拼接,最终呈现出语音识别、图像生成这类看似拥有思考能力的效果。究其本质,它们全部由底层无数次 “搬数据、做运算、存结果” 的固定步骤堆叠而成。
2.计算机编程语言的本质
编程语言本质是人类为了和只懂0和1的计算机对话,一层层搭起来的翻译阶梯。
第一层:机器语言
计算机从诞生起,就只会识别两种状态:开和关,对应数字里的0和1。所有能被CPU直接执行的指令,全是由0和1排列组合出来的二进制序列,这就是机器语言。
它没有多余的修饰,每一位二进制代码都直接对应硬件上的电信号,因此运行速度极快。代价是程序员必须记忆数量庞大的二进制指令,哪怕写错其中一个二进制位,都可能造成整个程序崩溃。
第二层:汇编语言
为了提高编程效率和机器代码的易读性,工程师们把常用的二进制指令用对应的英文单词表示。
如把移动数据的二进制指令用MOV表示,把加法二进制指令用ADD表示,MOV和ADD就是对应二进制指令的助记符。如图2所示。

图 2 用助记符表示二进制指令
用助记符编写的代码就是汇编代码,该语言也称为汇编语言。汇编语言没有改变机器指令的核心逻辑,只是用人类能看懂的助记符,来表示二进制指令。如图3所示。

图 3 用助记符编写的汇编代码
但计算机依然不认识这些英文单词,这就需要一个专门的翻译官——汇编器,把写好的汇编代码,完整转换成机器能直接执行的二进制序列。这是人类第一次在人的思维和机器的逻辑之间,搭起了一座简易的桥梁。
第三层:高级语言
再往后走,人们已经不满足汇编语言了。希望直接用贴近自然语言的方式,描述自己想要实现的功能。
于是C、Java、Python这类高级语言应运而生。 程序员可以直接写出“如果a比b大,就打印a更大”这样逻辑清晰的代码,几乎和日常的英文表达没有太大区别。这时候程序员完全不需要关心底层硬件的细节,只需要专注于描述自己的需求。
这些高级语言编写的代码想要被计算机执行,依然要经过编译器或者解释器的处理,先转换成汇编,再最终翻译成机器代码,送到CPU里运行。
所有语言的本质,都是翻译与抽象
从机器语言到汇编,再到各式各样的高级语言,编程语言的发展史,并不是让计算机本身变得更聪明的过程,而是一部持续降低人类表达成本的历史。
每向上封装一层,就是做一次抽象:把底层繁琐细碎的硬件细节隐藏起来,降低程序员的认知负担,更容易编排指令。
每做一次抽象,就必然配套一次翻译:把人类能轻松理解的表达,一层层向下转换,最终变成计算机能识别的机器代码。
就像去餐厅吃饭,只需要用中文说出你想吃的菜,不需要去后厨亲自生火、配菜、翻炒。中间的服务员、厨师,就是这套体系里的翻译官。
编程语言把用人类思维指挥计算机干活这件事,从极少数技术人员的专利,变成了今天无数普通人都能掌握的技能。
3.关于程序
打开手机里任意一个 App,或是电脑上运行的软件,表面上看是图标、界面、流畅的交互反馈;但往底层追问,它们究竟是什么?
程序是什么?一句话就可以概括:一套有序、有边界、可重复执行的指令集合。别看它简短,程序最底层、最重要的三个特点,全都藏在这里面。如图4所示。

图 4 程序的定义
我们先看第一个关键词:有序。指令可不是随便堆在一起的,它有严格的先后依赖关系。以生活中的炒菜为例,流程是固定的:先备菜,再开火倒油,最后下锅炒制。顺序颠倒,事情就做不成。程序也是同理,每一条指令都被安排在确定的时序上,一步一步依次执行,顺序错了,整个逻辑就跑偏了。
第二个关键词:有边界。程序有清清楚楚的开始,也有清清楚楚的结束。它从入口出发,顺着预先设计好的路线往前走,做完事情就从出口退出。正常它不会一直跑个不停;一旦停不下来,多半就是死循环,属于程序 Bug。有边界,说的就是它是一件完整的事,从启动到收尾,有始有终。
第三个关键词:可重复执行。同一套指令,你让它跑一万遍,只要输入不变,出来的结果就一模一样。同样的事情交给人去做,重复一百次,难免心烦走神、出现差错。机器没有情绪,不知疲惫,程序跑多少次,都会按指令执行,不会出现差错。
而支撑这一切的基石,就是指令。程序的底层,终究由一条条简单指令拼接而成。一款 App 上几十个、上百个功能,拆解到底,就是成千上万条基础指令排队依次执行。
一句话总结:程序是人下达给计算机、用以自动完成任务的操作规程,也就是一套有序、有边界、可重复执行的指令集合。
这,就是程序最本真的样子。
4.IPO模型
前面我们知道:程序本质是有序、有边界、可重复执行的指令集合。这些指令在工作的时候,在宏观上会遵循一个最简单、最通用的工作范式——IPO 模型。
IPO 是三个英文单词的缩写:Input(输入)、Process(处理)、Output(输出)。
它描述了几乎所有计算机程序的标准工作流程:
接收输入数据 → 按照预定指令进行加工处理 → 产生输出结果。如图5所示。

图 5 程序IPO模型
这是理解程序运行逻辑非常核心的模型,不管是最简单的两数相加,还是复杂的 AI 识图,底层都逃不开 IPO。
Input 输入
输入,就是程序拿到的原始数据,是整个流程的原料。
输入来源非常多:可以是键盘手动录入的数字、文本;可以是文件里读取的数据(如导入的 Excel 表格);可以是传感器采集的信号;也可以是别的程序传递过来的参数。
记住,程序本身不会凭空产生数据,没有输入,后续的处理过程就没有对象。输入的数据有确定格式、范围,程序只能识别设计者约定好的数据,不合规的数据就会造成处理异常。
Process 处理
处理,就是程序里面一堆有序指令开始执行的阶段,也就是我们前面讲的:搬运数据、运算、判断、分支、循环。
程序拿到输入之后,按照预先写好的逻辑对数据加工:做加减乘除计算、判断分数是否合格、拼接字符串、排序、过滤数据、转换格式。
这里要记住:计算机本身不会自己想出新规则,处理的逻辑完全是人提前写死在程序里的指令。它只会机械地按照流程,对输入的数据做固定操作。
Output 输出
输出,是处理完成之后,程序向外交付的结果。
输出形式多种多样:页面以表格方式展示处理后的记录、弹窗展示计算结果、导出 Excel 文件、打印文字、在屏幕绘制图形、向后台数据库写入数据等。
输出是给人或者其他程序看、用的结果。一个程序如果只有输入和处理,没有输出,人们永远不知道它计算出了什么,这个程序就失去了意义。
IPO 完整串联例子
Input(输入):用户在输入框里输入两个数字,比如 5 和 3
Process(处理):程序执行预先写好的加法指令:5 + 3
Output(输出):屏幕上显示计算结果:8
这个求和程序本身,就是一套有序、有边界、可重复执行的指令集合。只要输入不变,不管运行多少次,结果永远是 8。
一句话总结 IPO 模型:程序从外界获取输入数据,按照预设指令完成加工处理,最后返回输出结果,输入—处理—输出,构成计算机解决问题的标准范式。