NOPL在x86机中的作用是什么?感觉它什么也不做,但是为什么它总是在汇编代码中呢?
发布于 2012-09-24 05:49:54
NOP
是一个单字节的“什么都不做”的操作,字面意思是“没有操作”。NOPW,NOPL等是等效的不做任何事情,但取字和长字节。
例如:
NOP // 1byte opcode
NOP // 1byte opcode
等于做
NOPW // 2byte opcode.
它们非常方便地填充东西,因此代码序列从特定的内存边界开始,占用几个字节的指令空间,但实际上什么也不做。
NOP对CPU的唯一影响是将IP
/EIP
增加1,NOPx等效值将增加2、4等。
发布于 2012-09-24 11:23:34
根据John的博客: AMD64上NOP的操作数,nopw
,nopl
等是gas
语法,而不是AT&T语法。
下面是gas
为不同的nop
和来源生成的指令编码,指令长度从3字节到15字节不等。请注意,有些格式与英特尔推荐的nop
窗体相同(见下文),但并非全部。特别是在较长的nop
的gas
中,不同nop
窗体中使用多个(最多5个)连续的0x66
操作数前缀,而英特尔推荐的nop
窗体在任何单个推荐的nop
指令中都不会使用多个d13操作数和前缀。
nop编码来自
源代码
for gas 2.3(为了可读性而重新格式化):
/* 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
};
英特尔使用不同的语法,所有指令长度从1到9个字节都可以使用nop。有几个不同的nop,因为所有nop的长度都超过两个字节,都可以接受一个操作数。单字节nop (0x90)是xchg (e)ax,(e)ax的同义词。
Intel 64和IA-32架构软件开发人员手册,第2卷(2A、2B和2C):指令集参考,A,第4章:指令集参考,M
列出了不同指令长度的推荐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
因此,除了英特尔推荐的这些nop之外,还有许多其他的nop,除了将指令与特定的内存边界对齐外,马克?B在他的回答中提到,nop的指令在自修改代码、调试和逆向工程方面也非常有用。
发布于 2013-10-13 05:08:38
实际上,当代码需要修补时,NOP将在汇编代码中使用。
由于新指令的大小可能与旧指令不同,因此需要填充。
填充指令应该与NOP相同,尽管它可能占用几个字节。
我们插入一个更复杂的指令,比如6690,而不是几个NOPs,是因为一条指令的执行速度通常比几条NOPs更快。
https://stackoverflow.com/questions/12559475
复制相似问题