为什么C编译器在RET指令后生成NOP?

时间:2015-11-25 17:58:11

标签: c macos assembly

在OSX 64bit上,编译一个虚拟C程序:

<script>
  function myFunction(bgImgUrl) {
    window.parent.document.getElementById('seekerBase').style.backgroundImage = 'url(' + bgImgUrl + ')';
  }
</script>

<button type="button" onclick="myFunction('http://www.floom.com/images/waveform_lotos.gif')">Get the background image of div</button>

生成以下ASM代码(使用otool反汇编二进制代码):

#include <stdio.h>

void foo1() {
}

void foo2() {
}

int main() {
        printf("Helloooo!\n");
        foo1();
        foo2();
        return 0;
}

在foo1()和foo2()函数的“ret”之后找到的“nop”指令是什么?当然,它们从未被执行,因为“ret”指令从函数调用返回。这是任何类型的填充或它有不同的含义?

3 个答案:

答案 0 :(得分:3)

来自Assembly language for x86 processors, Kip R. Irvine

  

您可以编写的最安全(也是最无用的)指令称为NOP(无操作)。它占用1个字节的程序存储空间,不做任何工作。编译器和汇编器有时会使用将代码与偶数地址边界对齐

00000000 66 8B C3 mov ax,bx  
00000003 90 nop ; align next instruction  
00000004 8B D1 mov edx,ecx  

答案 1 :(得分:1)

  

在foo1()和foo2()函数的“ret”之后找到的“nop”指令是什么?

nop是一个无操作指令(什么都不做),来自链接的维基百科页面(强调我的)

  

NOP最常用于计时目的, 强制 内存对齐,以防止危险,占用分支延迟槽,使得现有指令(如跳转)无效,或者作为占位符在程序开发中稍后被活动指令替换(或者在重构时将替换删除的指令有问题或耗时)。

答案 2 :(得分:0)

nop是No Operation的缩写。在这种情况下,nop指令提供执行代码对齐。请注意,标签位于16字节边界上。在OSX上,链接器(ld)应该有一个-segalign选项,它将影响这种行为。