简要介绍编程实践的历史演变。
在计算的早期,硬件很昂贵,而程序员则很便宜。 实际上,程序员是如此廉价,以至于他们甚至都没有被称为“程序员”,实际上通常是称之为数学家或电气工程师。 实际上早期的计算机被用来快速解决复杂的数学问题,因此数学家很自然地适合“编程”工作。
什么是程序?
首先,一点背景知识。 计算机本身不能做任何事情,所以它们需要程序来驱动它们的行为。 程序可以被认为是非常详细的配方,它接受一个输入并产生一个输出。 配方中的步骤由操作数据的指令组成。 虽然这听起来很复杂,但你可能知道这句话是怎么回事:
代码语言:javascript复制1 2 = 3
加号是“指令”,而数字1和2是数据。 从数学上讲,等号表示等式的两边都是“等价的”,但是大多数计算机语言使用等于的变体表示“赋值”。 如果计算机正在执行该语句,它将把加法的结果(“ 3”)存储在内存中的某个位置。
计算机知道如何对数字进行数学运算以及如何在计算机的内存层次结构中移动数据。 除了内存通常有两种不同的说法外,我将不做过多介绍:快/小和慢/大。 CPU寄存器非常快,非常小并且充当暂存器。 主存储器通常很大,并且不及寄存器存储器快。 CPU将它们正在使用的数据从主存储器中重排到寄存器中,然后在程序执行时再次返回。
汇编程序
电脑很贵,人很便宜。 程序员花了无尽的时间将手写的数学运算转换为计算机可执行的计算机指令。 最早的计算机具有糟糕的用户界面,其中一些仅由前面板上的拨动开关组成。 这些开关在单个“字”存储器中表示1和0。 程序员将配置一个单词,指示其存储位置,然后将该单词提交到内存中。 这既费时又容易出错。
最终,一名电气工程师认为自己的时间并不便宜,并编写了一个程序,输入内容以“食谱”的形式表达,人们可以阅读该术语,并输出计算机可读版本。 这是第一个“汇编程序”,引起很大争议。 拥有昂贵机器的人不想浪费时间在人们已经在做的任务上; 尽管缓慢且存在错误。 随着时间的流逝,人们开始意识到汇编程序相对于手工汇编程序的速度和准确性,并且计算机完成的“实际工作”数量也增加了。
虽然汇编程序从将位模式切换到机器的前面板是一大进步,但它们仍然非常专业。 上面的加法示例可能看起来像这样:
代码语言:javascript复制 01 MOV R0, 1
02 MOV R1, 2
03 ADD R0, R1, R2
04 MOV 64, R0
05 STO R2, R0
每一行都是一条计算机指令,以指令的简写名称开始,然后是指令所处理的数据。这个小程序首先将值1“移动”到一个名为R0的寄存器中,然后将值2“移动”到寄存器R1中。第03行添加寄存器R0和R1的内容,并将结果值存储到寄存器R2中。最后,第04和05行标识了结果应该存储在主存中的哪个位置(地址64)。管理数据存储在内存中的位置是编写计算机程序最耗时、最容易出错的部分之一。
编译器
汇编要比手工编写计算机指令好得多; 然而,早期的程序员渴望编写程序,就像他们习惯于编写数学公式一样。 这推动了高级编译语言的发展,其中一些是历史脚注,另一些至今仍在使用。 ALGO就是这样的一个脚注,而真正的问题今天仍然可以用 Fortran 和 C 等语言来解决。
这些“高级”语言的引入使程序员可以用更简单的术语编写程序。 在 c 语言中,我们的加法汇编程序是这样写的:
代码语言:javascript复制 int x;
x = 1 2;
第一条语句描述程序将使用的一块内存。 在这种情况下,内存应为整数大小,名称为x 。第二条语句为加法符,尽管写为“向后”。 AC程序员将读为“ X被分配了1加2的结果”。 请注意,程序员无需说出将x放在内存中的位置,因为编译器会处理该问题。
一种称为“编译器”的新型程序,会将用高级语言编写的程序转换为汇编语言版本,然后通过汇编程序运行该程序,以生成该程序的机器可读版本。 程序的这种组成通常称为“工具链”,其中一个程序的输出直接发送到另一个程序的输入。
与汇编语言程序相比,编译语言的巨大优势是可以从一种计算机模型或品牌移植到另一种计算机模型或品牌。 在计算的早期,IBM,Digital Equipment Corporation,Texas Instruments,UNIVAC,Hewlett Packard等公司涌现出各种类型的计算硬件。 除了需要插入电源之外,这些计算机都没有任何共同点。 内存和CPU体系结构差异很大,将程序从一台计算机转换到另一台计算机通常需要花费多年的时间。
使用高级语言,只需将编译器工具链移植到新平台。 一旦有了编译器,就可以在不做任何修改的情况下为新计算机重新编译高级语言程序。 高级语言的编译确实具有革命性。
1983年发布的IBM PC XT是降低硬件成本的早期例子。
对于程序员而言,生活变得非常美好。 表达他们想使用高级语言解决的问题要容易得多。 由于半导体的进步和集成芯片的发明,计算机硬件的成本急剧下降。 计算机变得越来越快,功能越来越强大,而且价格也越来越便宜。 在某个时刻,可能是在80年代后期,出现了反转,程序员变得比他们使用的硬件更昂贵。
解释器
随着时间的流逝,出现了一种新的编程模型,其中一种称为“解释器”的特殊程序可以读取程序,并将其转换为可立即执行的计算机指令。解释器将程序作为输入,并将其解释为中间形式,就像编译器一样。与编译器不同,解释器然后执行程序的中间形式。每次解释程序运行时都会发生这种情况,而编译过的程序仅被编译一次,并且计算机会按照“书面形式”执行机器指令。
附带说明一下,当人们说“解释的程序很慢”时,这是人们认为缺乏性能的主要原因。 现代计算机的功能是如此强大,以至于大多数人无法分辨编译程序和解释程序之间的区别。
解释程序(有时称为“脚本”)甚至更容易移植到不同的硬件平台。 由于脚本不包含任何特定于计算机的指令,因此程序的单个版本可以在许多不同的计算机上运行而无需更改。 当然,必须把口译员移植到新机器上才能使之成为可能。
perl是一种非常流行的解释语言。 我们添加问题的完整perl表达式为:
代码语言:javascript复制$x = 1 2
尽管外观和行为与C版本非常相似,但它缺少变量初始化语句。 还有其他区别(不在本文讨论范围之内),但是您可以看到我们可以编写一个计算机程序,该程序非常接近数学家用铅笔和纸手写的程序。
虚拟机
编程模型中最新的热潮是虚拟机,通常缩写为VM。 虚拟机有两种。 系统虚拟机和进程虚拟机。 两种类型的VM都提供了与“真实”计算硬件的抽象级别,尽管它们具有不同的范围。 系统虚拟机是可以替代物理硬件的软件,而过程虚拟机则设计为以独立于系统的方式执行程序。 因此,在这种情况下,进程虚拟机(以下简称虚拟机)在范围上与解释器相似,因为在虚拟机执行程序之前,先将程序编译为中间形式。
解释器和虚拟机之间的主要区别在于,虚拟机实现了通过其虚拟指令集访问的理想化CPU。 这种抽象使编写前端语言工具成为可能,这些工具可以编译用不同语言编写的程序并以虚拟机为目标。 可能最流行和最著名的虚拟机是Java虚拟机(JVM)。 JVM最初仅在1990年代才用于Java编程语言,但现在托管了许多流行的计算机语言:Scala,Jython,JRuby,Clojure和Kotlin仅举几例。 还有其他例子可能不是常识。 我直到最近才了解到,我最喜欢的语言Python不是解释型语言,而是虚拟机上托管的语言 !
虚拟机延续了一种历史趋势,即减少程序员用支持其领域特定需求的语言表达问题所需的平台特定知识的数量。
结语
我希望您喜欢这篇关于软件中一些不太显眼的部分的入门文章。还有什么话题是你想让我接着深入研究的吗? 请在评论中告诉我。
本文最初发表在PyBites上 ,经许可后转载。