世界上第一个编译器,是用纯机器码手工写出来的

这是一个经典的“先有鸡还是先有蛋”的问题。最直接、最反直觉的答案是:

世界上第一个编译器,是用纯机器码(二进制)手工写出来的。

没有任何高级语言可以用来写它,因为高级语言和编译器在当时都不存在。整个过程,是一场从“纯硬件”向“软件”艰难攀登的壮举。

🐣 第一步:机器码手搓汇编器(1950年代初)

我们通常说的“第一个编译器”指的是第一个汇编器(Assembler),它将人类可读的助记符(如 ADD R1, R2)翻译成机器能执行的二进制机器码(如 0001 1010 0011)。

  • 用什么写? 直接用机器的原生二进制指令(机器码),通过打孔纸带或面板上的开关,一条一条手工输入。

  • 过程:先写出一个极其简陋、能翻译少数几条指令的“加载器”。然后用这个加载器,再去编写功能稍强一点的汇编器。如此反复迭代,最终才得到一个能用的汇编器。

这个“用机器码写程序”的过程,类似于在完全黑暗的屋子里,用火柴点亮一根蜡烛,再用这根蜡烛去点亮下一根。

🚀 第二步:汇编器编译高级语言编译器(1950年代末)

第一个真正意义上的高级语言编译器,通常被认为是 FORTRAN 的编译器(1957年,IBM团队开发)。

  • 用什么写? 此时,汇编器已经成熟。FORTRAN 的编译器,绝大部分是用汇编语言(Assembly)编写的

  • 过程:程序员用助记符(如 MOVJMP)编写编译器的源代码,然后由汇编器将其转化为机器码。这相当于用“火柴”(汇编器)点燃了“火把”(第一个高级语言编译器)。

🤝 第三步:自举(Bootstrap)—— 用自己编译自己

编译器一旦成型,一个更优雅的工程化做法就出现了:自举(Bootstrapping)

以C语言为例:

  1. 首先,用汇编语言写一个极简的C编译器(只支持C语言一个非常小的子集)。

  2. 然后,用这个迷你编译器,去编译一个功能更完整的C编译器的源代码(该源代码是用标准C语言编写的)。

  3. 最后,再用这个功能更完整的编译器,去编译它自己的源代码,从而生成一个完全优化、可独立运行的最终版C编译器。

从此,“用自己开发自己的编译器”成为了行业标准。 我们今天的 gcc 可以编译 gcc 自身的源代码,Rust的 rustc 可以用Rust语言重写。

🌏 对中国自研编译器的启示

这个“自举”过程,也解释了为什么国内在研发编译器时,往往选择基于LLVM或开源GCC进行二次开发。

  • 门槛问题:从机器码手搓一个商业级编译器(如支持C++17全部特性的Clang)已经是不可能的任务。其代码量百万行级别,相当于要重新发明一遍整个软件工业的地基。

  • 策略选择:华为的毕昇编译器、香山编译器选择基于LLVM,就像拿到了一个半成品的“发动机”(优化框架和后端),只需根据鲲鹏或RISC-V芯片的特点,开发定制化的优化Pass即可。这是一种更高效的工程化策略。

💎 总结

回答你的问题:

  • 第一个编译器(汇编器):用机器码

  • 第一个高级语言编译器(FORTRAN):用汇编语言

  • 现代编译器(如GCC、Rustc):用自身语言(自举)。

这条路径,完美地印证了你之前提到的观点:这一切都从艰难的“科学探索”演变成了一套成熟的“工程化”流程。 今天我们能站在LLVM和RISC-V的肩膀上工作,正是因为前人在没有路的地方,一步一步铺出了第一块基石。

posted @ 2026-08-19 17:57  古锁阳关  阅读(27)  评论(0)    收藏  举报