高级语言
高级语言是相对于直接面向机器的低级语言(如汇编语言)而言的。高级语言更加偏向于人类侧,对人类编写、阅读、理解、使用更加友好。
CPU 指令集和低级语言
CPU(中央处理器)指令集(Instruction Set Architecture, ISA)是指 CPU 能够识别和执行的所有机器指令的集合。指令集定义了 CPU 的基本操作能力,包括数据处理、存储访问、控制流等,是硬件与软件之间的接口。
指令通常是一个二进制编码的数字,向 CPU 传递一个指令的时候,CPU 将会根据内部的数字电路执行某个操作和运算。指令集就是一个 CPU 所能支持的全部二进制编码的数字的有限集合。因此指令集与特定的 CPU 所绑定。一个 CPU 如果计划按照某个指令集来进行设计,那么,它需要支持指令里面的全部指令,这样它就可以复用该指令集生态里面的工具和资源。
常见的指令集类型有:
- CISC(复杂指令集计算机):如 x86 架构,指令种类丰富,单条指令功能强大,适合复杂操作。
- RISC(精简指令集计算机):如 ARM、MIPS、RISC-V 等,指令种类少、结构简单,执行效率高,便于流水线设计。
主流指令集架构包括:
- x86/x86-64:广泛应用于 PC 和服务器,由 Intel 和 AMD 主导。
- ARM:应用于移动设备、嵌入式系统,具有低功耗、高性能的特点。
- RISC-V:开源指令集,近年来发展迅速,适用于学术和工业界。
汇编语言是对 CPU 指令集的符号化表示。由于人类不方便记忆由 01 序列组成的二进制编码,因此使用英语符号来表示某个特定的二进制数,从而降低记忆负担。汇编语言是对机器指令的一层简单映射,人们会使用汇编器来将汇编语言代码符号映射成机器码。
不同的指令集有各自对应的汇编语言,指令集与汇编语言是强绑定的关系。程序员通过汇编语言可以直接操作底层硬件,实现对 CPU 资源的精细控制。
高级语言类型
汇编语言提供了简单的抽象,但是随着程序复杂度的提升,汇编器帮助开发人员的地方还是太少,因此出现了高级语言,高级语言支持更加完备的开发支持和特性,能够显著提升开发者的效率。
各个高级语言的编译器或者运行时,往往有两种类型,一种是纯编译、一种是纯解释,当然还有能够将两者合二为一的混合类型。
编译型
编译器接受源代码文件进行处理,输出面向特定架构 CPU 的指令,典型的例子:C、C++、Rust、Go、Zig。这些语言可以直接面向底层硬件的特性,拥有细粒度控制下层资源的能力,能够访问下层硬件的全部特性,具有极高的运行效率。
以 C 为例,C 编译器将 C 源代码编译成为面向特定 CPU 的汇编指令,然后由该硬件厂商或者开源实现的汇编器,将汇编代码汇编成为对应架构的机器码,最终生成二进制可执行文件,二进制可执行文件可以直接运行在 CPU 上。
操作系统抽象
现代的程序往往需要依赖操作系统提供的一些 API,从而获得快捷访问硬件功能的能力,另一方面,操作系统提供的进程封装,可以让应用层的程序按需加载和释放。
应用程序在被操作系统加载到内存之后,便可以直接运行在 CPU 之上,当应用程序需要操作系统的 API 的时候,通过调用特殊指令,触发跳转,从而切换到内核态的代码,执行操作系统的代码。也就是说,应用程序在执行自身的代码的时候往往无需操作系统的介入,只有当它需要调用操作系统 API 的时候,才会触发跳转以运行操作系统的代码。
解释型
解释型语言的运行时不会将源代码一次性编译为机器指令,而是通过解释器逐行读取、分析和执行源代码,解释器会将每一个高级语言语法和指令,映射成为一个解释器内部的函数调用。相当于引入了一个中间代理层,上层只管发号施令,下层具体实现由解释器负责。典型代表有 Python、Ruby、Lua 等。这类语言开发效率高,跨平台能力强,适合快速开发和脚本编程,但运行速度通常较慢。
解释型语言的执行流程一般为:源代码 → 解释器 → 逐行翻译为中间指令或直接执行。同时,解释器可以实现动态类型检查、即时调试和热加载等特性。
混合型
混合型语言结合了编译型和解释型语言的优点。通常,源代码首先被编译为中间代码(如字节码),然后由虚拟机(VM)或运行时环境进行解释执行。这样既能获得较好的跨平台能力,也能通过运行时优化提升执行效率,缺点是运行时环境较为复杂,占用资源较多。典型代表有 Java、C#、Dart 等。
JIT 和 AOT
解释性语言和混合型语言由于有中间层,可以做一些优化,从而在性能上获得提升。主要有两个策略。
- JIT(Just-in-Time Compilation,即时编译):在程序运行时,将中间代码动态编译为机器码,并可根据实际运行情况进行优化。可根据实际运行数据进行优化,兼顾跨平台和性能,支持动态加载和调试。首次运行时启动较慢,运行时资源消耗较大。
典型应用:Java(JVM)、C#(.NET CLR)、JavaScript(V8)、Dart(Dart VM 开发模式)。
- AOT(Ahead-of-Time Compilation,预编译):就是仿效编译型语言,将解释性语言的代码进行部分的提前编译,从而获得特定 CPU 的机器码,以提升效率,但是这会导致跨平台能力下降,需要分平台进行构建。
典型应用:Dart(Dart VM AOT 模式)、Java(Graal VM)。
实际应用中,许多现代语言和平台会结合使用 AOT 和 JIT,以兼顾启动速度、运行效率和开发体验。