現在のブログ
ゲーム開発ブログ (2025年~) Gamedev Blog (2025~)
レガシーブログ
テクノロジーブログ (2018~2024年) リリースノート (2023~2025年) MeatBSD (2024年)
 
        【プログラミング】アセンブリ言語を介してマシンコードを学ぶ方
進める前に、以下の記事を未だ読んでいない場合や復習が必要な場合は、以下の順序で、先ず読んで下さい:
此の記事は上記の2つの記事で説明された知識を基盤としており、此れらを事前に読んでいないと此の記事の内容は理解出来ません。
アセンブリはほぼマシンコード
前の記事で使用した objdump コマンドを覚えていますか?
此の記事でも再び使用します!
其の理由は、次の様な出力が見られるからです:
2016db: b9 09 00 00 00                mov     ecx, 0x9左側の16進数値と右側のアセンブリコードに注目して下さい。
此処に秘密があります:此れらは全く同じ意味を持っています!
其の通り、アセンブリコードは16進数値の人間が読める表現なのです!
b9 は「次の32ビットの即値を移動する」という意味で、09 00 00 00 はリトルエンディアンフォーマットで即値「9」を表します。
2進数では次の様に書かれます:10111001 00001001 00000000 00000000 00000000
そして此の2進数表現がマシンコードです!
次の例:
2016d2: 8b 45 f8      mov     eax, dword ptr [rbp - 0x8]
2016e6: 8b 75 f8      mov     esi, dword ptr [rbp - 0x8]
2016e9: 8b 55 f4      mov     edx, dword ptr [rbp - 0xc]8b は「次の32ビットの値をメモリ位置から指定されたレジスタに移動する」という意味です。45、75、及び 55 は使用するレジスタや宛先レジスタを含むアドレッシングモードを示します。
詰り、4は eax、7は esi、5は edx です。
此れら3つ全てに続く5は rbp を意味します。
最後に、f8 は -0x8 を、f4 は -0xc を表し、此れらはベースポインタである rbp のオフセットです。
16進数を2進数に変換:
8b 45 f8 → 10001011 01000101 11111000
8b 75 f8 → 10001011 01110101 11111000
8b 55 f4 → 10001011 01010101 11110100繰り返しになりますが、2進数表現がマシンが本当に理解する物です。
ModR/Mバイト
中間の部分、詰り45、75、55を見てみましょう。
2進数表現が得られたので、ModR/Mバイトについて説明出来ます。
2進数では、バイトは次の様に成ります:
ビット:   7 6 | 5 4 3 | 2 1 0
フィールド: Mod | Reg   | R/M8b 45 f8 では、45 の部分は2進数で 01000101 に変換されます。
Modはビット 01 で構成されています。
此れは8ビットのディスプレースメント( [rbp - 0x8] )を持つメモリ参照を示します。
詰り、メモリアドレスは [ベースレジスタ + ディスプレースメント] として計算され、ディスプレースメントは符号付き8ビット値です。
以下は可能なModフィールドのリストです:
- 00 → ディスプレースメントなし、レジスタ間接アドレッシング
- 01 → 8ビット符号付きディスプレースメント
- 10 → 32ビット符号付きディスプレースメント
- 11 → レジスタ直接アドレッシング
Regはビット 000 で構成されています。
此れは宛先レジスタを指定し、此の場合は eax で、x86エンコーディングではレジスタコード 000 です。
他の2つの例では、110(7)が esi を、010(5)が edx を意味する事が明らかに成ります。
以下は標準的なx86(32ビット)レジスタコードのリストです:
- 000→- eax
- 001→- ecx
- 010→- edx
- 011→- ebx
- 100→- esp
- 101→- ebp
- 110→- esi
- 111→- edi
R/Mはビット 101 で構成されています。
此れはベースレジスタを指定し、此の場合は rbp です。
コードのリスト:
- 000→ メモリアドレス- [eax]
- 001→ メモリアドレス- [ecx]
- 010→ メモリアドレス- [edx]
- 011→ メモリアドレス- [ebx]
- 100→ 特別なケース:複雑なメモリアドレス(例:- [eax + ebx*4])を指定する為にSIB(Scale-Index-Base)バイトが続く事を示す
- 101→- Mod = 00の場合は32ビットのディスプレースメント(ベースレジスタなし)を意味し、- Mod = 01又は- Mod = 10の場合は- [ebp + displacement]を意味する
- 110→ メモリアドレス- [esi]
- 111→ メモリアドレス- [edi]
ディスプレースメントは f8 で、45 の直後に来ており、前に説明したように-8、詰り16進数で -0x8 を意味します。
C言語で書かれたプログラムをデコンパイルする事で、アセンブリを学ぶだけでなく、最も低レベルなマシンコードも学ぶ事が出来ます!
かっこいいでしょ!!
以上