【问题标题】:Difference between assembly and disassembly in XCodeXCode中汇编和反汇编的区别
【发布时间】:2021-04-14 18:44:54
【问题描述】:

如果这是一个幼稚的问题,我深表歉意,但我想知道 XCode 能够生成的“反汇编”和“汇编”之间有什么区别。大会是:

还有“反汇编”:

我想不同之处在于,Assembly 包含一些调试和 Dwarf 信息,而 Disassembly 被剥离了所有符号并从(我认为?)可执行文件生成而没有打开任何调试。这是准确的,还是可能有什么不同?调试程序时,如果您可以同时访问两者,通常会查看什么?

【问题讨论】:

    标签: c xcode assembly disassembly


    【解决方案1】:

    Assembly 是编译器的文本输出(来自clang -S),将包含标签而不是数字分支目标。反汇编只能为您提供任何进入符号表的符号名称。

    clang 的 -S 输出使用 asm cmets,例如用于 SIMD 洗牌指令。对于 FP 位模式,它显示了表示的值:https://godbolt.org/z/efz1fq 显示了 float f = 1.25; 如何使用 clang 为 x86-64 编译(去除一堆“明显”且不太有趣的指令,如 .section .data)

    f:
            .long   0x3fa00000                      # float 1.25
    

    gcc -fverbose-asm 将操作数的 C 名称作为 cmets 添加到每条指令中,但 clang -fverbose-asm 并没有做太多事情。

    .loc 是调试元数据,C/C++ 源代码行号。 .cfi_* 是回溯信息(调用帧信息),最终会出现在 .eh_frame 部分中。


    对于性能调优/查看某些东西是如何编译的,我通常更喜欢编译器 asm 输出,而不是反汇编,而是过滤掉 CFI 和 .loc 指令等噪音 (How to remove "noise" from GCC/clang assembly output?)。查看分支目标上的标签,以便您知道何时可以从其他地方跳转到某个位置,这对于注意循环的顶部非常有用。 (像 Agner Fog 的 objconv 这样的一些反汇编程序可以反汇编成可以重新组装的源代码,并带有编译器使用的自动编号标签名称。)

    如果您使用链接时优化,最好在跨文件内联后查看它以获得真实情况,因为它与通常的-S -O3 输出不同的代码生成。这可能意味着反汇编二进制文件,除非您的工具可以要求链接时优化器打印 asm 文本。

    对于实际调试,像 GDB 这样的调试器让您可以选择使用 C 代码和行号进行源代码级调试,并使用调试信息将 C 名称与寄存器或内存位置相关联。通常你会使用它,但如果你想健全地检查逻辑以查看它是否按照你期望的方式编译,大多数调试器都可以轻松地在反汇编视图中单步执行指令。 (例如,有时你会注意到你使用了错误的变量名,因为一堆东西被优化掉了,而且 asm 比你预期的要简单得多。或者你的分支条件实际上是检查 or (|) 而不是短-电路逻辑||.)

    在复杂代码中,反汇编视图中的单步执行是查看其正在做什么的好方法,至少可以找到主循环或特定输入所采用的执行路径。

    -S 编译器生成的 asm 文本在调试时通常不可用。除非您要求,否则 Clang 根本不会生成它。 (GCC 总是生成一个.s 并在其上运行as,与cc1 C->asm 编译器分开,如果您询问可以保存)。但是没有元数据将运行程序中的代码地址与.s asm 行关联起来,所以在真正调试的时候并不好用。

    【讨论】:

      猜你喜欢
      • 2019-04-15
      • 2011-05-20
      • 1970-01-01
      • 2016-10-11
      • 2013-11-12
      • 2019-01-07
      • 2014-01-21
      • 2020-03-03
      相关资源
      最近更新 更多