【问题标题】:Assembly versus binary output汇编与二进制输出
【发布时间】:2010-01-04 13:42:23
【问题描述】:

编译器是把代码编译成汇编语言更好,还是直接输出二进制机器码更好?

我能想到的汇编语言的优点:无需学习目标文件格式,易于调试后端。

二进制的优点:编译速度更快。这有多重要?假设使用了 Gnu 汇编器(除了其他任何东西,可以合理地假设它在大多数机器上都可用),是否需要大量时间来汇编一百万行代码?

汇编器会隐藏的各种操作系统之间的目标文件格式是否存在差异?

还有没有其他我没有想到的优势?

【问题讨论】:

  • GNU 汇编器一次性工作。它与生成的二进制文件的大小成线性关系。除非你的编译器是非常基础的并且根本没有进行困难的优化,否则 GNU 汇编器所花费的时间在总编译时间中可以忽略不计。

标签: compiler-construction assembly code-generation


【解决方案1】:

Assembly 更容易输出,并且具有人类可读的优点。 至于编译时间,以下是我编译器的一些统计数据:

[~/ecc/ellcc/ecc/Main] main% ../../bin/x86-elf-ecc test/sieve.c -time-actions
===-------------------------------------------------------------------------===
                   ... Ellcc action timing report ...
===-------------------------------------------------------------------------===
Total Execution Time: 2.9006 seconds (2.9857 wall clock)

---User Time---   --System Time--   --User+System--   ---Wall Time---  --- Name ---
2.0397 ( 71.3%)   0.0250 ( 65.8%)   2.0647 ( 71.2%)   2.1174 ( 70.9%)  Bitcode linking
0.7999 ( 27.9%)   0.0070 ( 18.4%)   0.8069 ( 27.8%)   0.8111 ( 27.2%)  Generating
0.0000 (  0.0%)   0.0010 (  2.6%)   0.0010 (  0.0%)   0.0274 (  0.9%)  Assembly
0.0110 (  0.4%)   0.0030 (  7.9%)   0.0140 (  0.5%)   0.0143 (  0.5%)  LLVM generation
0.0070 (  0.2%)   0.0000 (  0.0%)   0.0070 (  0.2%)   0.0066 (  0.2%)  Type checking
0.0000 (  0.0%)   0.0020 (  5.3%)   0.0020 (  0.1%)   0.0041 (  0.1%)  Linking
0.0030 (  0.1%)   0.0000 (  0.0%)   0.0030 (  0.1%)   0.0031 (  0.1%)  Optimization
0.0010 (  0.0%)   0.0000 (  0.0%)   0.0010 (  0.0%)   0.0010 (  0.0%)  Elaboration
0.0010 (  0.0%)   0.0000 (  0.0%)   0.0010 (  0.0%)   0.0004 (  0.0%)  Integrity checking
0.0000 (  0.0%)   0.0000 (  0.0%)   0.0000 (  0.0%)   0.0004 (  0.0%)  Parsing
2.8626 (100.0%)   0.0380 (100.0%)   2.9006 (100.0%)   2.9857 (100.0%)  TOTAL

[~/ecc/ellcc/ecc/Main] main%

正如您所见,链接和代码生成使汇编时间相形见绌。此示例编译并链接一个小的 main() 以及标准库,所有这些都采用 LLVM 中间形式。然后为整个程序生成一个汇编语言文件。该文件使用链接器链接(实际上是重新定位),链接器会创建 a.out 文件。

【讨论】:

    【解决方案2】:

    汇编的另一个优点:能够为跳转、循环、分支和函数调用使用标签,因此您无需手动计算内存地址。

    【讨论】:

      【解决方案3】:

      如果你生成汇编代码,那么你会结束

      • 将该代码写入磁盘,汇编器必须读取它;
      • 调用汇编器,即启动一个新进程。

      汇编器本身运行很快,但文件 I/O 需要一两分钟。一百万行?也许5秒。启动汇编程序将需要 100 到 1000 毫秒。没什么大不了的。

      我认为更容易调试和消除对对象格式的需要将很容易弥补稍长的编译时间。

      【讨论】:

        【解决方案4】:

        直接生成二进制文件的主要优点是您可以将代码直接喷射到内存中,刷新 I-cache,然后分支到它。这意味着您可以使用本机代码编译器创建一个很好的交互式循环。一个不错的功能,在Standard ML of New Jersey 编译器中部署了 20 多年。

        【讨论】:

          【解决方案5】:

          汇编器会隐藏的各种操作系统之间的目标文件格式是否存在差异?

          是的,即使在同一个操作系统上,您也可以有多种目标文件格式。 (例如,MASM 可以生成例如 OMF 或 COFF 对象格式以供不同的链接器使用。)

          有关不同目标文件格式的更多信息,请参见 this document.

          【讨论】:

            【解决方案6】:

            您可以尝试为您的代码生成程序集需要多长时间:

            gcc -O2 -S -c foo.c
            

            【讨论】:

              猜你喜欢
              • 2017-05-18
              • 1970-01-01
              • 2023-01-12
              • 2015-05-29
              • 1970-01-01
              • 2014-08-08
              • 2011-08-06
              • 1970-01-01
              • 2016-01-10
              相关资源
              最近更新 更多