7

ちょっとした思い出として、x86 アーキテクチャは0x0F 0x1F [mod R/M]マルチバイト NOP として定義します。

今、私は 8 バイト NOP の特定のケースを見ています:

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

最後の 5 バイトには任意の値が含まれています。

[mod R/M]分割された3 番目のバイト は次のようになります。

modrm

  • mod = 10b: 引数はreg1+ DWORD サイズの変位です
  • reg2 = 000b: (私たちは気にしません)
  • reg1 = 100b: 引数が代わりにSIBバイト + DWORD サイズの変位であることを示します。

さて、具体例を挙げると

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

私が持っている

  • SIB = 0x12
  • displacement = 0x9A785634: DWORD

0x66次に、ディスプレースメントが DWORD ではなく WORD であることを示す命令プレフィックスを追加します。

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

0x78 0x9A私は「断ち切られ」、新しい指示として扱われることを期待しています。ただし、これをコンパイルobjdumpして結果の実行可能ファイルで実行すると、4 バイトすべて (DWORD) が変位として使用されます。

この文脈での「変位」の意味を誤解していますか? または、0x66プレフィックスはマルチバイト NOP 命令には影響しませんか?

4

1 に答える 1

8

66Hプレフィックスは、オペランドのサイズを 16 ビットにオーバーライドします。
必要に応じて、アドレスのサイズをオーバーライドしません。67H

すべてのオペランドのリストを次に示します。

        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 を使用することをお勧めします。

AMD によると、推奨されるマルチバイト nops は次のとおりです。

表 4-9。NOP 命令の推奨マルチバイト シーケンス

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 をそのように構築できます。

 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 を排除することもできます。

例えば

rep mov reg,reg //one extra byte

または、同じ命令のより長いバージョンを使用するように CPU に強制します。

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

即値オペランドを持つ命令には、短いバージョンと長いバージョンがあります。

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

ほとんどのアセンブラは、すべての命令を短縮してくれるので、長い命令は自分でコーディングする必要があります。db

これらを戦略的な場所に散在させることで、nop のデコードまたは実行による遅延を招くことなく、ジャンプ ターゲットを整列させることができます。

ほとんどの CPU で実行中の nop は、依然としてリソースを使い果たしていることに注意してください。

于 2016-04-01T16:56:50.363 に答える