Mar*_*c B 35
NOP
是一个单字节的"无所事事"操作,完全是"无操作".NOPW,NOPL等等等等,但是占用字和长字节.
例如
NOP // 1byte opcode
NOP // 1byte opcode
Run Code Online (Sandbox Code Playgroud)
相当于做
NOPW // 2byte opcode.
Run Code Online (Sandbox Code Playgroud)
它们非常方便填充事物,因此代码序列从特定的内存边界开始,占用几个字节的指令空间,但实际上并没有做任何事情.
NOP对CPU的唯一影响是增加IP
/ EIP
减1.NOPx等价物将增加2,4等...
nrz*_*nrz 34
据约翰Fremlin的博客:操作数对AMD64 NOP,nopw
,nopl
等都是gas
语法,而不是AT&T语法.
下面是由生成的指令编码gas
为不同的nop
从的gas
源从3到15个字节为指令的长度.请注意,有些与英特尔推荐的nop
表格相同(见下文),但并非全部.特别是,在较长nop
的gas
使用多个(最多5个)连续的0x66
在不同的操作数前缀nop
的形式,而英特尔的推荐nop
形式从来没有使用一个以上的0x66
在任何单一的推荐操作数前缀nop
指令.
nop
从编码的源代码用于气体 2.30(重新格式化为可读性):
/* nopl (%[re]ax) */
static const unsigned char alt_3[] = {0x0f,0x1f,0x00};
/* nopl 0(%[re]ax) */
static const unsigned char alt_4[] = {0x0f,0x1f,0x40,0x00};
/* nopl 0(%[re]ax,%[re]ax,1) */
static const unsigned char alt_5[] = {0x0f,0x1f,0x44,0x00,0x00};
/* nopw 0(%[re]ax,%[re]ax,1) */
static const unsigned char alt_6[] = {0x66,0x0f,0x1f,0x44,0x00,0x00};
/* nopl 0L(%[re]ax) */
static const unsigned char alt_7[] = {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00};
/* nopl 0L(%[re]ax,%[re]ax,1) */
static const unsigned char alt_8[] = {0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
/* nopw 0L(%[re]ax,%[re]ax,1) */
static const unsigned char alt_9[] =
{0x66,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
/* nopw %cs:0L(%[re]ax,%[re]ax,1) */
static const unsigned char alt_10[] =
{0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
static const unsigned char *const alt_patt[] = {
f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8,
alt_9, alt_10
};
Run Code Online (Sandbox Code Playgroud)
英特尔使用不同的语法,并且nop
可用于1到9个字节的所有指令长度.有几个不同nop
的,因为所有nop
超过两个字节接受1个操作数.一个字节nop
(0x90
)是同义词xchg (e)ax,(e)ax
.
英特尔®64和IA-32架构软件开发人员手册,第2卷(2A,2B和2C):指令集参考,AZ,第4章:指令集参考,MZ列出nop
了不同指令长度的推荐形式:
Table 4-12. Recommended Multi-Byte Sequence of NOP Instruction
Length Assembly Byte Sequence
2 bytes 66 NOP 66 90H
3 bytes NOP DWORD ptr [EAX] 0F 1F 00H
4 bytes NOP DWORD ptr [EAX + 00H] 0F 1F 40 00H
5 bytes NOP DWORD ptr [EAX + EAX*1 + 00H] 0F 1F 44 00 00H
6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
7 bytes NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H] 66 0F 1F 84 00 00 00 00 00H
Run Code Online (Sandbox Code Playgroud)
所以除了nop
英特尔推荐的这些之外,还有很多其他nop
的.除了将指令与特定的内存边界对齐之外,正如Marc B在他的回答中提到的那样,nop
在自修改代码,调试和逆向工程中也非常有用.
小智 6
实际上,当代码需要修补时,NOP将用在汇编代码中.
由于新指令的大小可能与旧指令的大小不同,因此需要填充.
填充指令应该与NOP相同,尽管它可能占用几个字节.
我们插入更复杂的指令(例如66 90而不是几个NOP)的原因是一条指令通常比几条NOP执行得更快.