怎么可能 bootstrap 一个 C 编译器(来自源代码)?
How could one possibly bootstrap a C compiler(from source)?
我正在研究 compiler bootstrapping,我研究了 Golang 如何从源代码实现引导,即通过构建用 C 实现的 Golang 的最新版本并使用生成的可执行文件来编译较新的 Go 版本。这让我很好奇如何用 C 完成同样的事情。你能在一台计算机上构建一个 C 编译器吗?如果不是,那么我怎么能相信我使用的编译器的二进制文件不会自动用间谍软件填充它编译的二进制文件?
相关问题,since the first C compiler was written in BB是用BCPL写的,BCPL是用什么写的?
您可以用汇编代码或机器代码编写一个非常弱的 C 编译器,然后从那里 bootstrap。
在编程语言出现之前,您只是编写机器代码。这就是它的完成方式。
后来出现了汇编程序,它就像“简单模式”的机器代码,并从那里发展出像 Fortran 和 BCPL 这样的高级语言。通过使用适当的编译器进行翻译,这些与机器架构分离。
今天你可能会用 C 写一些东西然后从那里开始,任何编译的东西都是合适的,尽管现在 LLVM 存在,“编译”是一个松散的定义,你可以敲出 LLVM IR 代码而不是实际的机器代码.例如,Rust 始于 OCaml,现在“自托管”在 LLVM 之上。
Can you construct a C compiler on a computer with literally nothing present on it?
主要问题是如何(2021年)你会为那台电脑写程序吗!你会如何输入它?
70 年代的计算机(例如 IBM 360 mainframes) had many mechanical switches to enter some initial program. In the 1960s, they had even more, e.g. IBM1620。
今天,您将如何输入初始程序?您是否考虑过今天使用一些 Arduino ? Even oscilloscopes 包含带程序的微处理器....
今天的一些业余爱好者已经设计(并花费了很多钱)制造 - 几年前 - 带有机械装置的计算机 relays。这些可能比您可以购买的最便宜的笔记本电脑(或您的计算机鼠标内的微控制器 - 而且您的鼠标也包含一些软件)慢数千倍。
你也可以买很多分立的 transistors(比如几千个 2N2222)然后焊接起来做一台电脑。
即使是便宜的主板(例如 MSI A320M A-PRO) has today some firmware program called UEFI or BIOS。它随该程序一起提供....传闻主要是用 C 编写的(几十万条语句)。
在某些方面,计算机芯片是用 VHDL, SystemC 编码的“软件”,等等……等等……
但是,原则上您仍然可以 bootstrap 2021 年的 C 编译器。
这是一个假设的故事....
假设您今天有一台笔记本电脑 运行 一个小型 Linux 分布在某个孤岛上(la Robinson Crusoe), without any Internet connection - but with books (including Modern C and some book about x86-64 assembly and instruction set architecture and many other books in paper form), pencils, papers, food and a lot of time to spend. Imagine that system does not have any C compiler (e.g. because you just removed by mistake the gcc
package from some Debian distribution), but just GNU binutils (that is, the linker ld
and the assembler gas
), some editor in binary form (e.g. GNU emacs or vim), GNU bash and GNU make as binary packages. We assume you are motivated enough to spend months in writing a C compiler. We also assume you have access to man pages in some paper form (notably elf(5) and ld(1)...). We have to assume you can inspect a file in binary form with od(1) and less(1).
然后你可以在纸上设计 EBNF notation. With months of efforts, you can write a small assembler program, directly doing syscalls(2) (see Linux Assembly HowTo) and interpreting that µC language (since writing an interpreter is easier than writing a compiler; read for example the Dragon book, and Queinnec's Lisp In Small Pieces and Scott's programming language pragmatics 书中 C 语言的一个子集 µC。
一旦你有了微型 µC 解释器,你就可以在 µC 中编写一个简单的 µC 编译器(因为 Fabrice Bellard 已经能够编写他的 tinyC 编译器)。
调试完 µC 编译器后,您可以扩展它以接受 C 的所有语法和语义。
一旦你有了一个完整的 C 编译器,你可以改进它以更好地优化,也许扩展它以接受 C++ 的一个小子集,你也可以编写一个受 Frama-C 启发的静态 C 代码分析器。
PS。 Bootstrapping 可以广泛推广 - 请参阅 Pitrat 关于 bootstrapping artificial intelligence (Jacques Pitrat, born in 1934, died in october 2019) and the RefPerSys 项目的博客。
正如一些程序员老兄在评论中所说,由于 C 是一种可移植的编程语言,您可以使用适用于不同平台的编译器来生成交叉编译器,该编译器在该平台上将为目标平台生成可执行文件。
然后您在 主机平台 上为 目标平台 编译相同的 C 编译器,以便结果是目标的可执行文件平台。
然后将该编译器二进制文件复制到目标机器上,然后它就可以自托管了。
自然地,在早期历史的某个时刻,有人确实不得不用汇编程序或机器代码在某处写一些东西。如今,它已不再是必需品,而是一种“人生选择”。
至于“我怎么能相信我使用的编译器的二进制文件不会自动用间谍软件填充它编译的二进制文件?”问题 has been solved - 您可以使用两个独立的编译器从 相同的源代码库 和目标编译交叉编译器,并且这两个交叉编译器应该产生按位相同的结果对于目标可执行文件。然后你会知道结果要么没有间谍软件,要么你在开始时使用的两个独立编译器会用完全相同的 same 间谍软件感染生成的可执行文件 - 这是极不可能的。
我正在研究 compiler bootstrapping,我研究了 Golang 如何从源代码实现引导,即通过构建用 C 实现的 Golang 的最新版本并使用生成的可执行文件来编译较新的 Go 版本。这让我很好奇如何用 C 完成同样的事情。你能在一台计算机上构建一个 C 编译器吗?如果不是,那么我怎么能相信我使用的编译器的二进制文件不会自动用间谍软件填充它编译的二进制文件?
相关问题,since the first C compiler was written in BB是用BCPL写的,BCPL是用什么写的?
您可以用汇编代码或机器代码编写一个非常弱的 C 编译器,然后从那里 bootstrap。
在编程语言出现之前,您只是编写机器代码。这就是它的完成方式。
后来出现了汇编程序,它就像“简单模式”的机器代码,并从那里发展出像 Fortran 和 BCPL 这样的高级语言。通过使用适当的编译器进行翻译,这些与机器架构分离。
今天你可能会用 C 写一些东西然后从那里开始,任何编译的东西都是合适的,尽管现在 LLVM 存在,“编译”是一个松散的定义,你可以敲出 LLVM IR 代码而不是实际的机器代码.例如,Rust 始于 OCaml,现在“自托管”在 LLVM 之上。
Can you construct a C compiler on a computer with literally nothing present on it?
主要问题是如何(2021年)你会为那台电脑写程序吗!你会如何输入它?
70 年代的计算机(例如 IBM 360 mainframes) had many mechanical switches to enter some initial program. In the 1960s, they had even more, e.g. IBM1620。
今天,您将如何输入初始程序?您是否考虑过今天使用一些 Arduino ? Even oscilloscopes 包含带程序的微处理器....
今天的一些业余爱好者已经设计(并花费了很多钱)制造 - 几年前 - 带有机械装置的计算机 relays。这些可能比您可以购买的最便宜的笔记本电脑(或您的计算机鼠标内的微控制器 - 而且您的鼠标也包含一些软件)慢数千倍。
你也可以买很多分立的 transistors(比如几千个 2N2222)然后焊接起来做一台电脑。
即使是便宜的主板(例如 MSI A320M A-PRO) has today some firmware program called UEFI or BIOS。它随该程序一起提供....传闻主要是用 C 编写的(几十万条语句)。
在某些方面,计算机芯片是用 VHDL, SystemC 编码的“软件”,等等……等等……
但是,原则上您仍然可以 bootstrap 2021 年的 C 编译器。
这是一个假设的故事....
假设您今天有一台笔记本电脑 运行 一个小型 Linux 分布在某个孤岛上(la Robinson Crusoe), without any Internet connection - but with books (including Modern C and some book about x86-64 assembly and instruction set architecture and many other books in paper form), pencils, papers, food and a lot of time to spend. Imagine that system does not have any C compiler (e.g. because you just removed by mistake the gcc
package from some Debian distribution), but just GNU binutils (that is, the linker ld
and the assembler gas
), some editor in binary form (e.g. GNU emacs or vim), GNU bash and GNU make as binary packages. We assume you are motivated enough to spend months in writing a C compiler. We also assume you have access to man pages in some paper form (notably elf(5) and ld(1)...). We have to assume you can inspect a file in binary form with od(1) and less(1).
然后你可以在纸上设计 EBNF notation. With months of efforts, you can write a small assembler program, directly doing syscalls(2) (see Linux Assembly HowTo) and interpreting that µC language (since writing an interpreter is easier than writing a compiler; read for example the Dragon book, and Queinnec's Lisp In Small Pieces and Scott's programming language pragmatics 书中 C 语言的一个子集 µC。
一旦你有了微型 µC 解释器,你就可以在 µC 中编写一个简单的 µC 编译器(因为 Fabrice Bellard 已经能够编写他的 tinyC 编译器)。
调试完 µC 编译器后,您可以扩展它以接受 C 的所有语法和语义。
一旦你有了一个完整的 C 编译器,你可以改进它以更好地优化,也许扩展它以接受 C++ 的一个小子集,你也可以编写一个受 Frama-C 启发的静态 C 代码分析器。
PS。 Bootstrapping 可以广泛推广 - 请参阅 Pitrat 关于 bootstrapping artificial intelligence (Jacques Pitrat, born in 1934, died in october 2019) and the RefPerSys 项目的博客。
正如一些程序员老兄在评论中所说,由于 C 是一种可移植的编程语言,您可以使用适用于不同平台的编译器来生成交叉编译器,该编译器在该平台上将为目标平台生成可执行文件。
然后您在 主机平台 上为 目标平台 编译相同的 C 编译器,以便结果是目标的可执行文件平台。
然后将该编译器二进制文件复制到目标机器上,然后它就可以自托管了。
自然地,在早期历史的某个时刻,有人确实不得不用汇编程序或机器代码在某处写一些东西。如今,它已不再是必需品,而是一种“人生选择”。
至于“我怎么能相信我使用的编译器的二进制文件不会自动用间谍软件填充它编译的二进制文件?”问题 has been solved - 您可以使用两个独立的编译器从 相同的源代码库 和目标编译交叉编译器,并且这两个交叉编译器应该产生按位相同的结果对于目标可执行文件。然后你会知道结果要么没有间谍软件,要么你在开始时使用的两个独立编译器会用完全相同的 same 间谍软件感染生成的可执行文件 - 这是极不可能的。