作为一个小小的召回,x86架构将 0x0F 0x1F [mod R/M]
定义为多字节NOP .
现在我看一下8字节NOP的具体情况:我有
0x0F 0x1F 0x84 0x__ 0x__ 0x__ 0x__ 0x__
最后5个字节有任意值 .
分开的第三个字节 [mod R/M]
给出:
-
mod = 10b
:参数是reg1
一个DWORD大小的位移 -
reg2 = 000b
:(我们不在乎) -
reg1 = 100b
:表示参数是SIB
字节,是DWORD大小的位移 .
现在,作为一个具体的例子,如果我采取
0x0F 0x1F 0x84 0x12 0x34 0x56 0x78 0x9A
我有
-
SIB = 0x12
-
displacement = 0x9A785634
:一个DWORD
现在我添加 0x66
指令前缀以指示位移应该是WORD而不是DWORD:
0x66 0x0F 0x1F 0x84 0x12 0x34 0x56 0x78 0x9A
我希望 0x78 0x9A
为'cut off'并被视为新指令 . 但是,在编译它并在生成的可执行文件上运行 objdump
时,它仍然使用所有4个字节(DWORD)作为位移 .
在这种情况下,我是否误解了'displacement'的含义?或 0x66
前缀对多字节NOP指令没有任何影响?
1 回答
66H
前缀会将操作数的大小覆盖为16位 .如果你想使用
67H
,它不会覆盖地址的大小这是所有操作数的列表 .
但是最好不要创建自己的nop指令,而是坚持推荐的(多字节)nops .
据AMD称,推荐的多字节数如下:
表4-9 . 推荐的NOP指令多字节序列
英特尔最多不介意3个冗余前缀,因此nop最多可以构造11个字节 .
当然,您也可以通过在正常指令前加上冗余前缀来消除nops .
例如
或强制cpu使用相同指令的更长版本 .
具有立即操作数的指令具有短版和长版 .
大多数汇编程序会帮助您缩短所有指令,因此您必须使用
db
编写更长的指令 .将这些分布在战略位置可以帮助您对齐跳转目标,而不必因为解码或执行nop而导致延迟 .
请记住,大多数CPU的执行nop仍然耗尽资源 .