程序设计语言和编译程序
低级语言基本概念
介绍:
包括机器语言和汇编语言
机器语言:指的是机器能直接识别的程序语言。无需经过翻译,每一操作码在计算机内部都有相应的电路来完成它,或指不经翻译即可为机器直接理解和接受的程序语言或指令代码。计算机硬件只能识别“断开”和“闭合”两种物理状态,也就是0和1。机器语言使用绝对地址和绝对操作码。不同的计算机都有各自的机器语言,即指令系统,不同型号的计算机其机器语言是不相通的,按着一种计算机的机器指令编制的程序,不能在另一种计算机上执行。从使用的角度看,机器语言是最低级的语言。
- 操作码:操作码给出指令完成的功能
- 地址码:地址码给出与操作数相关的地址或者操作数本身
- 指令 10110110【操作码】 00000000【地址码】 表示进行一次加法操作
- 指令 10110101【操作码】 00000000【地址码】 表示进行一次减法操作
汇编语言:是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为
符号语言
。在汇编语言中,用助记符(Mnemonics)代替机器指令的操操作码,用地址符号(Symbol)或标号(Label)代替指令或操作数的地址。在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。普遍地说,特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植。举个例子,a = a + b的表达方式:
- MOV AX,1
- MOV BX,2
- ADD AX,BX
ps:是不是相较于之前的0和1,现在已经可以大致看懂了?
优点:
- 速度快
缺点:
- 难理解,出错率高,难维护
- 依赖于具体机器,移植性差
发现:
- 越是低级的语言对机器越是友好,越是符合机器的思考方式,因此执行效率高。
- 越是高级的语言对人类越是友好,越是符合人类的思考方式,因此开发效率高。
高级语言基本概念
形式语言
介绍:
用精确的数学或机器可处理的公式定义的语言。与自然语言对应,自然语言就是人类讲的语言,这类语言不是认为设计,而是自然进化的。形式语言是为了特定的应用而人为设计的语言,存在领域之分,例如数学家用的各种运算符号,化学家用的各种分子式,而
编程语言也是一种形式语言,是专门设计用来表达计算过程的形式语言
。
特点:
- 高度的抽象化:采用形式化的手段-专用符号,数学公式-来描述语言的结构关系,这种结构关系是抽象的
- 是一套演绎系统:形式语言本身的目的就是要用有限的规则来推导语言中无限的句子,提出形式语言的哲学基础也是想用演绎的方法来研究自然语言
- 具有算法的特点
高级语言
介绍:
高度封装了的编程语言,与低级语言相对,它更接近于我们平时正常的人思维,其最大的特点是编写容易,代码可读性好。实现同样的功能,使用高级语言耗时更少,程序代码量更短,更容易阅读。其次,高级语言是可移植的,也就是说,仅需稍作修改甚至不用修改,就可将一段代码运行在不同类型的计算机上。现在大多数人使用的语言,如C、C++、Python、Java、Javascript等等,都属于高级语言。
优点:
- 面向自然表达
- 更易于学习,易于理解,易于修改
- 可移植性高
缺点:
- 运行需要其他程序支撑(编译程序等)
- 运行速度相比汇编要慢
- 占用空间相对较多
高级语言与汇编语言程序的执行
翻译程序
翻译程序可以将一种计算机编程语言编写的程序翻译成另一种计算机语言。输入对象是源程序
,一般是由高级语言编写的程序,输出对象是目标程序
,可以是机器语言,汇编语言,或者是用户自定义的某种中间语言程序或者是其他的高级语言。翻译程序可以包括:
- 汇编器(Assembler)
- 编译器(Compiler)
- ...
Linker(链接器):将
目标文件内容
连同运行时库程序
合成到一个计算机能够加载和执行的目标程序
执行方式
执行高级语言程序的方式分为三种:
- 编译方式
- 解释方式
- 转换方式
下面我来具体介绍~
编译方式和解释方式
编译方式
解释方式
详细介绍
这里我先借助知乎网友的例子,这个过程的区别很像是:
A是英语演讲者,B是台下的听众,C是翻译官。那么,编译器就是:翻译官把A的演讲的所有内容(等A演讲完)一次性整理好成一份翻译后的文件,发给听众B看。 翻译器就是:翻译官C在A演讲的时候,A讲一句,C翻一句给听众B。
其实这个例子还是很生动形象的,总结起来就是:
- 编译器是在代码运行之前生成目标平台指令,可脱离编译器独立运行。
- 解释器在代码运行过程中生成目标平台指令,所以不可以脱离解释器独立运行。
于是我们看到的现象是,编译型语言要先编译再运行,而解释性语言直接“运行”源代码。
即他们的根本区别
就是运行时,解释型需要将程序解释成目标平台指令来运行,费了一道手续,而编译型在运行之前就已经让编译器给程序编译成目标平台指令了,所以更快。
ps:此处可以结合后面辩证的看
那个段落效果更佳~
解释器与编译器不同角度对比
- 着眼点:解释器是执行系统,编译器是转换系统
- 程序动态修改:解释执行更胜任,编译执行需要动态编译技术,难度较大
- 速度:解释器较慢
- 空间开销:解释器开销大
- 错误诊断:解释器更强,因为解释器会逐个语句的执行源程序
辩证的看
我们不妨换个角度来看,其实如果单纯从编译方式和解释方式的定义出发,他们是那么的水火不相容,然而编译和解释的界限却并没有如此的清晰,举个例子(下文有流程图):Java需要预先把代码编译成虚拟机指令的,然后在运行这些虚拟机指令,有的教科书上会成为混合型或者半编译型,这样的好处之一是在一台机器上编译得到的字节码可以在另一台机器上解释执行,通过网络就可以完成机器之间的迁移。所以其实我们把他们撕裂着看又有一点点不合理,我查阅资料也发现有很多人对此有不同的见解,其实我眼里,我们高级代码执行,无非是从高级的抽象转化为低层级抽象的一个过程,我们在这个过程中,可能用到了解释器,也可能用到了编译器,这两者的使用并无冲突,就像上面的例子一样,无非是我们可能在降低代码抽象层级的过程中分出了不同的阶段,用了不同的方案而已,无论是编译执行还是解释执行,应该与语言无关,只是使用了什么样的方案把代码让机器看的懂而已,所以
纠结一个语言是解释型还是编译型语言在我的认知中是不必要
的
上一段Java的流程图:
转换方式
转换方式我放在最后单独说,因为可能和上述内容有一点点不同:
- 假如我们要实现L语言
- 我们现在已经有了L1语言的编译程序
- 那么我们可以先把用L语言编写的程序转换成等价的L1语言程序
- 再去利用L1语言的编译程序去实现L语言
说白了我们就是利用转换器将没有编译程序的L程序转换成已经存在编译程序的L1语言再去将其转换为目标程序 。