假如你来发明编程语言
聪明的人类发现把简单的开关组合起来可以表达复杂的布尔逻辑,在此基础之上构建了 CPU。因此 CPU 只能简单地理解开关,用数字表达就是 0 和 1。
创世纪:聪明的笨蛋
CPU 相当原始,就像单细胞生物一样,只能把数据从一个地方搬到另一个地方、简单地进行加减运算,没有任何高难度动作。这些操作虽然看上去很简单很笨,但 CPU 有一个无与伦比的优势,那就是一个字:快,这是人类比不了的。CPU 出现后,人类开始拥有第二个大脑。
就是这样原始的一个物种开始支配起另一个叫做程序员的物种。
干活的是大爷
一般来说两个不同的物种要想交流,比如人和鸟,就会有两种方式:要不就是鸟说人话,让人听懂;要不就是人说鸟语,让鸟听懂;就看谁厉害了。
最开始 CPU 胜出,程序员开始说鸟语并认真感受 CPU 的支配地位。好让 CPU 大爷可以工作,感受一下最开始的程序员是怎么说鸟语的:
程序员按照 CPU 的旨意直接用 0 和 1 编写指令,你没有看错,这破玩意就是代码了,就是这么原生态,然后放到打孔纸带上输入给 CPU,CPU 开始工作。这时的程序可真的是看得见摸得着,就是有点浪费纸。
这时程序员必须站在 CPU 的角度来写代码,画风是这样的:
1101101010011010100100110010100111001000110111101011101101010010
乍一看你知道这是什么意思吗?你不知道,心想:'这是什么破玩意?',但 CPU 知道,心想'这就简直就是世界上最美的语言'。
天降大任
终于有一天程序员受够了说鸟语,好歹也是灵长类,叽叽喳喳说鸟语太没面子,你被委以重任:让程序员说人话。
你没有苦其心志劳其筋骨,而是仔细研究了一下 CPU,发现 CPU 执行的指令集来来回回就那么几个指令,比如加法指令、跳转指令等等。因此你把机器指令和对应的具体操作做了一个简单的映射,把机器指令映射到人类能看懂的单词,这样上面的 01 串就变成了:
sub $8, %rsp
mov $.LC0, %edi
call puts
mov $0, %eax
这样,程序员不必生硬地记住 1011.....,而是记住人类可以认识的 ADD SUB MUL DIV 等这样的单词即可。
汇编语言就这样诞生了,编程语言中首次出现了人类可以认识的东西。
这时程序员终于不用再'叽叽喳喳。。',而是升级为'阿巴阿巴。。',虽然人类认知'阿巴阿巴'这几个字,但这和人类的语言在形式上差别还是有点大。
细节 VS 抽象
尽管汇编语言已经有人类可以认识的单词,但汇编语言和机器语言一样都属于低级语言。
所谓低级语言是说你需要关心所有细节。
关心什么细节呢?我们说过,CPU 是非常原始的东西,只知道把数据从一个地方搬到另一个地方,简单的操作一下再从一个地方搬到另一地方。
因此,如果你想用低级语言来编程的话,你需要使用多个'把数据从一个地方搬到另一个地方,简单的操作一下再从一个地方搬到另一地方'这样的简单指令来实现诸如排序这样复杂的问题。
有的同学可能对此感触不深,这就好比,本来你想表达'去给我端杯水过来':
![示意图:高级抽象与底层实现的对比]
弥补差异
CPU 实在太简单了,简单到不能理解任何稍微抽象一点诸如'给我端杯水'这样的东西,但人类天生习惯抽象化的表达,人类和机器的差距有办法来弥补吗?
换句话说就是有没有一种办法可以自动把人类抽象的表达转为 CPU 可以理解的具体实现,这显然可以极大增强程序员的生产力,现在,这个问题需要你来解决。
套路,都是套路
思来想去你都不知道该怎么把人类的抽象自动转为 CPU 能理解的具体实现,就在要放弃的时候你又看了一眼 CPU 可以理解的一堆细节:
![示意图:CPU 指令执行流程]
电光火石之间灵光乍现,你发现了满满的套路,或者说模式。
大部分情况下 CPU 执行的指令平铺直叙的,就像这样:
![示意图:顺序执行指令]
这些都是告诉 CPU 完成某个特定动作,你给这些平铺直叙的指令起了个名字,姑且就叫陈述句吧,statement。
除此之外,你还发现了这样的套路,那就是需要根据某种特定状态决定走哪段指令,这个套路在人看来就是'如果。。。就。。。否则。。就。。。':


