Raz*_*orm 10 architecture compiler-construction boot gcc bootstrapping
我正在查找pypy项目(Python中的Python),并开始思考运行python外层的问题?当然,我猜想,它不能像古老的说法那样"乌龟一路走下去"!毕竟,python是无效的x86程序集!
很快我就想起了bootstrapping的概念,并查找了编译器引导."好的",我想,"所以它可以用不同的语言编写,也可以用汇编编写".为了性能,我确信C编译器只是从汇编中构建的.
这一切都很好,但问题仍然存在,计算机如何获得该汇编文件?!
假设我买了一个没有任何东西的新cpu.在第一次操作期间,我希望安装一个运行C的操作系统.什么运行C编译器?BIOS中是否有微型C编译器?
谁可以给我解释一下这个?
小智 12
假设我买了一个没有任何东西的新cpu.在第一次操作期间,我希望安装一个运行C的操作系统.什么运行C编译器?BIOS中是否有微型C编译器?
我理解你在问什么...如果我们没有C编译器并且必须从头开始会发生什么?
答案是你必须从装配或硬件开始.也就是说,您可以在软件或硬件中构建编译器.如果全世界都没有编译器,那么现在你可以在组装中更快地完成它; 然而,在当天我认为编译器实际上是专用硬件.在维基百科的文章是有点短,不支持我上,不过没关系.
我想下一个问题是今天发生了什么?那些编译器编写者多年来一直忙于编写可移植C,因此编译器应该能够自己编译.值得讨论的是汇编是什么.基本上,您接受一组语句并从中生成程序集.而已.好吧,它实际上比那更复杂 - 你可以用词法分析器和解析器做各种各样的事情,我只理解它的一小部分,但实际上,你正在寻找将C映射到汇编.
在正常操作下,编译器会生成与您的平台匹配的汇编代码,但它不需要.它可以为您喜欢的任何平台生成汇编代码,前提是它知道如何操作.因此,在您的平台上使C工作的第一步是在现有编译器中创建目标,开始添加指令并使基本代码正常工作.
一旦完成,理论上,您现在可以从一个平台交叉编译到另一个平台.接下来的阶段是:为该平台构建内核,引导加载程序和一些基本的用户态实用程序.
然后,您可以编译该平台的编译器(一旦您拥有了工作用户空间以及运行构建过程所需的一切).如果成功,您将拥有基本实用程序,工作内核,用户空间和编译器系统.你现在好了.
请注意,在移植编译器的过程中,您可能还需要为该平台编写汇编程序和链接程序.为了简化描述,我省略了它们.
如果有兴趣,Scratch的Linux是一本有趣的读物.它没有告诉你如何从头开始创建一个新目标(这是非常重要的) - 它假设你要为现有的已知目标构建,但它确实向你展示了如何交叉编译基本要素并开始构建系统.
Python实际上并没有组装到程序集.首先,正在运行的python程序会跟踪对象的引用计数,这是cpu不会为你做的事情.但是,基于指令的代码的概念也是Python的核心.玩这个:
>>> def hello(x, y, z, q):
... print "Hello, world"
... q()
... return x+y+z
...
>>> import dis
dis.dis(hello)
2 0 LOAD_CONST 1 ('Hello, world')
3 PRINT_ITEM
4 PRINT_NEWLINE
3 5 LOAD_FAST 3 (q)
8 CALL_FUNCTION 0
11 POP_TOP
4 12 LOAD_FAST 0 (x)
15 LOAD_FAST 1 (y)
18 BINARY_ADD
19 LOAD_FAST 2 (z)
22 BINARY_ADD
23 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
在那里你可以看到Python如何看待你输入的代码.这是python字节码,即python的汇编语言.如果你喜欢实现这种语言,它实际上有自己的"指令集".这是虚拟机的概念.
Java有着完全相同的想法.我拿了一个类函数并运行javap -c class得到这个:
invalid.site.ningefingers.main:();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iconst_0
3: istore_1
4: iload_1
5: aload_0
6: arraylength
7: if_icmpge 57
10: getstatic #2;
13: new #3;
16: dup
17: invokespecial #4;
20: ldc #5;
22: invokevirtual #6;
25: iload_1
26: invokevirtual #7;
//.......
}
Run Code Online (Sandbox Code Playgroud)
我认为你明白了.这些是python和java世界的汇编语言,即python解释器和java编译器分别如何思考.
值得一读的其他东西是JonesForth.这既是一个工作的解释器和一个教程,我不能推荐它足以考虑"如何执行"以及如何编写一个简单,轻量级的语言.
小智 6
为了性能,我确信C编译器只是从汇编中构建的.
如今,C编译器(几乎?)完全用C语言编写(或者更高级语言 - 例如Clang是C++).编译器从包含手写汇编代码中获得的收益甚微.花费大部分时间的事情和它们一样慢,因为它们解决了非常困难的问题,"硬"意味着"大计算复杂性" - 在汇编中重写最多会带来不断的加速,但那些在那里并不重要水平.
此外,大多数编译器都希望具有高可移植性,因此前端和中端的体系结构特定技巧是不可能的(在后端,它们也不可取,因为它们可能会破坏交叉编译).
假设我买了一个没有任何东西的新cpu.在第一次操作期间,我希望安装一个运行C的操作系统.什么运行C编译器?BIOS中是否有微型C编译器?
当您安装操作系统时,(通常)没有C编译器运行.安装CD中充满了针对该架构的易于编译的二进制文件.如果包含一个C编译器(就像许多Linux发行版的情况一样),那也是一个已经编译好的可编译器.那些让你构建自己的内核等的发行版也至少包含一个可执行文件 - 编译器.当然,除非你必须使用C编译器在任何现有的安装上编译自己的内核.
如果"新CPU"意味着一个新的架构不能向后兼容任何尚未支持的东西,那么自托管编译器可以遵循通常的移植过程:首先为该新目标编写后端,然后自己编译,突然间你在新平台上得到了一个成熟的编译器,其中包含一个经过强制攻击(编译完整编译器)的本机后端.
| 归档时间: |
|
| 查看次数: |
3219 次 |
| 最近记录: |