nasm是否有任何内置方法来发出给定长度的long-nop(aka multi-byte nops)指令?
答案 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
。