文章目录
- 前置基础共识
- [一、汇编(Assemble):汇编代码 → 机器码目标文件](#一、汇编(Assemble):汇编代码 → 机器码目标文件)
-
- [1. 什么是汇编](#1. 什么是汇编)
- [2. 核心特点](#2. 核心特点)
- 实操拆分gcc完整四步
- 生活化小比喻
- [二、狭义编译(Compile):高级代码 → 汇编代码](#二、狭义编译(Compile):高级代码 → 汇编代码)
-
- [1. 编译阶段核心工作](#1. 编译阶段核心工作)
- 关键区分
- 三、链接(Link):多个半成品整合为可执行程序
- 四、解释(Interpret):边翻译边执行,无汇编/链接流程
-
- [1. 执行逻辑](#1. 执行逻辑)
- [2. 典型特征](#2. 典型特征)
- 补充混合语言Java(易混考点)
- 五、四大概念完整对比表
- 六、总结
前置基础共识
CPU只认识纯二进制机器码(0/1)。
我们写的C/Python等高级语言是人类文本,想要交给CPU执行,分两条路线:
- 静态路线(C/C++):预处理 → 狭义编译 → 汇编 → 链接 四步完整流程,提前生成可执行文件
- 动态路线(Python/JS):解释,运行时逐行翻译,无完整前置流水线
一、汇编(Assemble):汇编代码 → 机器码目标文件
很多人分不清「狭义编译」和「汇编」,这是考试高频坑点!
1. 什么是汇编
狭义编译产出的是汇编代码 (人类能看懂的低级助记符,比如mov、add、call);
汇编 就是汇编器把汇编指令,一对一翻译成二进制机器码,生成.o/.obj目标文件。
2. 核心特点
- 一对一映射:一条汇编指令 = 一条机器指令,几乎没有复杂转换;
- 只翻译指令,不处理函数引用:遇到
call printf只会留占位,不知道printf真实地址; - 产出
.o半成品,依旧不能独立运行,必须等待链接。
实操拆分gcc完整四步
以test.c举例
c
#include <stdio.h>
int main(){
printf("hello world");
return 0;
}
- 只预处理+狭义编译,生成汇编文件
.s
bash
gcc -S test.c
打开test.s,里面全是movl push这类汇编助记符,这一步是狭义编译 ,还没走汇编阶段。
- 单独执行汇编,把汇编
.s转为目标文件.o
bash
gcc -c test.s
这一步才是汇编阶段 ,汇编器as执行翻译,得到半成品test.o。
生活化小比喻
狭义编译:把中文作文翻译成极简机器助记短句(汇编代码)
汇编:把每一句短句逐个翻译成01二进制编码(目标文件)
二、狭义编译(Compile):高级代码 → 汇编代码
注意!平时大家说的"编译"分两种:
- 广义编译:预处理+狭义编译+汇编+链接整套流程
- 狭义编译:只做「高级语言 → 汇编代码」这一步
1. 编译阶段核心工作
- 词法、语法、语义检查:少分号、变量未定义、类型不匹配直接报编译错误;
- 优化代码:常量合并、无用代码删除等简单优化;
- 将高级逻辑翻译成汇编助记符,不会生成二进制。
关键区分
编译:高级语言 → 汇编文本(可读)
汇编:汇编文本 → 二进制目标文件(机器可读,人看不懂)
三、链接(Link):多个半成品整合为可执行程序
汇编产出一堆.o目标文件,还有系统库文件,链接器负责收尾组装。
1. 两大核心工作
- 合并段:把所有
.o的代码段、数据段整合; - 符号解析+重定位:补齐
printf这类外部函数的内存地址,把汇编阶段留下的占位全部填满。
两种报错
- 编译错误:语法问题,卡在编译/汇编前,无法生成.s/.o;
- 链接错误:语法全对,但缺失函数实现、缺少依赖库,能生成.o,链接失败。
承接上面命令
bash
gcc test.o -o test
./test
链接完成后得到真正能运行的程序。
全套流水线类比
- 源代码.c = 中文作文初稿
- 狭义编译 = 翻译成机器专用短句(汇编.s)
- 汇编 = 短句转二进制草稿(.o半成品)
- 链接 = 补齐参考文献、整合全部草稿,产出完整可上交成品(exe/elf)
四、解释(Interpret):边翻译边执行,无汇编/链接流程
Python、JS、PHP这类解释型语言,不走上面四步流水线。
1. 执行逻辑
运行时解释器逐行读取源码,实时翻译成机器码,翻译一行执行一行,不会生成汇编、目标文件、可执行程序。
2. 典型特征
- 报错滞后:前面代码正常跑,执行到错误行才崩溃;
- 无需编译汇编链接,一键运行:
python test.py; - 缺点:重复代码重复翻译,运行速度远低于编译链接后的C程序。
补充混合语言Java(易混考点)
Java是折中方案:
- 先狭义编译:.java → 字节码.class(不是汇编,中间特殊格式)
- JVM运行时:解释执行 + JIT即时编译(热点代码转机器码)
全程不产生汇编、.o文件,和C流水线完全不同。
五、四大概念完整对比表
| 环节 | 输入文件 | 输出文件 | 核心工作 | 是否产生二进制 |
|---|---|---|---|---|
| 狭义编译 | .c 高级源码 | .s 汇编代码 | 语法检查、高级转汇编 | 否,文本 |
| 汇编 | .s 汇编代码 | .o/.obj目标文件 | 汇编指令一对一转机器码 | 是,半成品 |
| 链接 | 多个.o + 系统库 | exe/elf可执行程序 | 合并文件、补全符号地址 | 是,完整程序 |
| 解释 | .py/.js源码 | 无中间文件 | 运行时逐行实时翻译执行 | 无持久二进制文件 |
六、总结
- 狭义编译:高级源码翻译成可读汇编代码,做语法校验;
- 汇编:汇编助记符一对一转为二进制目标文件(.o),仅半成品;
- 链接:整合多个目标文件与系统库,补齐函数地址,生成可执行程序;
- 解释:运行时逐行翻译源码执行,无编译、汇编、链接流程,开发快执行慢。