0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Posted at

元: https://technicalsuwako.moe/blog/asm-convert-to-machine-code

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

此の記事は上記の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言語で書かれたプログラムをデコンパイルする事で、アセンブリを学ぶだけでなく、最も低レベルなマシンコードも学ぶ事が出来ます!
かっこいいでしょ!!

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?