为什么不能(不能)操作系统直接将C代码翻译成机器语言而不是首先将其翻译成汇编语言?

时间:2012-08-24 20:22:07

标签: c assembly compiler-construction

据我所知,当编译程序(例如用C语言编写)时,首先将其翻译成汇编语言,然后翻译成机器语言。为什么不能(不是)跳过“汇编语言步骤”?

7 个答案:

答案 0 :(得分:6)

您的理解是错误的,编译器不一定将C代码转换为汇编程序。它们通常执行几个阶段并具有内部表示,但这不一定类似于人类可读的汇编程序。

在这里,我找到了LLVM的精彩介绍。 LLVM是用于clang的编译器工具包。

答案 1 :(得分:5)

编译器开发人员更容易。

可以编写一个读取C并编写目标代码的编译器。但是,这需要编译器编写器编写所有编码指令的计算。某些机器上的指令编码错综复杂。此外,还有一些要填写的字段取决于其他交互,例如分支目标的距离,这取决于分支和目标之间的指令。

此外,编写编译器的部分方式是使用类似“增加对象x,发出增量指令”的模式。为了直接编写目标代码,您必须编码所需的所有指令写入这些模式。这意味着你的模式必须有某种语言来描述指令。

好吧,我们已经有了一种语言:汇编语言。因此,以“增加对象x,发出inc x”等方式编写模式会更容易。

现代编译器有很多层。有一个前端读取C文本(或其他语言)并将其转换为编译器内部的语言。有一个优化器可以对内部语言(或其表示)进行操作,并尝试改进代码。有一个后端将内部语言转换为汇编语言。有一个汇编程序将程序集转换为目标代码。并且有一个链接器将对象代码链接到可执行文件中。

与许多复杂的任务一样,当人类思维被分成很好的部分时,它可以更容易地处理复杂的任务。这可以减少错误并缩短使用软件所需的时间。它还使软件变得灵活,因为我们可以更改前端以支持新语言(例如,Java而不是C)或更改后端以支持新处理器(从Intel组件更改为PowerPC组件)。更改一个优化器可以改进所有编译器,包括Java和C以及Intel和PowerPC。

我们用于编译的gcc命令实际上只是一个驱动程序,它调用执行前端处理,优化,程序集和链接的其他程序。您也可以单独调用大部分这些阶段,或使用开关告诉gcc向您显示它正在使用的命令。

此外,GCC还具有一项功能,允许开发人员直接插入与C代码混合的汇编语言。这迫使GCC包括汇编程序。

答案 2 :(得分:2)

操作系统不会做那样的事情。这是编译器的工作。事实上,许多直接发出目标文件 - 你必须明确要求它们发出汇编代码。其他人选择不这样做,因为发出功能齐全的目标文件需要有关此存在的各种格式的专业知识。汇编程序具有各种便利功能,使工作更轻松,可以(有时?)以多个目标文件格式为目标,而无需更改汇编代码。此外,它是一个非常有用的功能来发出带注释的汇编代码,因此没有单独的代码生成器仅用于直接对象文件发送节省您的时间没有任何限制(除了需要汇编程序),这使它成为一个有吸引力的选择当你有限资源。

答案 3 :(得分:1)

取决于编译器;实际上并不需要汇编代码。

也许你所谈论的任何编译器的作者(GNU-CC?)认为如果他们不必解决像分支本身这样的某些事情,那对他们来说会更容易。

答案 4 :(得分:1)

汇编代码纯粹是一种方便的,有点人类可读的机器代码表示链接器在汇总不同翻译单元的输出时所需的符号引用和重定位。如果没有中间汇编语言步骤,编译器也将负责以链接器所需的形式生成重定位,这是可行的,但很痛苦。由于已经存在具有此功能的汇编程序来处理手写汇编代码,因此使用它是有意义的。

答案 5 :(得分:1)

通常没有汇编阶段。 MSVC(cl.exe)和GCC立即生成机器代码(.obj,.o)。

答案 6 :(得分:1)

交叉编译器可以在没有安装交叉编译器的操作系统的帮助下直接生成机器代码。

例如,安装在windows中的tornado软件包可以为vxworks生成机器代码。