在对 gcc 编译器的 -O2 优化运行一些测试时,我在函数的反汇编代码中观察到以下指令:
data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)
这个指令有什么作用?
更详细地说,我试图了解编译器如何通过 O2 优化来优化无用的递归,如下所示:
int foo(void)
{
return foo();
}
int main (void)
{
return foo();
}
上面的代码在未经优化的情况下编译时会导致堆栈溢出,但适用于 O2 优化的代码。
我认为使用 O2 它完全消除了函数 foo 的堆栈推送,但为什么data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)
needed?
0000000000400480 <foo>:
foo():
400480: eb fe jmp 400480 <foo>
400482: 66 66 66 66 66 2e 0f data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)
400489: 1f 84 00 00 00 00 00
0000000000400490 <main>:
main():
400490: eb fe jmp 400490 <main>
要回答标题中的问题,请参阅说明
data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)
是一条 14 字节的 NOP(无操作)指令,用于填充之间的间隙foo
函数和main
函数保持 16 字节对齐。
x86 架构有大量不同大小的 NOP 指令,可用于将填充插入到可执行段中,这样,如果 CPU 最终执行它们,它们将不起作用。然后英特尔优化手册包含有关可用作填充的不同长度的推荐 NOP 编码的信息。
在这种特定情况下,它是完全无关的,因为 NOP 永远不会被执行(甚至在无条件跳转后解码),因此编译器可以用它想要的任何随机垃圾填充。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)