低级编程语言(Low-level programming language)
接近硬件,机器相关,由0、1串组成,往往不可移植,难于阅读和对人不友好(human-friendly)。
比如你能看出下面的代码是啥么?
0000100100101110011001100110100101101100011001010000100100100010011011000110010101100011011101000111010101110010011001010011000100101110011000110010001000001010011001110110001101100011001100100101111101100011011011110110110101110000011010010110110001100101011001000010111000111010000010100010111001110011011001010110001101110100011010010110111101101110000010010010001000101110011101000110010101111000011101000010001000001010000010010010111001100001011011000110100101100111011011100010000000110100000010100000100100101110011001110110110001101111011000100110000101101100001000000110110101100001011010010110111000001010000010010010111001110100011110010111000001100101000010010010000001101101011000010110100101101110...
汇编语言(Assembly language)
汇编语言使用助记符代替一些机器指令,用地址符号或标号代替指令或操作数的地址。开始变得对人友好,可阅读性和便捷性比起机器语言有所提高。但汇编语言只是将机器语言做了简单编译,并没有从本质上解决机器语言的特定性,还是和机器自身和编程环境相关。
高级编程语言(High-level programming language)
接近自然语言和数学公式,具有更强的表达能力,易于学习和掌握,易于移植。
Fortran:第一个科学计算语言
Cobol:第一个商业数据处理语言
Lisp:第一个函数式程序语言
编译器和解释器的不同
编译器将源代码翻译成可以直接运行在目标机器上的机器代码;解释器不需要先翻译成机器代码,直接执行源代码中的每一条指令。
编译器花更多时间分析代码关系从而优化代码;解释器只是简单的转化每一条指令然后执行。
解释器直接执行程序直到遇到第一个可以中断执行的错误;编译器保证代码只有完全通过编译才能执行。
Java程序执行过程
Java是一个奇怪的语言,你可以说他是编译型语言,也可以说他是解释型语言。但在我看来,说的准确一点,Java是一个编译型与解释型混合语言。以下为Java程序的执行过程: (java编译的过程) Java源程序首先经过 Java编译器 生成后缀为.class的Java字节码文件,然后送到JVM执行。JVM首先会使用一个叫做 类加载器 (class loader)的程序将类的字节码加载到内存中。如果程序使用到了其他类,类加载程序会在需要他们之前动态的加载它们。当加载完成后,JVM使用一个称为 字节码验证器 (bytecode verifier)的程序来检验字节码的合法性,确保字节码不会违反Java安全规范。Java强制执行严格的安全规范,以确保来自网络的Java程序不会篡改和危害你的计算机。之后即可通过解释器执行Java程序。Java程序最初是通过 解释器 进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为“ 热点代码 ”。为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为 即时编译器 (Just In Time Compiler,JIT)。Java虚拟机规范并没有规定Java虚拟机内必须要有即时编译器存在,但是由于解释器的性能较低,主流的Java虚拟机都采用了 编译器 与 解释器 并存的架构。 从Java执行过程来看,把Java叫做 编译型与解释型混合语言 更准确一点。常见的编译型语言:C、C++、Pascal、Go等
常见的解释型语言:JavaScript、Perl、Python、Ruby等
3一般编译器构造 一般编译器按照逻辑可划分为7个部分,词法分析器(lexical analyzer)、语法分析器(syntax analyzer)、语义分析器(semantic analyzer)、中间代码生成器(intermediate code generator)、机器无关代码优化器(machine-independent code optimizer)、代码生成器(code generator)和机器相关代码优化器(machine-dependent code optimizer)。 (编译构造) 其中,词法分析器、语法分析器、语义分析器和中间代码生成器4部分叫做编译器前端,编译器前端对源程序进行分析,把源程序切分成一些基本块并生成中间语言表示IR(intermediate representation),并且收集源程序信息存到符号表(symbol table)。 (前端) 后端负责从由前端传递过来的中间代码和符号表生成目标程序,并且在处理过程中执行代码优化。 (后端)
Lexical Analysis(scanning,词法分析)
(词法分析) 词法分析器将源代码分成一个一个的词素(lexemes)或者词(words),对R于每一个词素,产生一个词法单元(token)。词素(lexeme),是一个字符串,程序设计语言中的语法单元。词法单元(token),是词素的一个语法集合。比如在英语中的名词、动词、形容词;编程语言中的标识符(identifier),关键字(keyword)等。一个基本的token形式: 如: (语法分析)Syntax Analysis(parsing,语法分析)
(语法分析器) 词法分析器使用语法分析器生成的 tokens 表示语法结构,这个结构通常是一个语法树(syntax tree)。语法树的中间节点表示操作(operation),孩子节点表示操作的参数(arguments)。 如: (词法分析实例)Semantic Analysis (语义分析)
(语义分析 ) 语义分析器使用语法树和符号表中的信息检查语言定义的语义一致性,同时为类型检查、类型转化和中间代码生成收集类型信息。语法(syntax)描述程序的适当形式。
语义(semantic)描述程序的意思。
Jack said Jerry left his assignment at home.(Jack说Jerry把他的作业放过家里了)
这句话是符合语法的,但是我们无法知道这里的“his”指代的是Jack还是Jerry,这就造成了语义不明。语义分析就是为了确定每一条指令的具体意思。
Intermediate Code Generation (中间代码生成)
(中间代码生成) 当完成语义分析后,编译器生成一个中间表示,通常是三地址码(three-address code)。一张图说明生成中间表示的重要意义。 (中间表示) 如果没有合适的中间表示,在有 M 种语言和 N 种机器的情况下,就需要 M*N 个不同的编译器。但是存在一个合适的中间表示的情况下,就只需要 M+N 个不同的编译器。大家都知道O(n)和O(n 2 )的区别吧。三地址码(TAC)
最多只有一个运算符在指令右边,通常形式为 x = y op z。因为涉及三个变量,因此被称为三地址码。三地址码可以有不同的表现形式,典型的表现形式为四元式(Quadruples)、三元式(Triples)和间接三元式(Indirect triples)。四元式表示法一般形式:<op arg1 arg2 result>
三元式表示一般形式:<op arg1 arg2>
a = b ∗ −c + b ∗ −c
,以下为对应的三元式和四元式表示。
(三元式和四元式)
感觉三元式似乎比四元式简单,但其实三元式存在着一个缺点,无法交换指令顺序从而执行后序代码优化。例如:
(三元式缺点)
交换指令1和2并不会影响四元式的执行结果,但是在三元式中,得到了错误的答案。
间接三元式相对三元式增加了一个指令列表,可以实现指令交换。
Machine-Independent Code Optimization (机器无关的代码优化)
(机器无关代码优化) 机器无关代码优化提高中间代码的质量,目的是为了让它运行的更快,占用更少的内存,代码更短,消耗更少的资源等等。常见的优化点有死代码消除,局部/全局子表达式消除,复制传播和代码移动等。 例如: (机器无关代码优化例子)Code Generation (代码生成)
(代码生成) 代码生成器负责把中间表示(IR)翻译成对应目标机器代码,这里需要处理给变量分配寄存器和内存。 例如: (代码生成例子)Machine-dependent Code Optimization (机器相关的代码优化)
(机器相关代码优化实例) 机器相关的代码优化是在目标代码生成之后根据目标机器架构转换代码。它涉及CPU寄存器,可能有绝对内存引用而不是相对引用。机器相关的代码优化努力最大限度地利用内存层次结构。 比如某CPU架构将执行一条指令分为5部分IF: 获取指令(Instruction fetch from memory)
ID: 指令解码和寄存器读(Instruction decode & register read)
EX: 指令执行(Execute operation or calculate address)
MEM: 内存访问(Access memory operand)
WB: 结果写回寄存器(Write result back to register)
原创不易,希望大家多多支持>3<