本文介绍了x86 多字节 NOP 和指令前缀的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

回忆一下,x86 架构将 0x0F 0x1F [mod R/M] 定义为多字节 NOP.

As a small recall, the x86 architecture defines 0x0F 0x1F [mod R/M] as a multi-byte NOP.

现在我正在查看 8 字节 NOP 的具体情况:我有

Now I'm looking at the specific case of an 8-byte NOP: I have got

0x0F 0x1F 0x84 0x__ 0x__ 0x__ 0x__ 0x__

其中最后 5 个字节具有任意值.

where the last 5 bytes have got arbitrary values.

第三个字节,[mod R/M],拆分后给出:

The third byte, [mod R/M], split up gives:

  • mod = 10b:参数是 reg1 + DWORD 大小的位移
  • reg2 = 000b:(我们不在乎)
  • reg1 = 100b:表示参数是 SIB 字节 + 一个 DWORD 大小的位移.
  • mod = 10b: argument is reg1 + a DWORD-sized displacement
  • reg2 = 000b: (we don't care)
  • reg1 = 100b: indicates that the argument is instead the SIB byte + a DWORD-sized displacement.

现在,作为一个具体的例子,如果我取

Now, as a concrete example, if I take

0x0F 0x1F 0x84 0x12 0x34 0x56 0x78 0x9A

我有

  • SIB = 0x12
  • 位移 = 0x9A785634:一个双字

现在我添加 0x66 指令前缀以指示位移应该是 WORD 而不是 DWORD:

Now I add the 0x66 instruction prefix to indicate that the displacement should be a WORD instead of a DWORD:

0x66 0x0F 0x1F 0x84 0x12 0x34 0x56 0x78 0x9A

我希望 0x78 0x9A 被切断"并被视为一条新指令.但是,当编译它并在生成的可执行文件上运行 objdump 时,它仍然使用所有 4 个字节(一个 DWORD)作为位移.

I expect 0x78 0x9A to be 'cut off' and be treated as a new instruction. However, when compiling this and running objdump on the resulting executable, it still uses all 4 bytes (a DWORD) as displacement.

在这种情况下,我是否误解了位移"的含义?还是 0x66 前缀对多字节 NOP 指令没有任何影响?

Am I misunderstanding the meaning of 'displacement' in this context? Or does the 0x66 prefix not have any effect on multi-byte NOP instructions?

推荐答案

66H 前缀将操作数的大小覆盖为 16 位.
它不会覆盖地址的大小,如果您希望使用 67H

The 66H prefix overrides the size of the operand to 16 bit.
It does not override the size of the address, if you want that you use 67H

这是所有操作数的列表.

Here's a list of all operands.

        F0h = LOCK  -- locks memory reads/writes
        String prefixes
        F3h = REP, REPE
        F2h = REPNE
        Segment overrides
        2Eh = CS
        36h = SS
        3Eh = DS
        26h = ES
        64h = FS
        65h = GS
        Operand override
        66h. Changes size of data expected to 16-bit
        Address override
        67h. Changes size of address expected to 16-bit

但是最好不要创建自己的 nop 指令,而是坚持推荐的(多字节)nop.

However it is best not to create your own nop instructions, but stick to the recommended (multi-byte) nops.

根据 AMD 推荐的多字节 nops 如下:

According to AMD the recommended multibytes nops are as follows:

表 4-9.NOP指令的推荐多字节序列

Table 4-9. Recommended Multi-Byte Sequence of NOP Instruction

bytes  sequence                encoding

 1      90H                            NOP
 2      66 90H                         66 NOP
 3      0F 1F 00H                      NOP DWORD ptr [EAX]
 4      0F 1F 40 00H                   NOP DWORD ptr [EAX + 00H]
 5      0F 1F 44 00 00H                NOP DWORD ptr [EAX + EAX*1 + 00H]
 6      66 0F 1F 44 00 00H             NOP DWORD ptr [AX + AX*1 + 00H]
 7      0F 1F 80 00 00 00 00H          NOP DWORD ptr [EAX + 00000000H]
 8      0F 1F 84 00 00 00 00 00H       NOP DWORD ptr [AX + AX*1 + 00000000H]
 9      66 0F 1F 84 00 00 00 00 00H    NOP DWORD ptr [AX + AX*1 + 00000000H]

Intel 不介意最多 3 个冗余前缀,因此可以像这样构造最多 11 个字节的 nop.

Intel does not mind up to 3 redundant prefixes, so nop's up to 11 bytes can be constructed like so.

 10     66 66 0F 1F 84 00 00 00 00 00H     NOP DWORD ptr [AX + AX*1 + 00000000H]
 11     66 66 66 0F 1F 84 00 00 00 00 00H  NOP DWORD ptr [AX + AX*1 + 00000000H]

当然,您也可以通过在普通指令前加上冗余前缀来消除 nops.

Of course you can also eliminate nops by prefixing normal instructions with redundant prefixes.

例如

rep mov reg,reg //one extra byte

或强制 cpu 使用相同指令的更长版本.

or forcing the cpu to use longer versions of the same instruction.

test r8d,r8d is one byte longer than: test edx,edx

带有立即操作数的指令有短版和长版.

The instructions with immediate operands have short and long versions.

and edx,7 //short
and edx,0000007  //long

大多数汇编程序都会帮助您缩短所有指令,因此您必须使用 db

Most assembler will helpfully shorten all instructions for you, so you'll have to code the longer instructions yourself using db

将这些散布在战略位置可以帮助您对齐跳跃目标,而不必因 nop 的解码或执行而产生延迟.

Interspersing these in strategic locations can help you align jump targets without having to incur delays due to the decoding or execution of a nop.

请记住,大多数 CPU 执行 nop 仍然会消耗资源.

Remember on most CPU's executing nop's still uses up resources.

这篇关于x86 多字节 NOP 和指令前缀的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-20 08:31