【问题标题】:Why does gcc output machine code have nop instructions为什么gcc输出机器码没有nop指令
【发布时间】:2011-08-19 14:22:06
【问题描述】:

每次我执行 objdump -d 时,我总是会看到带有成批 nop 指令(什么都不做的指令)的 asm 代码

以同样的程序为例:

#include <stdio.h>
#include <math.h>

int main()
{
    printf("Hello World!\n");
    printf("cos:  %f\n", cos(1));
    return 1;
}

例如,objdump 在入口点的末尾有 2 个 nop

0000000000400450 <_start>:
400450: 31 ed                   xor    %ebp,%ebp
400452: 49 89 d1                mov    %rdx,%r9
400455: 5e                      pop    %rsi
400456: 48 89 e2                mov    %rsp,%rdx
400459: 48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
40045d: 50                      push   %rax
40045e: 54                      push   %rsp
40045f: 49 c7 c0 00 06 40 00    mov    $0x400600,%r8
400466: 48 c7 c1 70 05 40 00    mov    $0x400570,%rcx
40046d: 48 c7 c7 34 05 40 00    mov    $0x400534,%rdi
400474: e8 bf ff ff ff          callq  400438 <__libc_start_main@plt>
400479: f4                      hlt    
40047a: 90                      nop
40047b: 90                      nop 

这只是众多示例之一,但您明白了。为什么 C 代码是这样编译的?提前致谢。

【问题讨论】:

    标签: c objdump nop


    【解决方案1】:

    通常这些只是用于填充,以便后续内容再次从单词或边界开始,因为访问未在单词边界上对齐的任意代码对 cpu 来说代价更高。

    【讨论】:

      【解决方案2】:

      添加nops 以强制下一个函数与 4 字节边界对齐。 (注意最后一个nop 后面的地址是40047c,可以被4整除)

      【讨论】:

      • 在 x86_64 上,我还注意到函数中间有一个 4 字节 nop(就在 call 之前):0f 1f 40 00 nop DWORD PTR [rax+0x0] 知道这有什么好处吗?发生在-O3
      • @Kerrek 如果我没记错的话,它告诉处理器清除它的缓存并用指向地址的数据重新加载它。在这种情况下,处理器将使用[rax] 处的数据擦除其缓存(我假设这是调用跳转到的地址)。这允许处理器在跳转之前开始使用正确的数据重新加载其缓存。
      猜你喜欢
      • 2020-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-16
      • 2021-11-22
      • 1970-01-01
      • 2017-10-14
      • 1970-01-01
      相关资源
      最近更新 更多