原文地址: https://juejin.im/post/5cea0c4be51d45775a70027f
在计算机的世界中,一个Programmer多多少少有听说过编辑器,解释器,机器码,字节码这些名词, 现在我们稍微深入问一问:
- 这些名词分别表示的是什么?
- 编辑器和解释器是如何运行?
- 它们之间又有什么联系呢?
本文的目的就是为了理清这些问题.
目录
Type of code(代码的类型)
计算机的代码根据封装程度的高低可以分为以下几类(从低到高):
-
Microcode(微码): 微码是一种直接控制CPU的代码, 通过将机器指令与相关的电路实现分离, 使得机器指令可以更自由的进行设计与修改,而不用考虑到实际的电路架构.(传统架构CPU的操作直接写死在电路板上,需要物理改动才能修改).
- 也被称为firmware(固件).
- 通常存放在ROM上,不开放修改.
- 仅适用于其设计的特定硬件.
- 处于软件层面的最底层.
-
Machine code(机器码): 可以由CPU直接执行的代码.
- 在CISC架构的电脑上会被转化为机器码来执行.
- 在RISC架构的电脑上直接执行.
- Object code(目标代码): 一般是机器码,但是只是一部分,需要通过Linker(链接器)来将多个目标代码文件链接成一个完整的可执行程序.(如C语言中对标准库的引用).
-
Bytecode(字节码): 通常指的是已经经过编译,需要解释器翻译后才能成为机器码的中间代码. 如Java字节码.
- 是为了解释器的高效执行而设计.
- 可跨平台.
Level of Programming Language(编程语言的层级)
编程语言根据对机器语言的抽象(封装)程度可以分为两类:
-
Low-level programming language(低级编程语言): 不提供或jin仅提供很少的封装,接近机器语言.
- 一般指Machine language(机器语言)和Assembly language(汇编语言).
- 代码通常只能在特定平台上执行.
- 执行效率高.
- 可阅读性差.
- 开发效率低.
-
High-level programming language(高级编程语言): 高度封装了机器语言, 需要编译器或解释器转化成机器码才能执行. 如: C,C++,Java,Python等.
- 执行效率较低.
- 可读性好.
- 开发效率高.
汇编语言的代码需要由汇编器(assembler)将代码转为机器码才能执行,也可以认为是高级语言.
如下图:
图片来自: Quora: What are the different types of programming languages?
用高级语言编写的程序要么由某种解释器直接执行,要么由编译器(以及汇编程序和链接程序)转换成机器代码, 然后由CPU执行.
下面来介绍编译器和解释器.
Compiler(编译器)
编译器是一个将一种编程语言的代码翻译(translate)为另外一种编程语言的代码的计算机程序. 通常指将高级语言的代码翻译为低级语言的代码.
主要目的是将便于人编写,阅读,维护的高级语言的代码翻译为计算机能解读,运行的机器码.
编译器还有以下几类:
- cross-compiler(交叉编译器): 翻译输出的代码可以运行于不同的平台(不同的CPU或操作系统).
- bootstrap compiler: 由要编译的输入语言编写的编译器,它初始核心版本由其他语言生成(一般是汇编语言).
- decompiler(逆编译程序): 将低级语言的代码翻译为高级语言的代码.
- source-to-source compiler(源码到源码编辑器): 将一种高级语言代码翻译成另外一种高级语言的代码.
编译器的工作流程
一个编译器的工作流程一般会包括以下几个步骤(顺序执行):
- preprocessing
- lexical analysis
- parsing
- semantic analysis (syntax-directed translation)
- conversion of input programs to an intermediate representation
- code optimization
- code generation
如下图:
Interpreter(解释器)
解释器是一种直接执行高级语言代码的计算机程序, 而无需将代码编译成机器码.
- 优点: 消除了编译整个程序的负担,程序可以拆分成多个部分来模块化.
- 缺点: 解释器像是一位“中间人”,每次运行程序时都要先将代码转成另一种语言的代码,然后再作运行,因此解释器的程序运行速度比较缓慢.
解释器执行代码的策略一般有以下三种:
- 直接运行高级编程语言的代码(如Shell内置的解释器).
- 先将代码转换成高效的中间码(如:Bytecode),然后马上执行(不输出中间码).
- 由解释器中内置的编译器先将高级语言的代码编译成中间码,然后再执行.(输出中间码,相当于两个阶段,如Java的执行)
与编译器的执行方式的对比如下图:
图片来自: Compiler vs Interpreter: Complete Difference Between Compiler and Interpreter