nop操作码的目的是什么?

时间:2008-10-24 19:14:03

标签: assembly cil

我正在浏览MSIL并注意到有很多nop指令。 MSDN文章称,如果操作码被修补,它们不采取任何操作并用于填充空间。它们在调试版本中比在发布版本中使用得更多。我知道在汇编语言中使用这些语句来确保操作码适合字边界,但为什么在MSIL中需要它?

20 个答案:

答案 0 :(得分:98)

NOP有几个目的:

  • 它们允许调试器在行上放置断点,即使它与生成的代码中的其他符号组合在一起。
  • 它允许加载程序使用不同大小的目标偏移来修补跳转。
  • 它允许一个代码块在特定边界对齐,这对于缓存很有用。
  • 它允许增量链接以通过调用新节来覆盖代码块,而不必担心整体功能改变大小。

答案 1 :(得分:9)

以下是调试使用nops的方法:

语言编译器(C#,VB等)使用Nops来定义隐式序列点。这些告诉JIT编译器在哪里确保机器指令可以映射回IL指令。

Rick Byer关于DebuggingModes.IgnoreSymbolStoreSequencePoints的博客文章,解释了一些细节。

C#还会在呼叫指令后放置Nops,以便源中的返回站点位置是呼出而不是呼叫后的线路。

答案 2 :(得分:8)

它为代码中的基于行的标记(例如断点)提供了机会,其中发布版本不会发出任何内容。

答案 3 :(得分:6)

在针对特定处理器或体系结构进行优化时,它还可以使代码运行得更快:

处理器长时间使用大致并行工作的多个流水线,因此可以同时完成两个独立的指令。在具有两个流水线的简单处理器上,第一个可以支持所有指令,而第二个仅支持一个子集。此外,当必须等待前一条指令尚未完成的结果时,管道之间会有一些停顿。

在这些情况下,专用的 nop 可能会强制下一条指令进入特定的管道(第一条,或者不是第一条),并改善后续指令的配对,以便< em> nop 超过摊销。

答案 4 :(得分:4)

多德! No-op太棒了!这是一条除了消耗时间之外什么也不做的指令。在昏暗的黑暗时代,你会用它在关键循环中进行微调,或者更重要的是作为自修改代码中的填充物。

答案 5 :(得分:3)

它们的一个经典用途是,您的调试器始终可以将源代码行与IL指令相关联。

答案 6 :(得分:3)

在我最近工作的一个处理器(四年)中,NOP用于确保先前的操作在下一个操作开始之前完成。例如:

加载值进行注册(需要8个周期) nop 8 将1添加到注册

这确保寄存器在添加操作之前具有正确的值。

另一个用途是填写执行单元,例如必须是一定大小(32字节)的中断向量,因为vector0的地址对于向量1 0x20来说是0,依此类推,所以编译器放了NOP在那里,如果需要的话。

答案 7 :(得分:3)

他们可以在调试时使用它们来支持编辑并继续。它为调试器提供了工作空间,可以用新的代码替换旧代码而无需更改偏移等。

答案 8 :(得分:3)

50岁太晚了,但是嘿。

如果您手动输入汇编代码,Nop非常有用。 如果你必须删除代码,你可以删除旧的操作码。

类似地,您可以通过覆盖某些操作码来插入新代码并跳转到其他位置。你把覆盖的操作码放在那里,然后插入你的新代码。准备好后,你会跳回来。

有时您必须使用可用的工具。在某些情况下,这只是一个非常基本的机器码编辑器。

现在有了编译器,这些技术再也没有任何意义了。

答案 9 :(得分:3)

Nop在缓冲区溢出漏洞的有效载荷中至关重要。

答案 10 :(得分:3)

正如ddaa所说,nops让你考虑堆栈中的差异,这样当你覆盖返回地址时它会跳转到nop sled(连续很多nops)然后正确地命中可执行代码,而不是跳转到不是开头的指令中的某个字节。

答案 11 :(得分:2)

有点非正统的用法是NOP-Slides,用于缓冲区溢出攻击。

答案 12 :(得分:2)

在软件破解场景中,解锁应用程序的一种经典方法是使用NOP修补检查密钥或注册或时间段的行或什么不做,以便它什么也不做,只需继续启动应用程序就好像它已注册。

答案 13 :(得分:2)

我还看到代码中的NOP修改了自己,以模糊它作为占位符(veeery旧版本保护)的作用。

答案 14 :(得分:1)

我学到的第一个程序集是SPARC所以我熟悉分支延迟槽,如果你不能用另一个指令填充它,通常是你要放在分支指令上面的指令或者在循环中增加一个计数器,你使用NOP。

我不熟悉破解,但我认为使用NOP覆盖堆栈很常见,因此您无需准确计算恶意功能的开始位置。

答案 15 :(得分:1)

我使用NOP自动调整进入ISR后累积的延迟。指甲时间非常方便。

答案 16 :(得分:1)

.NET编译器是否对齐MSIL输出?我认为它可能有助于加快对IL的访问...此外,我的理解是它的设计是可移植的,并且在其他一些硬件平台上需要对齐访问。

答案 17 :(得分:1)

这不是您具体问题的答案,但在过去,您可以使用NOP来填充branch delay slot,如果您无法用其他有用的说明填写它。< / p>

答案 18 :(得分:1)

它们允许链接器用较短的指令(短跳转)替换较长的指令(通常为长跳转)。 NOP占用了额外的空间 - 代码无法移动,因为它会阻止其他跳跃工作。这发生在链接时,因此编译器无法知道长跳或短跳是否合适。

至少,这是他们的传统用途之一。

答案 19 :(得分:-1)

nop在内存破坏利用有效载荷中将很有用。当然,nopxchg eax, eax

类似