[英]Computer architecture and compiler
基于我对以下假设的理解,我有一个疑问,1.对于每个 CPU 体系结构,汇编语言集都会有所不同。
所以,我怀疑通用编译器/解释器如何将其转换为 .asm 代码,因为并非所有计算机都具有相同的体系结构!
对此的回答我猜想“当我们在我们的系统本身中安装编译器时,它会了解它正在安装的计算机体系结构,因此它将 C++/python/java 转换为相应的 CPU.asm 代码”
所以,如果我上面的猜测是正确的,那么我就明白,当他们设计编译器时,开发人员需要将所有 CPU 架构的汇编集集成到编译器中。
注意:我的怀疑是愚蠢的,我从未参加过任何编译器课程,是 ECE 毕业生。 提前致谢;p
汇编语言不一定是你需要关注的地方。
每个处理器都有一个体系结构,特别包括指令集。 想想指令集,机器代码,而不是汇编语言,因为对于同一体系结构,有无数不兼容的汇编语言的例子。 归根结底,您需要机器代码和说明。
编译器至少有一个输入和一个 output,例如 C 编译器可能会将 C 转换为 asm,或者可能会将 C 转换为机器代码。 或者它可能将 C 转换为 java 字节码或其他一些字节码。 语言在这里是一个大问题,有趣的是 C 很难标准化并且与实现定义的项目一起打包,实际上正在融合 pyton,rust 等由于某种原因随着时间的推移而变化/分歧。 无论如何,您有各种编译器和各种目标。 这当然是我想从理想的高级语言到低级语言的情况。 但是您可能拥有一个从一开始就为一个目标 (isa) 设计的编译器,并且从前到后旨在针对该目标优化其 output。 像 gcc 这样的其他人可能是从哪里开始的,我不知道,但现在基本上是前面、中间和后面。 前面本质上是解析要编译的语言,例如C。 它通常会变成一些内部代码或数据结构,添加两个变量并存储在第三个变量中可能会变成三个变量分配步骤,每个步骤都有一定的大小,然后操作得到这个操作数,得到那个操作数,然后将它们相加,然后存储结果。 很像把高级变成汇编语言。 通常,大部分优化发生在您拥有这些通用操作的这一层。 然后你有你的后端,将这个中间代码/数据转换为目标特定代码。 理想情况下是一些优化,有时你会听到窥孔优化器这个术语,程序集通常不会被优化,这会导致严重的问题,但编译后的代码,通常仍然可以获得一些特定于目标的优化。 一些指令集可以使用立即数添加小数字,其他指令集可能需要将立即数加载到寄存器中然后执行操作,因此如果将那个小数字优化到操作中,则可以保存指令和可能的寄存器。 后递增,如果为零则递减分支等等。所有这些都被认为是一个编译器。 此时的 output 不一定是汇编语言,imo 这是理智的方式,但是,它可以是机器代码和一些其他数据来帮助 linker。如果编译器被设计为使对象稍后链接为一个步骤在工具链中。
所以像gcc这样的编译器,不仅有前中后,特别是gcc可以和其他语言共享中后你可以让它解析java或d语言等,然后在中间优化然后后端到目标。 而其他人则是单一语言、单一目标,以及介于两者之间的一切。
这一切都很棒,对于许多语言来说,它是系统独立的,gcc 将采用 C 并将其转换为 asm 或对象,与您打算使用的操作系统或裸机无关。 当您开始链接事物以及您链接的库时,您就会进入目标操作系统。 相同的目标,例如 x86,不假定具有相同的系统调用结构,甚至不一定假定使用相同的系统调用机制,例如 macos vs windows vs linux。 因此,您需要一个 C 库,该库在前端根据常见的 C 库调用是通用的,但随着它越来越接近系统,它会进行系统特定的调用。 什么文件格式和该文件格式的规则/属性由操作系统定义,所以我们知道 windows 的 EXE 和 linux 的 elf 和其他文件。即使目标指令集相同。
要成功获得 gnu 工具链(gcc 加 binutils)和 C 库 (glibc),以便您可以成功构建 COMMAND LINE 程序,有很多活动部件。 当您使用预构建的 gnu 工具链时,例如 x86 和 windows。它将被构建为知道首选文件格式,它将有一个为操作系统系统调用构建的 c 库。 Linker 与 C 库及其引导程序等相关的脚本。
正如评论中提到的,一些编译器是交叉编译器或者可以是。 例如,编译器二进制文件本身可以是 x86 linux 程序,但 output 是 arm 指令。 一些工具链的架构方式是运行时它们可以通过 if-then-else 方式使用一个编译器二进制文件到达各种目标。 llvm 就是这样设计的。 gnu 工具被设计为在编译时,即编译工具链本身时,您选择目标和一长串选项,然后构建二进制文件以匹配这些选项。 所以如果你想要一个 gnu mips C 编译器和一个 arm C 编译器你需要构建 gcc/binutils/glibc 两次并将它们安装到不同的目录。
所以是的,如果你问的是编译器,你需要从你想要编译的高级语言开始,最终你需要知道目标指令集和操作系统以及这三者的规则。 然后根据输入语言的规则和目标指令集的规则,将编译器构建为 output 功能代码(永远不要假设任何两个编译器或编译器版本将从相同的输入生成相同的 output),并且可能不在编译时时间,但更多的是系统级别(库、文件格式等)文件格式和目标操作系统的系统调用。
将一种语言转换为另一种语言只是获得有用工具的一系列步骤中的第一步。
问题未解决?试试以下方法:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.