jer*_*rgp 1 c x86 assembly clang
我正在查看编译器生成的程序集,并注意到一系列跳转命令,它们仅转到列出的下一个内存地址。我想知道这样做的目的是什么。这是从gcc编译器生成的。我用otool来拆卸。汇编的代码片段在函数列出之前就位于列表的底部,因此我确定它与main函数有关,因为它只是对printf的调用,否则,我无法做出正面或反面的声明它的功能...这里是到完整源的链接:https : //drive.google.com/open?id=1INI3i4ZP7dtJVQ5n4twA6RCG_sdbjVxd
它包含make文件,该程序使用m2k之类的参数将英里数转换为公里数,然后将3英里数转换为公里数,语法为:convert m2k 3。
0000000100000c95 cvtsd2ss %xmm0, %xmm0
0000000100000c99 callq 0x100000ee0
0000000100000c9e leaq 0x2a5(%rip), %rdi
0000000100000ca5 cvtss2sd %xmm0, %xmm0
0000000100000ca9 movb $0x1, %al
0000000100000cab callq 0x100000f0a
0000000100000cb0 movl %eax, -0x38(%rbp)
0000000100000cb3 jmp 0x100000cb8
0000000100000cb8 jmp 0x100000cbd
0000000100000cbd jmp 0x100000cc2
0000000100000cc2 jmp 0x100000cc7
0000000100000cc7 jmp 0x100000ccc
0000000100000ccc jmp 0x100000cd1
0000000100000cd1 jmp 0x100000cd6
0000000100000cd6 jmp 0x100000cdb
0000000100000cdb jmp 0x100000ce0
0000000100000ce0 xorl %eax, %eax
0000000100000ce2 addq $0x40, %rsp
0000000100000ce6 popq %rbp
0000000100000ce7 retq
Run Code Online (Sandbox Code Playgroud)
LLVM / clang-1001.0.46.4在我的MacBook上执行了此操作。
这似乎是在else if不优化的情况下编译chained 的产物。对于代码
if (E == 0) A;
else if (F == 0) B;
else C;
Run Code Online (Sandbox Code Playgroud)
编译器正在生成
<evaluate E into eax>
cmp eax, 0
jne EvalF
<code for A>
jmp EndIfE
EvalF:
<evaluate F into eax>
cmp eax, 0
jne DoC
<code for B>
jmp EndIfF
DoC:
<code for C>
EndIfF: goto EndIfE
EndIfE:
<rest of program>
Run Code Online (Sandbox Code Playgroud)
因此,这里有一个无用的跳转。使用更多链接的ifs,您将获得更多相同的无用跳转。
几乎可以肯定会发生这种情况,因为代码生成器创建了一个空的基本块数据结构来表示在每个代码之后运行的代码if else。对于单个单个if else基本块,最终将用语句完成后运行的代码填充。但是,当if elses链接时,只有最外面的块包含可执行代码。其余的保持为空。
空的基本块被编译成jmp指令是很自然的,因为每个基本块都以到另一个基本块的分支结尾。(实际上,这是定义的一部分。)jmp进入基本块的过程恰好最终被编译到紧随其后的地址,但是早期代码生成通常与该级别的低效率无关。而是全部与正确性有关,无用的跳转不是错误。
您可以在Wikipedia页面上了解有关基本块和控制流程图的更多信息。
编译器正在运行-O0。没有优化。像这样的代码生成怪癖是可以预期的。如果您使用-O1或更高版本进行编译,它们将消失。跳转线程是一种标准的优化算法。
| 归档时间: |
|
| 查看次数: |
109 次 |
| 最近记录: |