电脑怎样执行编程语言[未完待续]

这个问题真的是很大,让我们自顶向下的解释

在顶层,程序员编写出来的都是源代码。源代码可以使用各种高级语言写成,例如 c/c++ c# java python 等等;也可以使用对应平台的低级语言写成,例如汇编。想必你已经了解其中的过程了。

到这一步为止,距离最终机器可以执行的指令还有一大步要走。

首先要面临的一个问题是:源代码都是以人类语言写成的。即便是能够和机器指令一对一翻译的汇编代码,依然是人类语言。计算机无法理解其中的含义,所以不可能执行。

所以我们需要将人类语言翻译为计算机语言。计算机能听懂的语言,就叫做机器语言,简称机器码。

在这里说几句题外话。

在计算机历史的上古时代,大概是上个世纪50年代之前。那时编译理论和形式语言还没有得到发展。几乎所有的程序都是直接由机器码写成的。比如由工程师直接将二进制机器码和数值编写在打孔卡上,通过读卡机读入计算机存储器,然后执行。

而打孔卡长这个样子:

(来自 wiki,80列标准 IBM 打孔卡,你能读出上面是什么意思吗?)

计算机的基本架构虽然经过了将近百年的发展,但是核心的模型倒是一直很稳定,都是存储程序模型。

首先将程序指令从外存(打孔卡,磁带,硬盘,软盘,光盘,闪存卡,网络等)读入内存,然后让处理器从内存按顺序取指执行,结果写回内存中。

在那个年代,人们对程序运行原理的理解是不存在什么障碍的。工程师怎么写,计算机就严格的按照指令执行。每一条指令对应一个步骤。最后的到结果。

在这种条件下,程序开发绝对是顶尖的职业,首先能够理解目标机的架构就需要相当的功夫了。其次还要按照机器的方式思考,写出正确无误的指令序列。

这样的开发过程无疑限制了计算机行业的发展。

同时,即便是擅长于按照机器方式思考的工程师,也认为机器指令太难记了。如你所见,在打孔卡上准确无误的写上指令真是头疼的要死。所以工程师们开发了一套助记符,用来指示对应的机器码,这样以来,程序的编写和 debug 就方便多了。到上世纪40年代末期,就已经有一批成熟的助记符体系了。

 

(ARM v7 汇编指令卡中的某一页)

关于助记符的话题,暂且搁置。

 

回到正题。为了将人类语言翻译成机器变成机器能够理解的语言,还需要进行翻译。就好像你不懂英语,英语可以翻译成汉语,这样你就能明白其中的含义。对于计算机来说,这个过程是一样的。不过计算机对于翻译有更高的要求。人类之间互相翻译语言,有一些微小的出入并不影响理解,计算机为了能够准确的得到结果,要求这个翻译的过程,必须保证“将一种语言翻译成涵义相同的等价的另一种语言”。

在早期,程序的规模还比较小,翻译的过程可以人工的进行。利用查表的方式,最终是可以得到等价的机器码序列。随着计算机科学的发展,程序规模膨胀的越来越快,人工翻译变的没有可行性。此时就有人提出,编写一套软件来进行这个翻译的过程。

一开始人们只用汇编语言进行程序开发。所以只需要将汇编语言翻译为机器语言就可以了。这是相当直截了当的过程,因为汇编语言的助记符和机器指令是一一对应的关系。所以只需要完成一个能够自动查表并转换的程序即可。很快,这样的程序就被发明了出来。我们称之为“汇编器”。

伴随着汇编器的发展,工程师又开始想要偷懒。他们认为,既然汇编器可以将汇编指令翻译成等价的机器码,那么在翻译之前一定也可以做一些预先处理的工作,将一个助记符转换为多个助记符组成的序列。这样以来,开发人员就可以使用较少的代码,写出较多的内容。同时将常用的一些程序结构编写成对应的助记符,在需要时就使用这个助记符,还可以帮助开发人员减少程序出错的可能。简直太好了。于是,人们又在汇编器中引入了宏指令。

所谓“宏(macro)”就是一套预先定义好的指令序列。每当汇编进行的时候,先预处理一次将宏等价的展开,然后再进行翻译。如此,源程序变的更加容易理解了。

 

宏的引入,催生了程序结构化表达。在今天的汇编语言当中,我们也可以像使用高级语言的 if else for while 语句一样,使用等价的结构语句。只不过,汇编中的结构语句都是宏实现的。

 

结构化表达给了一些计算机科学人员启发。能不能更进一步,使用完全结构化,脱离某个对应机器平台的形式化语言来描述一个源程序?于是,就有了高级语言及其编译器。

开发人员利用高级语言编写程序,然后利用对应的编译器生成中间代码,最后再将中间代码变成机器码。中间代码可以是等价的汇编代码,也可以是其它类型的代码例如 JVM 的字节码。最终处理中间代码的程序可以是一个对应平台的汇编器,也可以是一个解释器。在这里姑且隐去这些细节,将编译的最终产物都视为一系列可以被执行的二进制机器码。关于编译器的更多内容,在网上可以找到很多详细的资料。在这个话题下,编译器不是核心问题,我就不再深入讨论了。

 

至此,就得到了一个可以被执行的程序了。这个文件的内容是一系列二进制指令和数据组成的序列。它能被装入机器的内存,并且可以被处理器解码执行。

 

但是,为什么是二进制

 

说回来,计算机其实是长期使用的一个简称。严格的讲应该叫做“电子计算机”。但是计算机的形态并不限于电子式计算机。算盘,计算尺,对数计算表都可以算作广义上的计算机,同时在电子式计算机出现之前,它的还有一个机械式计算机的表亲。

(来自 Wiki 。 查尔斯·巴贝奇 的分析机。蒸汽动力驱动,采用十进制,其内存能够存储1000个50位的十进制数,相当于20.7 KB 的 SRAM 或 DDRAM。采用打孔纸带读入程序,具有类似汇编语言的助记符编程系统,是图灵完备的。很蒸汽朋克,嗯?)

可是我们并不认为算盘以及计算尺和现代计算机是同一个东西。最核心的区别在于,现代计算系统是可编程的。按照这个定义,上面的分析机也是现代电子是计算机的鼻祖。它身上的核心模型一直继承至今。

在分析机上,已经实现了 “ 存储程序计算机 ”。

这也就是现代计算系统的基本概念:

  1. 以运算单元为中心
  2. 采用存储程序原理
  3. 存储器是按地址访问的,线性的空间
  4. 控制流由程序的指令流产生
  5. 指令由操作码和操作数组成

这一概念所描述的计算模型具有以下的过程:将完整的程序装入存储器后,运算单元依照地址按顺序的从存储器中取出指令和数据且执行。指令序列就像流水一样“流”入运算单元,当指令流尽,就意味着程序结束了。

对于计算机,自然是希望运算的速度越快越好。所以机械式运算很快就淘汰了。取而代之的就是电子式计算机。

 

电子式计算机的硬件基础,就是数字电路。因为二进制可以很自然的表示开和关的两种状态,高和低的两种状态,通和断的两种状态,等等。所以很快就取得了主导低位,其它进制的数字电子器件沦为小众。

理论上,二进制和十进制表示的数的范围是一样多的。因为实数集是一个连续同,不同进制实质上是对数集的不同分割。

基于二进制数字电子器件制造的电子式计算机自然就需要二进制的输入输出。

 

 

 

 

 

 

 

 

 

 

 

 



作者:知乎用户
链接:电脑怎样执行编程语言的?
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值