【问题标题】:Why doesn't (can't) the OS translate C code directly into machine language instead first translating it into assembly language?为什么操作系统不(不能)将 C 代码直接翻译成机器语言,而是先将其翻译成汇编语言?
【发布时间】:2012-08-24 20:22:06
【问题描述】:

据我了解,当一个程序(例如用 C 编写的)被编译时,它首先被翻译成汇编语言,然后被翻译成机器语言。为什么不能(不是)跳过“汇编语言步骤”?

【问题讨论】:

  • 它有什么好处?那能解决什么问题? (而且我敢肯定,有些编译器会直接使用机器代码。操作系统与这些无关。)
  • 所以你是说C代码背后没有汇编语言?那怎么跑得比 C 快呢?
  • 许多编译器跳过了文本汇编阶段..
  • C 和汇编语言均未执行。两者都必须先翻译成机器代码才能执行。将 C 直接翻译成机器代码与翻译成汇编语言然后再翻译成机器代码应该不会影响执行速度。

标签: c assembly compiler-construction


【解决方案1】:

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

在这里,我找到了LLVM 的一个很好的介绍。 LLVM 是用于 clang 的编译器工具包。

【讨论】:

    【解决方案2】:

    对编译器开发人员来说更容易。

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

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

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

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

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

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

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

    【讨论】:

    • 我认为这更多是因为开源 C 编译器中的历史原因,并且可能有点懒惰(同时拥有一个体面的机器代码编写器以提高速度和一个单独的文本汇编编写器以便于检查输出) .
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      也许您所谈论的任何编译器(GNU-CC?)的作者认为,如果他们不必自己解决某些问题(例如分支),对他们自己来说会稍微容易一些。

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

          • 实际上,GCC 总是生成程序集,但它可能只存在于内存中(通过管道传输到汇编器中,而不是使用临时文件)。用-v 编译一个文件,你会看到它确实调用了as
          【解决方案7】:

          交叉编译器可以直接生成机器码,无需安装交叉编译器的操作系统的帮助。

          例如windows中安装的tornado包可以为vxworks生成机器码。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-06-19
            • 1970-01-01
            • 2014-11-04
            • 2011-01-04
            • 1970-01-01
            相关资源
            最近更新 更多