XCode 中汇编和反汇编的区别
Difference between assembly and disassembly in XCode
如果这是一个幼稚的问题,我深表歉意,但我想知道 XCode 能够生成的“Disassembly”和“Assembly”之间有什么区别。程序集是:
和“反汇编”:
我想不同之处在于 Assembly 包含一些调试和 Dwarf 信息,而 Disassembly 去除了所有符号并从(我认为?)可执行文件生成,没有打开任何调试。这是准确的,还是有什么不同?调试程序时,如果两者都可以访问,通常会查看什么?
Assembly 是编译器的文本输出(来自 clang -S
),并将包含标签而不是数字分支目标。反汇编只能为任何构成符号 table.
的东西提供符号名称
clang 的 -S
输出使用 asm 注释,例如用于 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 名称作为注释添加到每条指令中,但 clang -fverbose-asm
几乎没有做任何事情。
.loc
是调试元数据,C/C++ 源行号。
.cfi_*
是回溯信息(调用框架信息),它将在 .eh_frame
部分结束。
对于 perf 调整/查看某些东西是如何编译的,我通常更喜欢编译器 asm 输出,而不是反汇编,但过滤掉了 CFI 和 .loc 指令等噪音 ()。查看分支目标上的标签,以便您知道何时可以从其他地方跳转到某个位置,这对于注意循环顶部非常有用。 (一些反汇编程序,如 Agner Fog 的 objconv
可以反汇编为准备好重新汇编的源代码,并使用编译器使用的自动编号标签名称。)
如果您使用 link 时间优化,最好查看它以获得跨文件内联后的真实情况,因为它与通常的代码生成不同 -S -O3
输出。这可能意味着反汇编二进制文件,除非您的工具可以要求 link-time 优化器打印 asm 文本。
对于实际调试,像 GDB 这样的调试器让您可以选择使用带有 C 代码和行号的源代码级调试,并使用调试信息将 C 名称与寄存器或内存位置相关联。通常你会使用它,但如果你想检查逻辑以查看它是否按你期望的方式编译,大多数调试器可以很容易地在反汇编视图中按指令单步执行。 (例如,有时您会注意到您使用了错误的变量名,因为一堆东西被优化掉了,而且 asm 比您预期的要简单得多。或者您的分支条件实际上是在检查 or
(|
) 而不是短路逻辑 ||
.)
在复杂的代码中,反汇编视图中的单步执行是查看其在做什么的好方法,至少可以找到主循环或特定输入所采用的执行路径。
-S
编译器生成的 asm 文本在调试时通常不可用。除非您要求,否则 Clang 根本不会生成它。 (GCC 总是生成一个 .s
并在其上运行 as
,与 cc1
C->asm 编译器分开,如果你问可以保存它)。但是运行程序中没有元数据将代码地址与.s
asm行关联起来,所以在真正调试时并不容易使用。
如果这是一个幼稚的问题,我深表歉意,但我想知道 XCode 能够生成的“Disassembly”和“Assembly”之间有什么区别。程序集是:
和“反汇编”:
我想不同之处在于 Assembly 包含一些调试和 Dwarf 信息,而 Disassembly 去除了所有符号并从(我认为?)可执行文件生成,没有打开任何调试。这是准确的,还是有什么不同?调试程序时,如果两者都可以访问,通常会查看什么?
Assembly 是编译器的文本输出(来自 clang -S
),并将包含标签而不是数字分支目标。反汇编只能为任何构成符号 table.
clang 的 -S
输出使用 asm 注释,例如用于 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 名称作为注释添加到每条指令中,但 clang -fverbose-asm
几乎没有做任何事情。
.loc
是调试元数据,C/C++ 源行号。
.cfi_*
是回溯信息(调用框架信息),它将在 .eh_frame
部分结束。
对于 perf 调整/查看某些东西是如何编译的,我通常更喜欢编译器 asm 输出,而不是反汇编,但过滤掉了 CFI 和 .loc 指令等噪音 (objconv
可以反汇编为准备好重新汇编的源代码,并使用编译器使用的自动编号标签名称。)
如果您使用 link 时间优化,最好查看它以获得跨文件内联后的真实情况,因为它与通常的代码生成不同 -S -O3
输出。这可能意味着反汇编二进制文件,除非您的工具可以要求 link-time 优化器打印 asm 文本。
对于实际调试,像 GDB 这样的调试器让您可以选择使用带有 C 代码和行号的源代码级调试,并使用调试信息将 C 名称与寄存器或内存位置相关联。通常你会使用它,但如果你想检查逻辑以查看它是否按你期望的方式编译,大多数调试器可以很容易地在反汇编视图中按指令单步执行。 (例如,有时您会注意到您使用了错误的变量名,因为一堆东西被优化掉了,而且 asm 比您预期的要简单得多。或者您的分支条件实际上是在检查 or
(|
) 而不是短路逻辑 ||
.)
在复杂的代码中,反汇编视图中的单步执行是查看其在做什么的好方法,至少可以找到主循环或特定输入所采用的执行路径。
-S
编译器生成的 asm 文本在调试时通常不可用。除非您要求,否则 Clang 根本不会生成它。 (GCC 总是生成一个 .s
并在其上运行 as
,与 cc1
C->asm 编译器分开,如果你问可以保存它)。但是运行程序中没有元数据将代码地址与.s
asm行关联起来,所以在真正调试时并不容易使用。