2025-10-12 12:18:12
諏訪子
lowlevel
assembly

【プログラミング】アセンブリ言語を介してマシンコードを学ぶ方

進める前に、以下の記事を未だ読んでいない場合や復習が必要な場合は、以下の順序で、先ず読んで下さい:

此の記事は上記の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ビットの値をメモリ位置から指定されたレジスタに移動する」という意味です。
4575、及び 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/M

8b 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ビット)レジスタコードのリストです:

  • 000eax
  • 001ecx
  • 010edx
  • 011ebx
  • 100esp
  • 101ebp
  • 110esi
  • 111edi

R/Mはビット 101 で構成されています。
此れはベースレジスタを指定し、此の場合は rbp です。
コードのリスト:

  • 000 → メモリアドレス [eax]
  • 001 → メモリアドレス [ecx]
  • 010 → メモリアドレス [edx]
  • 011 → メモリアドレス [ebx]
  • 100 → 特別なケース:複雑なメモリアドレス(例: [eax + ebx*4] )を指定する為にSIB(Scale-Index-Base)バイトが続く事を示す
  • 101Mod = 00 の場合は32ビットのディスプレースメント(ベースレジスタなし)を意味し、Mod = 01 又は Mod = 10 の場合は [ebp + displacement] を意味する
  • 110 → メモリアドレス [esi]
  • 111 → メモリアドレス [edi]

ディスプレースメントは f8 で、45 の直後に来ており、前に説明したように-8、詰り16進数で -0x8 を意味します。

C言語で書かれたプログラムをデコンパイルする事で、アセンブリを学ぶだけでなく、最も低レベルなマシンコードも学ぶ事が出来ます!
かっこいいでしょ!!

以上