1

很多基本的问题都在我的脑海里。我需要清除它们。

语句 1:编译器将人类可读的代码转换为目标代码,然后通过链接器将这些代码转换为机器代码(可执行文件)。

我在这里吗?

wikipedia上,它是这样写的

Object files are produced by an assembler, compiler, or other language
translator, and used as input to the linker.

问题 1:汇编程序将汇编语言代码 ( MOV A, B ADD C) 转换为机器代码。对于像 C++ 这样的高级语言,它是由上面的链接器生成的。所以汇编程序不在任何地方使用。那么它如何创建一个上面写的目标文件呢?

生成中间代码以使代码在不同的架构上运行。

问题 2: *.class(字节码)文件是由 java 编译器目标文件创建的吗?如果是,那么我们可以说运行它们的 JVM 是一种链接器(但是它不创建可执行文件)?

问题 3:当我们在 Turbo C++ 中编译 C++ 程序时,我们会得到 *.obj 文件,它们是目标文件。我们可以使用它们在其他架构中生成可执行文件吗?

4

2 回答 2

2

问题 1:是的,汇编程序(as、gas、nasm、masm)将汇编指令编译为目标代码。在高级语言 (H) 的情况下,编译器将 H 编译为另一种语言(例如 GHC,Glorious Haskell 编译器可以生成 C,但它也可以生成 C--,并且尝试(?)生成Java),或通过中间步骤(或语言 C-- 或核心)转换为目标代码。

生成中间代码的原因有很多: 1. 可移植性,例如来自 java 的 .class 文件,用于 Pascal 的 p 代码 2. 便于代码优化

问题 2:java 编译器可以生成 .class 文件,但 Scala 也生成 .class 文件,AspectJ(面向方面​​的风格)也生成 .class 文件。.class 文件不是目标文件,因为它们需要 Java 虚拟机(并且 unix 链接器ld不会将 .class 文件链接到 .o 文件)。原始 JVM 是 .class 文件的解释器,但您也可以即时编译 java。

问题 3:Turbo C++ .obj 文件(在 64 位 intel 上编译)在 Z80 机器上不会令人满意,除非编译器可以选择交叉编译另一个架构,所以对于 Turbo C++,目标文件的用途不是跨平台的可移植性。

于 2012-11-06T09:57:52.157 回答
2

目标文件是要链接的“机器代码”(.text)、初始化数据和符号的集合。

一个有效的目标文件可以只包含数据,例如字节码。

链接器是将一大堆对象映射到虚拟地址空间并解析某些外部符号属于哪个地址的程序。这允许程序的增量开发,因为在调用例如函数 printf 时只需要知道一个接口。链接器将在链接阶段将 printf 的真实地址注入机器代码中。这是通过重定位表完成的。

这部分回答了问题 #3:不能直接使用由另一种架构创建的目标文件。接口方法不一定是二进制兼容的。obj 文件格式也可以不同。但是,如果真的付出努力,可以编写包装器(很可能在汇编中),它可以从 Visual C 调用在 Turbo C 中编译的对象。如果指令集和内存模型等完全不同,仍然可以编写一个仿真器来调用功能。在编写例如视频播放框架时会经常使用这些方法,这些框架可以调用一些仅在 .dll 中提供的传统视频解码器。

当操作系统将可执行文件从磁盘加载到内存或程序与“动态库”链接时,链接也会部分发生。在这些情况下,可以向“printf”注入许多调用,但链接器只调用“存根”,一旦被调用,就会从操作系统加载正确的库并用库函数替换自身。

声明#1 不够正确。编译器和汇编器将人类可读的代码转换为机器代码,尽管一些编译器会产生中间语言来解释(和/或“及时”编译)。在这最后阶段,编译真正意味着它应该做的——编译成机器代码。

Gcc 包含一个汇编器和链接器。可以int main() { printf("HelloW\n");}gcc -S hw.c汇编器(hw.s)编译,这是符号机器码,插入或替换一些行并重新编译为目标代码gcc -c hw.s,最后链接gcc -o hw.exe hw.o

于 2012-11-06T09:36:57.753 回答