在nasm中的长nop指令

时间:2018-01-13 23:44:29

标签: assembly x86 nasm

nasm是否有任何内置方法来发出给定长度的long-nop(aka multi-byte nops)指令?

3 个答案:

答案 0 :(得分:3)

答案似乎是,开箱即用,没有正式的方法可以在nasm 1 中开出这些长n。

所以我根据英特尔手册 2 中推荐的序列编写了我自己的1到9个字节的宏:

0,0

我也已将这些添加到nasm-utils project,因此如果您有相同的需求,这是获取它们的一种方法。

1 虽然作为Jester points out,您可以深入了解内部,找到一些用于实现“智能对齐”功能的宏。

2 为了记录,我相信这些首次出现在AMD手册中,最终英特尔采用了相同的推荐序列。

答案 1 :(得分:2)

从2017年12月开始引用https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf第124页(3-28):

3.5.1.10使用NOP

代码生成器生成无操作(NOP)以对齐指令。 32位模式下不同长度的NOP示例如下所示:

1-byte: XCHG EAX, EAX
2-byte: 66 NOP
3-byte: LEA REG, 0 (REG) (8-bit displacement)
4-byte: NOP DWORD PTR [EAX + 0] (8-bit displacement)
5-byte: NOP DWORD PTR [EAX + EAX*1 + 0] (8-bit displacement)
6-byte: LEA REG, 0 (REG) (32-bit displacement)
7-byte: NOP DWORD PTR [EAX + 0] (32-bit displacement)
8-byte: NOP DWORD PTR [EAX + EAX*1 + 0] (32-bit displacement)
9-byte: NOP WORD PTR [EAX + EAX*1 + 0] (32-bit displacement)

这些都是真正的NOP,除了推进EIP之外,对机器的状态没有影响。

由于NOP需要硬件资源来解码和执行,因此请使用最少的数字来实现所需的填充。

单字节NOP:[XCHG EAX,EAX]具有特殊的硬件支持。虽然它仍然消耗了μop及其附带的资源,但是消除了对EAX旧值的依赖。

该μop可以尽早执行,减少未完成指令的数量,是最低成本的NOP。

其他NOP没有特殊的硬件支持。它们的输入和输出寄存器由硬件解释。因此,代码生成器应该安排使用包含最旧值的寄存器作为输入,以便NOP将尽早调度和释放RS资源。

尝试观察以下NOP生成优先级:

• Select the smallest number of NOPs and pseudo-NOPs to provide the desired padding.
• Select NOPs that are least likely to execute on slower execution unit clusters.
• Select the register arguments of NOPs to reduce dependencies.

答案 2 :(得分:-2)

请注意,代码方面,英特尔处理器中只有一条NOP指令。这有代码0x90,只有一个字节。

较长的“nop”是指不执行任何操作的指令,例如寄存器的XCHG。例如,对于“2字节NOP”,您可以写:

XCHG AL, AL

编码为:

86 C0

所以你可以编写宏来获得你想要的任何大小。找到所有这些“无所事事”的指示是有点工作的。另外,有时(通常)编译器会尝试优化您的表达式。这就是输入代码的必要条件。

我所知道的最长编码将使用LEA指令。这是地址偏移的大小可以优化的地方,因为它们将是零,很多零,并且它们应该进行优化。

正如Jester所说,你可以使用现有的宏。互联网上有一份文件副本。

https://github.com/letolabs/nasm/blob/master/macros/smartalign.mac

解码所有这些指令并查看它们的含义会很有趣。

例如,他们使用MOV %si, %si创建一个2字节NOP