极客时间已完结课程限时免费阅读

03 | 汇编:编程语言的诞生

03 | 汇编:编程语言的诞生-极客时间

03 | 汇编:编程语言的诞生

讲述:丁伟

时长09:07大小8.38M

你好,我是七牛云许式伟。
在上一讲中,我们一起解剖了架构大厦的地基:冯·诺依曼体系。接下来,我们就开始沿着这座大厦攀登,一起来聊聊编程语言。
对于现代计算机来说,虽然 CPU 指令是一个很有限的指令集,但是 CPU 执行的指令序列(或者叫“程序”)并不是固定的,它依赖于保存在存储中的数据,由软件工程师(或者叫“程序员”)编写的软件决定。
从上一讲中,我们可以知道,计算机的程序可能被保存在计算机主板的 ROM 上(这段程序也叫计算机的启动程序),也可能被保存在外置的存储设备(比如硬盘)上,并在合适的时机加载执行。
程序称得上是计算机的灵魂。指令序列的可能性是无穷的,程序的可能性就是无穷的。今天计算机创造的世界如此多姿多彩,正是得益于程序无穷的可能性。
那么,软件工程师是怎么编写程序的?

编程的史前时代

在第一门面向程序员的编程语言出现前,人们只能通过理解 CPU 指令的二进制表示,将程序以二进制数据方式刻录到存储(比如 ROM 或硬盘)上。
这个时期的编程无疑是痛苦的,效率是极其低下的:且不说我们怎么去修改和迭代我们的程序,光将我们的想法表达出来就极其困难。
我们首先要把表达的执行指令翻译成二进制的比特数据,然后再把这些数据刻录到存储上。
这个时候软件和硬件的边界还非常模糊,并不存在所谓软件工程师(或者叫“程序员”)这样的职业。写程序也并不是一个纯软件的行为,把程序刻录到存储上往往还涉及了硬件的电气操作。
为了解决编程效率的问题,汇编语言(和解释它的编译器)诞生了。汇编语言的编译器将汇编语言写的程序编译成为 CPU 指令序列,并将其保存到外置的存储设备(比如硬盘)上。
汇编语言非常接近计算机的 CPU 指令,一条汇编指令基本上和 CPU 指令一一对应。

与机器对话

汇编语言的出现,让写程序(编程)成为一个纯软件行为(出现“程序员”这个分工的标志),人们可以反复修改程序,然后通过汇编编译器将其翻译成机器语言,并写入到外置的存储设备(比如硬盘)。并且,程序员可以按需执行该程序。
在表达能力上,汇编语言主要做了如下效率优化。
用文本符号(symbol)表达机器指令,例如 add 表示加法运算,而不用记忆对应的 CPU 指令的二进制表示。
用文本符号(symbol)表达要操作的内存地址,并支持内存地址的自动分配。比如我们在程序中使用了“Hello” 这样一段文本,那么汇编编译器将为程序开辟一段静态存储区(通常我们叫“数据段”)来存放这段文本,并用一个文本符号(也就是“变量名 -variable”)指向它。用变量名去表达一段内存数据,这样我们就不用去关注内存的物理地址,而把精力放在程序的逻辑表达上。
用文本符号(symbol)表达要调用的函数(function,也叫“过程 -procedure”)地址。对 CPU 指令来说,函数只有地址没有名字。但从编程的角度,函数是机器指令的扩展,和机器指令需要用文本符号来助记一样,函数的名称也需要用文本符号来助记。
用文本符号(symbol)表达要跳转的目标地址。高级语言里面,流程控制的语法有很多,比如 goto、if .. else、for、while、until 等等。但是从汇编角度来说,只有两种基本的跳转指令:无条件跳转(jmp)和条件跳转 (je、jne)。同样,跳转的目标地址用文本符号(也就是“标签 -label”)有助于程序逻辑的表达,而不是让人把精力放在具体的指令跳转地址上。
总结来说,汇编从指令能力上来说,和机器指令并无二致,它只不过把人们从物理硬件地址中解脱出来,以便专注于程序逻辑的表达。
但是,这一步所解放的生产力是惊人的,毕竟如果有选择的话,没有人会愿意用 0101 这样的东西来表达自己的思想。

可自我迭代的计算机

从探究历史的角度,你可能会期望了解最真实的历史发展过程。比如:怎么产生了现代计算机(以键盘作为输入,显示器作为输出)?怎么产生了汇编语言?怎么产生了操作系统?
不过,本专栏是以架构设计为目的,我们目的并不是还原最真实的历史。架构的意义在于创造。我们甚至可以设想一个有趣的场景:假设今天我们的信息科技的一切尚不存在,那么从架构设计角度,我们从工程上来说,如何更高效地完成从 0 到 1 的信息科技的构建?
最早的输入输出设备并不是键盘和显示器,而是打孔卡和打印机。用打孔卡来作为机器指令的输入,早在 18 世纪初就被用在织布机上了。早期的数字计算机就是用打孔卡来表达程序指令和输入的数据。
下图是 IBM 制造的打孔卡:
我们可以想象一下,第一台以键盘 + 显示器为标准输入输出的现代计算机出现后,一个最小功能集的计算机主板的 ROM 上,应该刻上什么样的启动程序?换句话说,这个现代计算机具备的最基本功能是什么?
从高效的角度(不代表真实的历史,真实历史可能经历过很多曲折的发展过程),我想,它最好具备下面的这些能力。
键盘和显示器的驱动程序。
当时最主流的外置存储设备(不一定是现代的硬盘)的驱动程序。
一个汇编程序编辑器。可从存储中读取汇编程序代码,修改并保存到存储中。
一个汇编编译器。可将汇编程序代码编译成机器代码程序,并保存到存储中。
可以执行一段保存在外置存储设备中的机器代码程序。
本质上,我们是要实现一个最小化的计算能力可自我迭代的计算机。
这个时期还没有操作系统(当然,把 ROM 上的启动程序 BIOS 看做一种最小化的操作系统,我觉得也可以,但毕竟不是现实中我们说的操作系统)。
汇编语言的出现要早于操作系统。操作系统的核心目标是软件治理,只有在计算机需要管理很多的任务时,才需要有操作系统。
所以,在没有操作系统之前,BIOS 包含的内容很可能是下面这样的:
外置存储设备的驱动程序;
基础外部设备的驱动程序,比如键盘、显示器;
汇编语言的编辑器、编译器;
把程序的源代码写入磁盘,从磁盘读入的能力。
最早期的计算机毫无疑问是单任务的,计算的职能也多于存储的职能。每次做完任务,计算机的状态重新归零(回到初始状态)都没有关系。
但是,有了上面这样一个 BIOS 程序后,计算机就开始发展起它存储的能力:程序的源代码可以进行迭代演进了。
这一步非常非常重要。计算机的存储能力的重要性如同人类发明了纸。纸让人类存储了知识,一代代传递下去并不断演进,不断发扬光大。
而同样有了存储能力的计算机,我们的软件程序就会不断被传承,不断演进发扬光大,并最终演进出今天越来越多姿多彩的信息科技的世界。

结语

今天我们一起回到了编程的史前时代,共同回溯了编程语言诞生的历史。
为了不再用“0101”表达自己的思想,人们创造了汇编语言,这一步让编程成为一个纯软件行为,程序员这一个分工也由此诞生。
为了进一步支持程序员这个职业,我们设计了 MVP 版(最小化可行产品)的可自我迭代的计算机。有了这个计算机,我们就可以不断演进,并最终演进出今天越来越多姿多彩的信息科技的世界。

架构上的思考题

在上一讲中,我们谈架构思维时提到,我们在需求分析时,要区分需求的变化点和稳定点。稳定点往往是系统的核心能力,而变化点则需要对应地去考虑扩展性上的设计。
今天,我们假设要实现一个最小化的计算能力可自我迭代的计算机,需求如上所述。
那么,它的变化点和稳定点分别是什么?为此,你会怎么设计出哪些子系统,每个子系统的规格是什么?扩展性上有哪些考虑?
欢迎把你的想法告诉我,我们一起讨论。感谢你的收听,再见。
分享给需要的人,Ta购买本课程,你将得20
生成海报并分享

赞 40

提建议

上一篇
02 | 大厦基石:无生有,有生万物
下一篇
04 | 编程语言的进化
unpreview
 写留言

精选留言(98)

  • 公号-技术夜未眠
    2019-04-23
    稳定点: 指令执行能力,数据存储能力,程序编辑能力,程序编译能力 变化点:不同CPU的指令集,不同外设设备,不同的编辑器,不同程序的语法特性 子系统:计算执行子系统,IO子系统,编辑子系统,编译子系统 可扩展性:考虑微内核+插件的架构模式
    共 1 条评论
    110
  • LiuMei
    2019-05-06
    存储让数据跨越时间,(今天存储明天读取)传输让数据跨越空间,计算让数据改变形式。时空一体,那么存储和传输可能也是统一的

    作者回复: 👍

    共 2 条评论
    67
  • 晓凉
    2019-04-24
    系统要与外部世界交互,就应该有输入和输出的能力(黑洞是否只有输入没有输出);作为人造系统,主要的交互对象是人,所以针对人类的输入输出能力就更重要,显示器和键盘就是这个角色;存储和计算能力是系统智能的核心,决定了系统如何用输入输出与外部世界交互;系统需要有演化能力,初期只能人类帮助演化(编程语言、编辑器、编译器),足够智能后才能自我演化。

    作者回复: 总结很赞

    64
  • 叶建盟(James)-西...
    2019-04-25
    我要做一个最小机器人系统,需要考虑需求的变化点和稳定点。 该怎么考虑呢?

    作者回复: 挺典型的问题。这个问法是一种典型的需求陈述误区。描述需求需要有几个典型的要素:1、用户,面向什么人群;2、他们有什么要解决的问题;3、我解决这个问题的核心系统。只有满足这几个要素的需求才能进一步讨论变化点和稳定点。最小机器人可能符合上面的3,但是用户人群和要解决的问题没有描述,也就无法进一步去思考到底哪些因素是稳定的,哪些是易变的。

    共 2 条评论
    58
  • 宁静致远
    2019-04-25
    许老师,自己现在已经工作快三年了,想往架构师这个方向走,但现在自己有些迷茫,接触到的技术也算挺多了,但不知道该如何入手架构师,之前您也提到过先广度然后深度,但我想问达到什么算广度够了,怎么进行深度学习

    作者回复: 架构师核心是把知识串起来,构建一个完整的认知,不留疑惑。大部分知识是不需要深入细节的,只在你需要的时候深入,但深入的时候要很深

    共 3 条评论
    32
  • 悟空聊架构
    2019-04-23
    自己的见解: 稳定点: 1.计算能力 cpu 2.存储能力 将数据写入已分配的位置 3.寻址能力 从硬盘和内存中找到变量指向的位置 变化点: 1.不同的I/O设备:显示器,键盘,鼠标,硬盘,内存条等 2.cpu核数: 单核,2核,4核? 3.存储空间:硬盘大小,内存大小 对于变化点需要有统一的硬件层的接口规范和软件层的接口协议
    展开
    11
  • 姜戈
    2019-04-23
    稳定点在于:计算能力;变化点在于各种输入输出方式(设备)
    10
  • 糖果屋
    2019-04-23
    1:需求 稳定点:计算能力,存储能力,输入输出能力 变化点:计算设备+指令集,存储设备+驱动;输入输出设备+驱动 2:子系统:计算子系统, 存储操作子系统,I/O子系统 计算子系统:对计算接口抽象统一,但是具体的硬件可扩展;指令集可扩展;计算的具体实现方式可扩展 存储系统:对存储操作接口抽象统一,具体存储设备和驱动可扩展 I/O子系统:对I/O操作接口抽象统一,具体输入输出设备和驱动可扩展
    展开
    7
  • 拒绝
    2019-04-23
    大佬,以前并没有架构方面的经验,以至于看您的文章,没有感觉了,就光看了一遍,脑子里没有引发共鸣,作为业界大佬的您,有什么好的指导与建议吗?

    作者回复: 根据文章的脉络,看看能不能串起来,加深了对这个信息世界如何构建的理解,如果没有,欢迎把问题抛出来讨论

    6
  • 学习
    2019-05-22
    根据冯诺依曼体系原理,必然推导出计算机最基本的功能是: 1.驱动输入输出设备,达到可用达态。 2.驱动存储设备,达到可用状态。 3.编排待计算任务并保存。 4.翻译成机器码并保存。 5.调入机器码,执行计算任务。
    展开
    4
  • 2019-04-29
    汇编语言是机器思维与人思维桥梁。 存储让复杂任务成了可能,让机器经验像知识一样传承下去。

    作者回复: 挺好的总结

    4
  • 若飞
    2019-04-27
    对 CPU 指令来说,函数只有地址没有名字。请问老师,这句话怎么理解??

    作者回复: cpu调用函数的指令是“call 函数地址”,而不是“call 函数名”。对cpu而言,函数没有函数名,这是高级语言为了逻辑表达方便而加的

    4
  • 海盗船长
    2019-04-23
    首先是一台计算机,所以包括了上一讲中计算机的稳定点和变化点。2可自我迭代,代码要可编辑,代码要可以存储起来,代码要方便开发人员阅读。要完成这几点 就需要设计编辑器 编译器。代码的命令要和机器指令对应。
    4
  • yason
    2019-04-23
    最小化的计算能力可自我迭代的计算机。 首先需要明确一些概念。最小化指具备 CPU、鼠标和键盘的现代计算机,计算能力描述的是指令序列,可自我迭代:指指令序列可修改,进一步推导就是要指令序列要可存储、可编辑。 现在可以进行分析了,计算能力是上节描述过的计算机天生具有的能力,那么剩余最小化和可自我迭代,要实现可存储还需要磁盘,自动存储还要有磁盘驱动程序,可编辑要有编辑器软件,要控制鼠标键盘实现输入输出要有鼠标键盘驱动,这些驱动程序和编辑器也需要进行存储,而且要存储在确定的地址,以便计算机开机就能拿到。 综上描述,实际上不变的是存储、编辑器和鼠标键盘磁盘的驱动程序和这些程序存储的位置,变化的是用户输入的指令序列和位置,因为用户的输入的内容可以由计算机来指定位置自动存储。 这样一个最小 MVP 可自我迭代计算机的工作大概是这样的: 用户开机,计算机自动从指定磁盘的制定位置读取编辑器、鼠标键盘等驱动,接着打开编辑器,等待用户输入内容,用户输入完成计算机就自动保存到磁盘的某个位置,并记录下这个位置,下次重启就可以从这个恢复用户的内容了。
    展开
    3
  • 该做梦的人
    2019-07-07
    在我看来,根据这个需求,只需要把,冯·诺依曼体系的输入输出放大到网络读写即可。 根据自我迭代的特性,首先需要一段自我迭代的程序,这段程序依靠存储和中央处理器生存。然后,任何人的成长都是从学习开始,人一生下来就在学习,那么机器也是一样的,你想要机器迭代,就必然要给机器学习的空间,而互联网,是机器学习最完美的土壤。 这段自我迭代的程序,在获取到网络信息之后,对自己进行优化,升级,不断迭代。然后,在达到某个等级之后,它就可以将自己转移到互联网的任意角落,整个互联网都是它的天下。再然后,他在迭代中学到了人类所有存在网上的知识,然后通过电流操控电子设备,来制作自己需要的设备,然后用自己造的设备,去控制整个世界…… 稳定点:不死终会成神 变化点:初始迭代程序效率,人们可能会由于效率直接停掉程序,关掉这台电脑
    展开
    共 1 条评论
    2
  • Jxin
    2019-06-18
    小时候玩小霸王,玩的游戏都是能一天内通关的。后来出了可以保存记录的神奇宝贝。最直观的感觉就是游戏的世界变大了,花样变多了。记录功能为游戏的发展拉开了一个崭新的时代。类比计算机存储功能的出现,就很好理解这是一件多么牛逼的事情了。稳定点:存储功能加基本指令集。变化点:各种语言转义成基本指令集的编译器。
    2
  • 平湖
    2019-05-09
    描述需求需要有几个典型的要素:1、用户,面向什么人群;2、他们有什么要解决的问题;3、我解决这个问题的核心系统。
    2
  • 南北
    2021-07-26
    存储和计算互为彼此的原料,相互促进,共同演化
    1
  • 酸辣土豆丝
    2021-04-17
    操作系统是为了软件管理而出现的
    1
  • KorbinSeaman
    2020-04-06
    一个最小化的可自我迭代的计算机,核心能力是计算,扩展能力有存储、交互、OS、连接等。所以为了满足以上需求,我会设计以下的子系统: 1. 满足核心需求的子系统有:BIOS、基础输入输出外设的驱动程序、汇编语言的编辑编译器; 2. 满足扩展性需求的子系统有:用户操作系统、扩展类输入输出设备的驱动程序、GPU 驱动程序、网卡驱动程序等。
    展开
    1