Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 什么';CIL nop操作码的目的是什么?_Assembly_Bytecode_Cil - Fatal编程技术网

Assembly 什么';CIL nop操作码的目的是什么?

Assembly 什么';CIL nop操作码的目的是什么?,assembly,bytecode,cil,Assembly,Bytecode,Cil,我正在浏览MSIL,注意到MSIL中有很多指令 MSDN的文章说,如果操作码打了补丁,它们不会采取任何行动,而是用来填充空间。它们在调试版本中的使用要比发布版本多得多 我知道这些类型的语句在汇编语言中用于对齐以后的指令,但是为什么MSIL中需要MSIL nops呢 (编者按:公认的答案是关于机器代码NOPs,而不是问题最初提出的MSIL/CIL NOPs。)它为基于行的标记(例如断点)提供了机会在代码中,发布版本不会发出任何指令。它们的一个经典用法是,调试器可以始终将源代码行与IL指令关联起来。

我正在浏览MSIL,注意到MSIL中有很多指令

MSDN的文章说,如果操作码打了补丁,它们不会采取任何行动,而是用来填充空间。它们在调试版本中的使用要比发布版本多得多

我知道这些类型的语句在汇编语言中用于对齐以后的指令,但是为什么MSIL中需要MSIL nops呢


(编者按:公认的答案是关于机器代码NOPs,而不是问题最初提出的MSIL/CIL NOPs。)

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

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

Dude!没有行动是可怕的!它是一种只消耗时间的指令。在昏暗的黑暗时代,你可以用它来对关键循环中的计时进行微调整,或者更重要的是作为自我修改代码的填充。

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


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

它们可以在调试时使用它们来支持编辑并继续。它为调试器提供了工作空间,可以在不改变偏移量的情况下用新代码替换旧代码等。

这并不是对您的特定问题的回答,但在过去,如果无法用其他有用的指令填充,您可以使用NOP来填充。

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

在软件破解场景中,解锁应用程序的经典方法是使用NOP对检查密钥、注册、时间段或其他内容的行进行修补,这样它就不会执行任何操作,只需像注册一样继续启动应用程序。

NOP有多种用途:

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

我还看到代码中的NOP会修改自身以混淆它作为占位符的功能(非常旧的复制保护)。

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


我不熟悉破解,但我认为使用NOP覆盖堆栈是很常见的,因此您不必精确计算恶意函数的起始位置。

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

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


在这些情况下,专用nop可能会强制下一条指令进入特定管道(第一条,或不是第一条),并改进以下指令的配对,从而使nop的成本超过摊销。

正如ddaa所说,nop允许您考虑堆栈中的差异,因此,当您覆盖返回地址时,它会跳转到nop底座(一行中有很多nop),然后正确地命中可执行代码,而不是跳转到指令中不是开头的某个字节。

以下是调试如何使用nop(而不是x86机器代码):

NOP被语言编译器(C#、VB等)用来定义隐式序列点。这些命令告诉JIT编译器在何处确保机器指令可以映射回IL指令

Rick Byer在上的博客文章解释了一些细节


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

我使用Nops自动调整输入ISR后累积的延迟。非常方便地确定时间。

在缓冲区溢出漏洞利用中使用了一种有点非正统的用法。

50年太晚了,但是嘿

如果手动键入汇编代码,Nop很有用。 如果你必须删除代码,你可以不使用旧的操作码

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

有时你不得不使用现有的工具。在某些情况下,这只是一个非常基本的machinecode编辑器


如今,对于编译器来说,这些技术已经毫无意义了。

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

将值加载到寄存器(需要8个周期) nop 8 将1添加到寄存器

这确保了寄存器具有c