Aqu*_*irl 6 compiler-construction assembly gcc
来自C++中的思考 - 第1卷:
在第二遍中,代码生成器遍历解析树并为树的节点生成汇编语言代码或机器代码.
至少在GCC中,如果我们给出生成汇编代码的选项,编译器会通过创建包含汇编代码的文件来服从.但是,当我们只是在gcc没有任何选项的情况下运行命令时,它是否在内部不生成汇编代码?
如果是,那么为什么需要首先生成汇编代码然后将其转换为机器语言?
Pet*_*des 12
TL:DR 不同的目标文件格式/更容易移植到新的 Unix 平台(历史上)是 gcc 将汇编器与编译器分开的主要原因之一,我认为。 在 gcc 之外,主流的 x86 C 和 C++ 编译器(clang/LLVM、MSVC、ICC)直接进入机器代码,如果你要求他们可以选择打印 asm 文本。
LLVM 和 MSVC 带有完整的工具链,而不仅仅是编译器。(还带有汇编器和链接器)。LLVM 已经将对象文件处理作为库函数,因此它可以使用它而不是写出 asm 文本来提供给单独的程序。
较小的项目通常选择将目标文件格式的详细信息留给汇编程序。例如,FreePascal 可以直接进入它的一些目标平台上的目标文件,否则只能进入 asm。有很多说法(1、2、3、4)几乎所有的编译器都通过 asm 文本,但对于许多最大的、使用最广泛的编译器(GCC 除外)来说,情况并非如此,这些编译器有很多开发人员在研究它们。
C 编译器倾向于仅针对单个平台(如供应商的微控制器编译器)并被编写为“该平台的 C 实现”,或者是非常大的项目,如 LLVM,其中包括机器代码生成不是编译器自身代码大小的很大一部分。不太广泛使用的语言的编译器通常更易于移植,但不想编写自己的机器代码/目标文件处理。(如今许多编译器都是 LLVM 的前端,因此可以.o免费获得输出,例如rustc,但较旧的编译器没有该选项。)
在所有编译器中,大多数都使用 asm。但是,如果您按每个人每天使用的频率进行加权,那么直接进入可重定位的目标文件 ( .o/ .obj) 是全球任何一天完成的总构建的重要组成部分。即,如果您正在阅读本文,您关心的编译器可能会以这种方式工作。
此外,像javac这样的目标是可移植字节码格式的编译器没有理由使用 asm;相同的输出文件和字节码格式适用于它们必须运行的每个平台。
有关的:
as独立优势的其他答案。.o或.obj)。除了tcc,Tiny C Compiler,旨在即时用于单文件 C 程序。是的,as是一个单独的程序,gcc前端实际上与cc1(生成文本 asm 的 C 预处理器+编译器)分开运行。
这使得 gcc 稍微更加模块化,使编译器本身成为一个文本 -> 文本程序。
GCC 在内部使用一些二进制数据结构来表示 GIMPLE 和 RTL 内部表示,但它不会将这些 IR 格式(的文本表示)写入文件,除非您使用特殊选项进行调试。
那么为什么要停止组装呢?这意味着 GCC 不需要知道同一目标的不同目标文件格式。 例如,不同的 x86-64 操作系统使用 ELF、PE/COFF、MachO64 目标文件,以及历史上的 a.out。 as将相同的文本 asm 组装成相同的机器代码,由不同目标上的不同目标文件元数据包围。(gcc 需要了解一些细微的差异,例如是否在_符号名称前加上 an ,是否可以使用 32 位绝对地址,以及代码是否必须是 PIC。)
任何特定于平台的怪癖都可以留给 GNU binutils as(又名 GAS),或者 gcc 可以使用供应商提供的系统附带的汇编程序。
从历史上看,有许多不同的 Unix 系统具有不同的 CPU,或者特别是相同的 CPU,但它们的目标文件格式不同。更重要的是,相当兼容一套汇编指令的喜欢.globl main,.asciiz "Hello World!\n"和类似。GAS 语法来自 Unix 汇编程序。
过去确实可以将 GCC移植到新的 Unix 平台上,而无需移植as,只需使用操作系统附带的汇编程序即可。
没有人开始将汇编程序作为库集成到 GCC 的cc1编译器中。这是为 C 预处理器完成的(历史上也是在单独的进程中完成的),但没有为汇编器完成。
大多数其他编译器确实直接从编译器生成目标文件,没有文本 asm 临时文件 / 管道。通常是因为编译器仅针对一个或几个目标设计,例如 MSVC 或 ICC 或各种最初仅用于 x86 的编译器,或许多供应商提供的用于嵌入式芯片的编译器。
clang/LLVM 的设计时间比 GCC 新得多。它被设计为一个优化的 JIT 后端,所以它需要一个内置的汇编程序来快速生成机器代码。要作为提前编译器工作,添加对不同目标文件格式的支持大概是一件小事,因为内部软件架构是直接使用二进制机器代码的。
LLVM 当然在寻找特定于后端的优化之前在内部使用 LLVM-IR 进行目标无关的优化,但同样,如果您要求,它只会将此格式作为文本写出。
| 归档时间: |
|
| 查看次数: |
2604 次 |
| 最近记录: |