2012-02-11 71 views
8

我知道这是一个非常基本的问题,但是当我编译我的C/C++代码与GCC/G ++究竟是中间的输出类型汇编进场之前生成机器码?是不是像X86指令?GCC/G ++输出型

+2

你的意思是什么_intermediate_输出? 'g ++'直接生成程序集。 – Lol4t0 2012-02-11 20:58:35

+0

以下选项可能会有用:'-g -Wa,-ahl = main.s'。它们导致GCC/G ++发出具有交错高级源代码的程序集。 – 2012-02-11 21:16:29

+0

这根本不是一个基本的问题。 – cha0site 2012-02-11 21:23:33

回答

12

GCC的处理链如下:

  • 源代码

  • 预处理源代码(扩展宏并包含条注释)(-E,.ii

  • 编译为程序集(-S.s

  • 组装成二进制(-c.o

  • 链接到可执行

在每一个阶段我已经列出了相关的编译器标志,使流程停在那里以及相应的文件后缀。

如果使用-flto进行编译,则将使用GIMPLE字节码来修饰目标文件,GIMPLE字节码是一种低级别中间格式,其目的是将实际的最终编译延迟到链接阶段,从而允许链接时间优化。

的“编译”的阶段适当的是实际的繁重的一部分。预处理器本质上是一个独立的独立工具(虽然它的行为是由C和C++标准规定的),汇编器和连接器是非常独立的独立工具,它们基本上分别实现硬件的二进制指令格式和操作系统的可加载可执行格式。

+0

+1,优秀的答案。你可能想要添加一个关于什么程序集的blurb,因为看起来提问者并不完全清楚。 – cha0site 2012-02-11 21:24:47

+0

@ cha0site:谢谢...让我们来看看; OP欢迎澄清,在这种情况下,我很乐意扩大。 – 2012-02-11 21:25:54

+0

@KerrekSB非常感谢您的详细解答,我想我现在明白了。下面的ZarakiKenpachi回答也很有帮助。所以我猜gcc在生成程序集之前获取有关我的硬件的信息,或者每种类型的硬件都有单独的编译器? – Cemre 2012-02-11 21:30:17

0

它必须是汇编代码。您可以在命令行中使用-S标志进行编译。

0

没有“中间输出”。你得到的第一个输出是机器码。 (虽然可以通过调用预处理器与-E得到C/C++中间输出。)

4

所以,在GCC可执行的汇编由4个部分组成:

1)预处理(GCC -E的main.c> main.i;变换的* .c为* .I) 是否包括扩展,处理马科斯。删除评论。编译(gcc -S main.i;如果成功,将* .i转换为* .s) 将C代码编译为汇编器(在目标x86架构上,它是x86汇编,在目标x86_64架构上这是x64的组件,目标ARM架构是臂组件等) 这一部分中的大多数警告和错误的发生(如没有错误和警告报告)

3)装配(如main.s - o main.o;如果成功,则再次将* .i转换为* .o) 汇编生成汇编到机器码。虽然还有程序的相对地址,诸如此类。

4.)链接(gcc main。o) 用绝对地址替换相对地址。删除无用的文本。 在此阶段链接错误和警告。 最后(如果成功),我们得到可执行文件。

所以,要回答你的问题,你所说的中间输出实际上就是所谓的汇编语言 - 关于Assembly language wiki请参阅维基。

+0

非常感谢您的详细解答。这非常有帮助。 – Cemre 2012-02-11 21:41:29

+0

第3步应阅读“...将* .s转换为* .o”? – nickgrim 2012-02-12 00:23:18

0

GCC工具链,将程序从源代码编译到机器码。编译器生成汇编程序汇编到机器代码中的汇编代码。 Here是初学者的好教程。

2

这里是由redhat magazine礼貌的GCC编译步骤的图形表示:

gcc compilation steps

相反,意味着什么其他的答案,也没有装配步骤 - 相反,生成汇编代码替换目标代码的生成;如果您真正想要的是二进制表示,将内存中表示转换为文本表示并没有什么意义。

+0

嗯,是的,如果你打算编写目标代码,生成助记符是没有什么意义的,这些助记符是供人阅读的。但是助记符与对象代码几乎是1:1,并且汇编器的代码生成部分已完成(计算跳转地址,诸如此类)。 – cha0site 2012-02-11 22:00:53