私は32ビットのオペコードを持っています: FF 35 0E 20 40 00
. これに対する答えを与える良い OpCode テーブルを知っている人はいますか? (逆アセンブラを使用できることは知っていますが、オペコードテーブルでこれを判断する方法を知りたいです)。このウェブページを見つけましたが、 には 7 つの異なるソリューションがありFF
ます。私はそれを取得していません。
2 に答える
あなたは間違った場所を見ています。これは、IntelまたはAMDの公式ドキュメントで確認する必要があります。
Appendix A Opcode Map
のはそれがだVol 2B
とIntel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 3A and 3B
言います。FF
INC/DEC Grp5
1A
Table A-6 Opcode Extensions for One- and Two-byte Opcodes by Group Number
ofVol 2B
は、バイトのビット5から3に応じて、、、、、、、、のいずれか、FF
次のバイトを言います。(0x35 >> 3)&7=6またはバイナリで110。だから、これはです。Group 5
INC
DEC
CALLN
CALLF
JMPN
JMPF
PUSH
ModR/M
PUSH Ev
Chapter 2 Instruction Format
ofは、それらのバイトとそうでないVol 2A
ものを含め、命令がどの部分で構成されているかを説明します。ModR/M
Appendix A Using Opcode Tables
のVol 2B
教えてくれますE
:
ModR / Mバイトはオペコードの後に続き、オペランドを指定します。オペランドは、汎用レジスタまたはメモリアドレスのいずれかです。メモリアドレスの場合、アドレスはセグメントレジスタと次の値のいずれかから計算されます:ベースレジスタ、インデックスレジスタ、スケーリング係数、変位。
それはまたあなたに教えてくれますv
:
オペランドサイズ属性に応じて、ワード、ダブルワード、またはクアッドワード(64ビットモード)。
つまり、これEv
はレジスタまたはメモリオペランドを意味し、これは32ビットコード用であり、命令プレフィックスがないため、オペランドサイズは32ビットです。したがって、Ev
メモリ内の32ビットレジスタまたは32ビット変数。
次に、ModR/Mから最後までの残りのバイトを把握する必要があります。
Figure 2-1. Intel 64 and IA-32 Architectures Instruction Format
を見てくださいVol 2A
。ModR/M
= 0x35の場合:
Mod
= 00(バイナリ)
Reg
= 110(バイナリ;前にこれらの3ビットを抽出しました)
R/M
= 101(バイナリ)
Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte
ofVol 2A
は、Mod
=00およびR/M
=101はdisp32
、IOWを意味し、命令には32ビットの変位で構成されるメモリオペランドがあることを示しています。
バイトのReg
フィールドはModR/M
、7つの命令の1つを選択するためにすでに使用されているため、このフィールドはレジスタオペランドをエンコードしません。
だから、あなたの指示はPUSH DWORD [0x0040200E]
です。
そして、それは私の逆アセンブラの出力と一致します。
このバイト シーケンスを 1 バイトずつ調べてみましょう。
- 最初のバイトは
FF
. Intel Instruction Set Reference のオペコード マップを調べると、これが暗号化された "Grp 5 - 1A" と共に命令INC
または命令であることがわかります。DEC
1A は、「オペコード拡張として使用される ModR/M バイトのビット 5、4、および 3」を意味します。ModR/M バイトは、この命令に使用されるオペランドのソースとアドレスをエンコードするバイトです。この場合、オペコードを拡張するために 3 ビットが使用されます。 - 次のバイトは
35
. これは ModR/M バイトで、通常、それを使用する命令でオペコード自体の直後に表示されます。35
(16 進数) は00110101
2 進数なので、ビット 5、4、および 3 は110
. オペコード拡張テーブル (表 A-6) でこれを調べると、これがPUSH d64 Ev
命令であることを意味することがわかります。脚注は、「64 ビット モードのd64
場合、命令はデフォルトで 64 ビット オペランド サイズになり、32 ビット オペランド サイズをエンコードできない」ことを意味します。これはPUSH
命令に期待されています。Ev
は、オペランドのエンコーディングを指定するシンボルです。最も重要なのは、ModR/M バイトがオペコード自体に続くことを示しています。のv
一方、オペランドのサイズがオペランドサイズ属性に依存していることを示します。ModR/M バイトが既にあるので、それをデコードしましょう (表 2-2、このコードが 32 ビット モードで実行されていると仮定)。実効アドレスは adisp32
で指定されます。これは、32 ビット ディスプレースメントが続く必要があることを意味します。 ModR/M バイト。レジスタを指定する部分はそれESI
を使用する必要があると述べていますが、この場合、このフィールドはオペコード拡張に使用されるため、レジスタ ソース オペランドを示すためには使用されません。 - 次の 4 バイトは 32 ビットの変位です。
0E 20 40 00
は、リトル エンディアンとしてデコードされた場合、 を意味し0x40200e
ます。これは、この命令で使用されるオペランドのアドレスです。
つまり、アドレスから読み取った 32 ビット値をスタックにプッシュしFF 35 0E 20 40 00
ます。PUSH DWORD [0x40200e]
0x40200e