基于我对以下假设的理解,我产生了一个疑问,1.对于每个CPU架构,汇编语言集都会不同。
所以,我怀疑的是通用编译器/解释器是如何将其转换为.asm代码的,因为不是所有的计算机都有相同的体系结构!
我猜答案是“当我们在系统中安装编译器时,它会了解要安装的计算机架构,因此它会将C++/python/java转换为相应的CPU.asm代码”
所以,如果我上面的猜测是正确的,那么我理解当他们设计编译器时,开发人员需要将所有CPU架构的汇编集集成到编译器中。
注:我的怀疑是愚蠢的,我从来没有做过任何编译课程,我是一个欧洲经委会的grad。p
1条答案
按热度按时间xwmevbvl1#
汇编语言不一定是你需要关注的地方。
每个处理器都有一个体系结构,特别是指令集。2考虑指令集,机器码,而不是汇编语言,因为有无数的例子,不兼容汇编语言的相同体系结构。3在一天结束时,你需要机器码,指令。
编译器具有至少一个输入和一个输出,例如,C编译器可以将C转换成asm或者可以将C转换成机器码,或者可以将C转换成java字节码或者一些其它字节码。语言在这里是一个大问题,因为有趣的是,难以标准化并且被打包有实现定义项的C实际上收敛于pyton,rust,等由于某种原因而随时间改变/发散。在任何情况下,你有各种各样的编译器和各种各样的目标。2这当然是一个我想从一个理想的高级语言到一个低级语言的例子。3但是你可能有一个编译器,从一开始就是为一个目标设计的(伊萨)和从前到后旨在优化它的输出为该目标。其他人像gcc可能已经开始这样做,我不知道,但现在是非常前面,中间和后面。前面本质上解析要编译的语言,它通常被转换成一些内部代码或数据结构,添加两个变量并存储在第三个变量中可能会转换成三个变量分配步骤,每个步骤都有一定大小。然后操作get这个操作数get那个操作数把它们加起来然后存储结果。非常像把高级语言变成汇编语言。一般来说,大部分优化发生在你有这些通用操作的这一层。然后你有你的后端,它把这个中间代码/数据变成目标特定的代码。理想情况下,一些优化,有时候你会听到窥视孔优化器这个词,汇编通常不会被优化,这会导致严重的问题,但编译代码,一般来说仍然可以得到一些目标特定的优化。一些指令集可以使用立即数添加小数字其他你可能需要加载立即数到寄存器中,然后执行操作,因此,如果你将最小数字优化到操作中,你可以保存一条指令,也可能节省一个寄存器。后置递增,如果为零则递减分支,等等。所有这些都被认为是一个编译器。此时输出不必是汇编语言,我认为这是明智的方式,但它可以是机器码与一些其他的数据,以帮助链接器。如果编译器的设计,使对象被链接后,作为一个步骤,在一个工具链。
所以像gcc这样的编译器,不仅有前端,中间和后端,gcc尤其可以和其他语言共享中间和后端,你可以让它解析java或d语言等,然后在中间进行优化,然后后端到目标,还有一些是单一语言,单一目标,以及介于两者之间的一切。
这很棒,而且对于许多语言来说,它是独立于系统的,gcc将把C转换成asm或对象,独立于你打算使用的操作系统或裸机。当你开始链接东西和你链接的库时,你就进入了目标操作系统。同一个目标,例如x86,不被认为具有相同的系统调用结构,甚至不一定假设使用相同的系统调用机制,例如macos vs windows vs linux。所以你需要一个C库,在前端是通用的每个常见的C库调用,但随着它越来越接近系统,然后它作出系统特定的调用。什么文件格式和规则/属性的文件格式是由操作系统定义的,所以我们知道windows和elf的EXE和linux的其他EXE。即使是相同的目标指令集。
要成功获得gnu工具链(gcc加binutils)和C库(glibc),这样你就可以成功地构建一个命令行程序,有很多移动的部分。当你使用一个预先构建的gnu工具链,例如x86 for windows。它将已经被构建知道首选的文件格式,它将有一个为操作系统系统调用而构建的C库。2与C库相关的链接器脚本及其 Bootstrap 等。
正如在注解中提到的,一些编译器是交叉编译器,或者可以是交叉编译器。例如,编译器二进制本身可以是x86 linux程序,但是输出是arm指令。一些工具链的架构方式是,运行时它们可以使用一个编译器二进制对不同的目标执行if-then-else。llvm就是这样设计的-ish. gnu工具被设计成在编译时,当你编译工具链本身的时候,你选择目标和一个选项列表,然后二进制文件被编译以匹配这些选项。所以如果你想要一个gnu mips C编译器和一个arm C编译器,你需要编译gcc/binutils/glibc两次,并将它们安装到不同的目录。
所以,如果你问编译器,你需要从你想编译的高级语言开始,最终你需要知道目标指令集和操作系统,以及这三者的规则,然后你设计编译器来输出函数代码(决不假设任何两个编译器或编译器版本将从相同的输入生成相同的输出)按照输入语言的规则,以及目标指令集的规则,并且可能不是在编译时,而是作为更多的系统级(库、文件格式等)、文件格式和目标操作系统的系统调用。
将一种语言转换成另一种语言只是成为有用工具的一系列步骤中的第一步。