众所周知,x86(和x86_64)处理器不仅具有单字节的NOP
指令,还具有各种类型的多字节NOP类指令。
以下是我找到的:
推荐使用AMD,参考AMD家族15h处理器软件优化指南,文档#47414,第5.8节“使用操作数大小覆盖和多字节NOP进行代码填充”,第94页)
90 NOP1_OVERRIDE_NOP
6690 NOP2_OVERRIDE_NOP
0f1f00 NOP3_OVERRIDE_NOP
0f1f4000 NOP4_OVERRIDE_NOP
0f1f440000 NOP5_OVERRIDE_NOP
660f1f440000 NOP6_OVERRIDE_NOP
0f1f8000000000 NOP7_OVERRIDE_NOP
0f1f840000000000 NOP8_OVERRIDE_NOP
660f1f840000000000 NOP9_OVERRIDE_NOP
66660f1f840000000000 NOP10_OVERRIDE_NOP
6666660f1f840000000000 NOP11_OVERRIDE_NOP
推荐使用Intel,参考Intel 64和IA-32体系结构软件开发人员手册卷2B:指令集参考,N-Z,第“NOP”节
90 NOP
6690 66 NOP
0f1f00 NOP DWORD ptr [EAX]
0f1f4000 NOP DWORD ptr [EAX + 00H]
0f1f440000 NOP DWORD ptr [EAX + EAX*1 + 00H]
660f1f440000 66 NOP DWORD ptr [EAX + EAX*1 + 00H]
0f1f8000000000 NOP DWORD ptr [EAX + 00000000H]
0f1f840000000000 NOP DWORD ptr [EAX + EAX*1 + 00000000H]
660f1f840000000000 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H]
GNU汇编器(在binutils / gas中)包括以下模式::
f32(旧的与英特尔兼容的CPU,直到Pentium):
90 nop
6690 xchg %ax,%ax
8d7600 leal 0(%esi),%esi
8d742600 leal 0(%esi,1),%esi
908d742600 nop; leal 0(%esi,1),%esi
8db600000000 leal 0L(%esi),%esi
8db42600000000 leal 0L(%esi,1),%esi
908db42600000000 nop; leal 0L(%esi,1),%esi
89f68dbc2700000000 movl %esi,%esi; leal 0L(%edi,1),%edi
8d76008dbc2700000000 leal 0(%esi),%esi; leal 0L(%edi,1),%edi
8d7426008dbc2700000000 leal 0(%esi,1),%esi; leal 0L(%edi,1),%edi
8db6000000008dbf00000000 leal 0L(%esi),%esi; leal 0L(%edi),%edi
8db6000000008dbc2700000000 leal 0L(%esi),%esi; leal 0L(%edi,1),%edi
8db426000000008dbc2700000000 leal 0L(%esi,1),%esi; leal 0L(%edi,1),%edi
alt(适用于现代CPU,Intel和AMD相同):
0f1f00 nopl (%[re]ax)
0f1f4000 nopl 0(%[re]ax)
0f1f440000 nopl 0(%[re]ax,%[re]ax,1)
660f1f440000 nopw 0(%[re]ax,%[re]ax,1)
0f1f8000000000 nopl 0L(%[re]ax)
0f1f840000000000 nopl 0L(%[re]ax,%[re]ax,1)
660f1f840000000000 nopw 0L(%[re]ax,%[re]ax,1)
662e0f1f840000000000 nopw %cs:0L(%[re]ax,%[re]ax,1)
alt_short(适用于现代AMD家族CPU):
0f1f440000660f1f440000 nopl 0(%[re]ax,%[re]ax,1); nopw 0(%[re]ax,%[re]ax,1)
660f1f440000660f1f440000 nopw 0(%[re]ax,%[re]ax,1); nopw 0(%[re]ax,%[re]ax,1)
660f1f4400000f1f8000000000 nopw 0(%[re]ax,%[re]ax,1); nopl 0L(%[re]ax)
0f1f80000000000f1f8000000000 nopl 0L(%[re]ax); nopl 0L(%[re]ax)
0f1f80000000000f1f840000000000 nopl 0L(%[re]ax); nopl 0L(%[re]ax,%[re]ax,1)
alt_long(适用于现代英特尔系列CPU):
66662e0f1f840000000000 data16; nopw %cs:0L(%[re]ax,%[re]ax,1)
6666662e0f1f840000000000 data16; data16; nopw %cs:0L(%[re]ax,%[re]ax,1)
666666662e0f1f840000000000 data16; data16; data16; nopw %cs:0L(%[re]ax,%[re]ax,1)
66666666662e0f1f840000000000 data16; data16; data16; data16; nopw %cs:0L(%[re]ax,%[re]ax,1)
6666666666662e0f1f840000000000 data16; data16; data16; data16; data16; nopw %cs:0L(%[re]ax,%[re]ax,1)
我的问题是:所有这些字节序列是否有任何广泛/常见的命名,例如宏、伪助记符或类似的东西?到目前为止,我只发现:
- AMD 建议将它们命名为
NOPx_OVERRIDE_NOP
(x
= 字节长度)。 - gas 理解
nopw
(作为 2 字节 nop)和nopl
(作为 4 字节 nop)
现代反汇编器如何输出这些值呢?
相关但不重复的问题:What does NOPL do in x86 system?
GAS
中,所有对齐指令(.align
、.p2align
、.balign
)在代码段中使用时都是这样工作的。如你所说,nasm
似乎缺少了这个特性。 - Jester