x64 asm コードで完全な命令に必要な最大バイト数は?
アドレスへのジャンプのようなものは、最大 9 バイトを占める可能性があります: FF 00 00 00 00 11 12 3F 1Fしかし、それが x64 命令で使用できる最大バイト数かどうかはわかりません
x86 命令セット (16、32、または 64 ビット、すべてのバリアント/モード) は、命令が最大 15 バイトであることを保証/要求します。それを超えると、「無効なオペコード」になります。冗長なプレフィックス (複数の 0x66 または 0x67 プレフィックスなど) を使用しないと、これを実現することはできません。
データ項目として実際に 64 ビットを使用する唯一の命令は、登録するロード定数です (Intel 構文: mov reg, 12345678ABCDEF00h
、at&t 構文: movabs $12345678ABCDEF00, %reg
)。したがって、31 ビットを超えて前方/後方にジャンプしたい場合は、目的の場所をレジスターに入力し、レジスターを呼び出す/ジャンプします。32 ビットの即値と変位を (相対ジャンプとアドレッシング モードで) 使用すると、64 ビット モードの多くの命令で 4 バイトが節約されます。
質問は、x86 命令セットで可能な最長の命令は何ですか?
答え:無限のバイト数を持つ有効な x86 命令を作成できます!
そうです、1 つの有効な命令で 64K ROM イメージ全体を埋めることができます。具体的には、8086 命令の長さに制限はありません。涼しい!残念ながら、最近の i386 の亜種は、15 バイトを超える命令をデコードしようとすると、一般保護違反をスローします。
では、無限に長いが有効な 8086 命令とはどのようなものでしょうか? 実際、ちょっと退屈です。オペコードの前に冗長なプレフィックスを使用することによってのみ、無限に長い命令を形成できます。命令プレフィックスは、命令によって使用されるデフォルトのアドレス サイズ、データ サイズ、またはセグメント レジスタを変更できる命令の先頭に付加されるバイトです。
たとえば、無害に見える命令を使用できます。
89 E5 mov %sp,%bp
そして、それを非常に長い命令に変えます:
66 66 66 66 … 66 66 89 E5 mov %sp,%bp
今ではそれはただの悪です。
https://web.archive.org/web/20131109063453/https://www.onlinedisassemblyr.com/blog/?p=23
場合によっては、従来の 15 バイトの長さ制限を超える有効な命令をエンコードすることが可能です。例えば:
; 16-bit mode F2 F0 36 66 67 81 84 24 disp32 imm32 = xaquire lock add [ss:esp*1+disp32],imm32 F3 F0 36 66 67 81 84 24 disp32 imm32 = xrelease lock add [ss:esp*1+disp32],imm32 ; 16-bit mode 36 67 8F EA 78 12 84 24 disp32 imm32 = lwpins eax,[ss:esp*1+disp32],imm32 36 67 8F EA 78 12 8C 24 disp32 imm32 = lwpval eax,[ss:esp*1+disp32],imm32 36 67 8F EA 78 10 84 24 disp32 imm32 = bextr eax,[ss:esp*1+disp32],imm32 ; 64-bit mode 64 67 8F EA F8 12 84 18 disp32 imm32 = lwpins rax,[fs:eax+ebx+disp32],imm32 64 67 8F EA F8 12 8C 18 disp32 imm32 = lwpval rax,[fs:eax+ebx+disp32],imm32 64 67 8F EA F8 10 84 18 disp32 imm32 = bextr rax,[fs:eax+ebx+disp32],imm32
Intel® 64 and IA-32 Architectures Software Developer's Manual から:
2.3.11 AVX 命令の長さ
Intel 64 および IA-32 命令の最大長は 15 バイトのままです。
15 バイト以上にエンコードする命令を作成することはできますが、そのような命令は違法であり、おそらく実行されません。