NOP
计算机科学中,NOP或NOOP(No Operation或No Operation Performed的缩写,意为无操作)是汇编语言的一个指令,一系列编程语句,或网络传输协议中的表示不做任何有效操作的命令。
NOP机器指令
有的计算机指令集包含一条指令,其主要目的是不改变任何程序可访问的寄存器,处理器状态标志或主存,而且可能需要特定的时钟周期来执行。在其它指令集中,NOP是用执行一条具有操作数,具有相同效果的指令来模拟的(例如SPARC处理器推荐使用sethi 0, %g0
模拟NOP)。
NOP指令通常用于控制时序的目的,强制内存对齐,防止流水线灾难,占据分支指令延迟),或是作为占位符以供程序的改善(或替代被移除的指令)。在某些情况中,NOP指令会产生副作用;例如在摩托罗拉 68000处理器中,NOP操作码会产生流水线同步[1]。
下表显示了部分CPU架构上NOP指令的特征:
CPU架构 | 助憶碼 | 字长 | 操作码 | 备注 |
---|---|---|---|---|
Intelx86系列CPU | NOP |
1; i686中为1–9 | 0x90; 0x0f 0x1f [2] | x86 CPU上的NOP指令实质上是XCHG EAX, EAX(操作码同为0x90)--无任何作用的指令。 |
Intel 8051 / MCS-51系列 | NOP |
1 | 0x00 | |
MIPS | NOP |
4 | 0x00000000 | |
MOS科技 65xx | NOP |
1 | 0xea | 65C02处理器发布时,之前多数的无效指令都被定义成了具有不同字长和需时的NOP指令。 |
PowerPC | NOP |
4 | 0x60000000 (ori r0,r0,0 的扩展操作码) |
NOP代码
NOP有时可以描述函数或一系列编程语句的作用,若部分没有作用(也可以称为冗余代码)。常见的编译器优化的作用就包括检测和去除这样的代码。
下面是一个起NOP作用的C语言语句的例子(评判标准在于语句是否影响程序输出,而非编译器是否为语句产生代码):
i+1;
(该语句执行了一个加法,但结果被丢弃。)
C语言中最简单的NOP块被称为空语句;其只包括一个分号。(标准没有要求编译器在这个例子中生成NOP指令;通常这个语句会直接为编译器所忽略。)
;
虽然空语句自身没有用处,但在某些情况下可以启动占位符的作用,例如在循环中:
while (ReadChar() != '\n')
;
以上代码一直调用ReadChar
函数,直到函数返回一个\n(NL,新行)字符。
Python中的pass
语句不会产生作用,可以作为NOP使用。它的主要目的是保证语法正确,由于Python的缩进敏感语法。
NOP协议命令
许多协议,比如telnet,包含NOP指令,该指令允许客户端可以在不会引起其它操作的情况下向服务器请求回应。NOP指令可以用于检测连接是否断开,或服务器是否可以响应操作。下列协议中包含NOOP指令(不完全列表):
注意:与其它协议不同,IMAP4的NOP命令允许客户端响应服务器发送由其它客户端反应的操作信息。
虽然大多数telnet和FTP服务器用OK或+OK回应NOOP指令,有的程序员在对客户端的回应中加入了特别的内容。例如MINIX的ftpd
守护进程会以以下消息回应NOOP:[3]
200 NOOP to you too!
破解
NOP通常在破解软件时有特殊用途,例如检查序列号,特定硬件或软件需求,加密狗等的软件。这是通过更改函数和/或子程序以跳过安全检查,直接返回期望的检测值实现的。由于大多数安全检查子程序中的指令会被废弃,它们会被NOP所代替。
安全问题
NOP操作码可以被用于组成一个NOP slide,允许在指令指针值未定义时执行代码,例如缓存溢出导致栈上的函数返回地址被更改。