【发布时间】:2018-02-22 09:28:14
【问题描述】:
据我所知,编译器会将源代码转换为机器代码。但是这段代码没有任何与操作系统相关的部分,链接器将它们添加到文件中。
但是是否有可能在没有链接器的情况下制作一些可执行文件?
【问题讨论】:
据我所知,编译器会将源代码转换为机器代码。但是这段代码没有任何与操作系统相关的部分,链接器将它们添加到文件中。
但是是否有可能在没有链接器的情况下制作一些可执行文件?
【问题讨论】:
从字面上回答您的问题 - 是的,可以在没有链接器的情况下制作执行文件:您不需要编译器或链接器来生成机器代码。二进制文件是一系列操作码和相关信息(偏移量、地址等)。如果你打开一个二进制编辑器,然后输入一些操作码并制作一个程序。保存并运行它。
当然,二进制文件将是特定于处理器的,就像您编译了一个二进制(本机)执行程序一样。这是对 Intel x86 操作码的参考。 http://ref.x86asm.net/coder32.html.
但是,如果您问“我可以在没有链接器的情况下将源文件直接编译成执行文件吗?”然后纯粹地说:不 - 除非编译器具有集成在其中的链接器的各个方面。编译器生成中间对象,这些对象传递给链接器以将它们“链接”到二进制文件中,例如库或执行程序。没有链接步骤,管道是不完整的。
【讨论】:
让我们首先做一个被认为是真实的声明,编译器不会生成可以立即执行的机器代码(JIT 可以,但我们忽略它)。
相反,它们生成文件(对象、静态、动态、可执行文件)来描述它们包含的内容以及符号组。符号可以是全局变量或函数。
但是符号就像文件本身一样包含元数据。这个元数据非常重要。看到存储在符号中的机器代码是目标架构的原始指令,但它不知道内存存储在哪里。
虽然现代 CPU 为每个进程提供了自己的地址空间,但一个符号可能不会出现,也可能不会两次出现在同一个地址中。在最近,这是一种安全措施,但在过去,动态链接可以正常工作。
因此,当操作系统加载可执行文件或共享库时,它可以将其放置在任何它想要的位置,并通过这样做使其不可重复。否则我们都必须开始关心并说“这个文件包含我打算执行的 100% 的代码”。通常在加载符号表中的原始二进制文件时,通过使用 RAM 中的符号位置对其进行修补来进行转换。让一切正常工作。
总而言之,编译器会发出允许动态修补程序集的文件 在执行之前。如果不是这样,我们将生活在一个非常限制和有问题的世界中。
链接器甚至有脚本来改变它们的操作方式。它们是使我们的程序正常运行所需的非常复杂和精致的软件。
如果您想了解这些格式的真正复杂程度,请阅读 PE-COFF 和 ELF 标准。
【讨论】: