关于编译器和汇编器的一些问题

时间:2012-11-06 09:12:09

标签: assembly compiler-construction machine-code object-code

我脑子里有很多基本问题。我需要清除它们。

声明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: java编译器目标文件是否创建了* .class(字节码)文件?如果是,那么我们可以说运行它们的JVM是一种链接器(但是它没有创建可执行文件)吗?

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

问题1:是的,汇编程序(as,gas,nasm,masm)将汇编指令编译为目标代码。对于高级语言(H),编译器将H编译为另一种语言(例如GHC,Glorious Haskell编译器可以生成C,但它也可以生成C--,并且有一个尝试(?)生成Java),或通过中间步骤(或语言C--或Core)进入目标代码。

可以生成中间代码有很多原因: 1.可移植性,例如java的.class文件,Pascal的p代码 2.促进代码优化

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

问题3:Turbo C ++ .obj文件(在64位intel上编译)在Z80机器上不高兴,除非编译器可以选择交叉编译另一种架构,所以在Turbo C ++的情况下目标文件不是跨平台的可移植性。

相关问题