浅谈汇编器、编译器和解释器


浅谈汇编器、编译器和解释器

文章插图
 
简单介绍一下编程方式的历史演变 。
-- Erik O'shaughnessy(作者)
在计算机诞生不久的早期年代,硬件非常昂贵,而程序员比较廉价 。这些廉价程序员甚至都没有“程序员”这个头衔,并且常常是由数学家或者电气工程师来充当这个角色的 。早期的计算机被用来快速解决复杂的数学问题,所以数学家天然就适合“编程”工作 。
什么是程序?首先来看一点背景知识 。计算机自己是做不了任何事情的,它们的任何行为都需要程序来引导 。你可以把程序看成是非常精确的菜谱,这种菜谱读取一个输入,然后生成对应的输出 。菜谱里的各个步骤由操作数据的指令构成 。听上去有点儿复杂,不过你或许知道下面这个语句是什么意思:
1 + 2 = 3其中的加号是“指令”,而数字 1 和 2 是数据 。数学上的等号意味着等式两边的部分是“等价”的,不过在大部分编程语言中对变量使用等号是“赋值”的意思 。如果计算机执行上面这个语句,它会把这个加法的结果(也就是“3”)储存在内存中的某个地方 。
计算机知道如何使用数字进行数学运算,以及如何在内存结构中移动数据 。在这里就不对内存进行展开了,你只需要知道内存一般分为两大类:“速度快/空间小”和“速度慢/空间大” 。CPU 寄存器的读写速度非常快,但是空间非常小,相当于一个速记便签 。主存储器通常有很大的空间,但是读写速度就比寄存器差远了 。在程序运行的时候,CPU 不断将它所需要用到的数据从主存储器挪动到寄存器,然后再把结果放回到主存储器 。
汇编器【浅谈汇编器、编译器和解释器】当时的计算机很贵,而人力比较便宜 。程序员需要耗费很多时间把手写的数学表达式翻译成计算机可以执行的指令 。最初的计算机只有非常糟糕的用户界面,有些甚至只有前面板上的拨动开关 。这些开关就代表一个内存“单元”里的一个个 “0” 和 “1” 。程序员需要配置一个内存单元,选择好储存位置,然后把这个单元提交到内存里 。这是一个既耗时又容易出错的过程 。
浅谈汇编器、编译器和解释器

文章插图
程序员 Betty Jean Jennings (左) 和 Fran Bilas (右) 在操作
后来有一名 电气工程师 认为自己的时间很宝贵,就写了一个程序,能够把人们可以读懂的“菜谱”一样的输入转换成计算机可以读懂的版本 。这就是最初的“汇编器”,在当时引起了不小的争议 。这些昂贵机器的主人不希望把计算资源浪费在人们已经能做的任务上(虽然又慢又容易出错) 。不过随着时间的推移,人们逐渐发现使用汇编器在速度和准确性上都胜于人工编写机器语言,并且计算机完成的“实际工作量”增加了 。
尽管汇编器相比在机器面板上切换比特的状态已经是很大的进步了,这种编程方式仍然非常专业 。上面加法的例子在汇编语言中看起来差不多是这样的:
01 MOV R0, 102 MOV R1, 203 ADD R0, R1, R204 MOV 64, R005 STO R2, R0每一行都是一个计算机指令,前面是一个指令的简写,后面是指令所操作的数据 。这个小小的程序首先会将数值 1 “移动”到寄存器 R0,然后把 2 移动到寄存器 R1 。03 行把 R0 和 R1 两个寄存器里的数值相加,然后将结果储存在 R2 寄存器里 。最后,04 行和 05 行决定结果应该被放在主存储器里的什么位置(在这里是地址 64) 。管理内存中存储数据的位置是编程过程中最耗时也最容易出错的部分之一 。
编译器汇编器已经比手写计算机指令要好太多了,不过早期的程序员还是渴望能够按照他们所习惯的方式,像书写数学公式一样地去写程序 。这种需求推动了高级编译语言的发展,其中有一些已经成为历史,另一些如今还在使用 。比如 ALGO 就已经成为历史了,但是像 Fortran 和 C 这样的语言仍然在不断解决实际问题 。
浅谈汇编器、编译器和解释器

文章插图
ALGO 和 Fortran 编程语言的谱系树
这些“高级”语言使得程序员可以用更简单的方式编写程序 。在 C 语言中,我们的加法程序就变成了这样:
int x;x = 1 + 2;第一个语句描述了该程序将要使用的一块内存 。在这个例子中,这块内存应该占一个整数的大小,名字是 x 。第二个语句是加法,虽然是倒着写的 。一个 C 语言的程序员会说这是 “X 被赋值为 1 加 2 的结果” 。需要注意的是,程序员并不需要决定在内存的什么位置储存 x,这个任务交给编译器了 。


推荐阅读