「はじめて読むPentium マシン語入門編」をVisual Studio 2017で学習する

最近はじめてCTF(Capture The Flag)にチャレンジしたので、アセンブラやバイナリに興味が湧いてきてしまいました。ということで、初心者向けとして非常に良書だと思っている、「はじめて読むPentium マシン語入門編」を再読していました。

はじめて読むPentium マシン語入門編

はじめて読むPentium マシン語入門編

ところがこの本は2004年出版で、かなり昔の本ということもあって、学習環境がVisual C++ 2003を前提として書かれています。

ではこの学習環境を今は作れないのかというと……2017年現在は、無償で利用できるVisual Studio 2017 Community Editionがあります。これでほぼ同書内と同じ学習環境が構築できるので、その方法を紹介しておこうと思います。(というか、忘れないように自分用のメモという意味合いが強かったり。)

前置きが長くなりましたが、この記事は、「マシン語アセンブラにちょっと触れてみたい/学習を始めてみたいけど、何をどうしたらいいかさっぱり分からない……」という人向けです。

Visual Studio 2017のインストール

2017年現在、無償で利用できるVisual Stduioで、マシン語の学習に利用できるモノとしては、「Visual Studio Community 2017」があります。

なお企業でCommunity Editionを使う際にはいくつかライセンスの問題がありますが、個人が学習用に使うならば何も問題ありません。具体的なダウンロード手順等は省略します。MSのサイトに行けば普通に見つかりますね。

ただし、インストールの際に、インストールするオプションに注意が必要なので以下で説明します。

マシン語学習のための初期インストール

Community Editionでは、マシン語学習用の環境であるWin32コンソールアプリケーションを作るモジュール(CLIサポート)がデフォルトではインストールされません。このため、インストール時にオプションを選択する必要があります。

具体的には、Visual Studioインストーラを起動すると、下図のインストールするコンポーネントの選択画面に移ります。

ここでまず、「C++によるデスクトップ開発」のチェックが外れているので、クリックして選択します。

さらに上図で、右側の「C++/CLIサポート」にもチェックを入れておきます。これをチェックしておかないと、Win32コンソールアプリケーションが作成できません。

これで「インストール」を押せば、必要なモジュールが入った状態でインストールできます。なおインストールには6GBちょっと必要と、なんとまぁ富豪的マシン語の学習環境です(笑。

インストール完了後に、「ファイル」→「新規作成」→「プロジェクト」で、Visual C++で「Win32 コンソール アプリケーション」が選べるようになっていることを確認してください。

「はじめて読むPentium」の学習環境は、これでひとまずインストール完了です。

「はじめて読むPentium」のサンプルコードの書き方と実行

ここでは、93ページからのリスト5-1「プロジェクト名findzero」の例を、現在のVisual Studio 2017で追うやり方を紹介します。なお、「はじめて読むPentium マシン語入門編」を持っていることを前提としているので、持っていない人はまず買ってください。

ソースコードの書き方

リスト5-1は、以下のようなコードです。これを実際にVisual C++で書いてみましょう。なお、Visual C++Intel記法を用いるため、mov等の引数は「mov dst src」です。

データ:
  char Title[] = "Hello World!";

プログラム:
  mov   ecx, 100h
  mov   edi, offset Title
Loop1:
  cmp   [edi], 0
  je    end
  inc   edi
  loop  Loop1
end:

(引用:「はじめて読むPentium マシン語入門編」リスト5-1)

まずデータ部は、グローバル変数となるためmain関数の外で定義します。実際のプログラム(アセンブリ言語)は、Visual C++インラインアセンブラの機能を利用して記述します。具体的には、main関数の中に、以下のように __asm{} というブロックを作ります。

   __asm {
      (ここにアセンブリ言語を書く)
   }

インラインアセンブラでリスト5-1を記述してみたのが以下の図です。本の指示通りにブレークポイントも設定してあります。

なおブレークポイントやステップイン実行は、Visual C++ 2003の頃から操作に変わりは無いので、本の通りに設定できます。

デバッグウィンドウ

メニューの「デバッグ」→「デバッグの開始」後、「デバッグ」→「ウィンドウ」→「レジスタ」(Ctrl+Alt+G)でレジスタの内容が確認できます。なおレジスタの子ウィンドウは自由に移動できるので、タイトルバーをクリックして掴んで、しっくりくる場所に移動してください。

上の図は、「はじめて読むPentium」 の通りに、「自動変数」のウィンドウに入れた例です。

メモリの内容も確認してみましょう。下図のとおり、今、変数Title(Hello, World!)のアドレスは0x00a79000です。

ここで、「デバッグ」→「ウィンドウ」→「メモリ」→「メモリ1」を選択し、0x00a79000を確認してみると、下の図のとおり該当のアドレスには確かに「Hello World!」が格納されています。

ここで、「!」のASCIIコードは0x21であることを思い出してください。アドレス0x00a79000から12バイトめの「21」の後ろは0x00となっており、文字列が終端されていることが分かります。(この例では、他のアドレスも0x00が多いのでちょっと分かりにくいけど)。

混合モードと逆アセンブル

「はじめて読むPentium」 の本の中では、「混合モード」でマシン語を確認しようと書かれています。しかしこれは古い呼び名で、現在のVisual Studio 2017では「逆アセンブル」で確認することができます。

ここでは、以下のようなシンプルなC言語のソースを書きます。

#include "stdafx.h"

int main()
{
    char ch = 'A';

    printf("ch=%c\n", ch);

    return 0;
}

ブレークポイントを設定してデバッグを開始したら、「デバッグ」→「ウィンドウ」→「逆アセンブル」(Ctrl+Alt+D)としてみてください。すると下図のように、C言語のソースがアセンブラ言語に展開された混合モードで表示されます。

さらにこの状態で、逆アセンブルウィンドウで右クリックして「コードバイトの表示(Y)」を選択すると、次のように各行のニーモニックに対応するマシン語が表示されます。

まとめ

「はじめて読むPentium マシン語入門編」を、現在のVisual Studio 2017(Visual C++ 2017)で学習する環境について解説しました。ひとまず操作がこれだけ分かっていれば、同書を読み進めることができる(はず)です。

なお「はじめて読む」シリーズは、実は「はじめて読む486―32ビットコンピュータをやさしく語る」が、もっとも内容が濃く優れた良書、という評判が多いです。

はじめて読む486―32ビットコンピュータをやさしく語る

はじめて読む486―32ビットコンピュータをやさしく語る

しかし、マシン語に全くの初心者ならば、これよりもまずは「はじめて読むPentium マシン語入門編」がいいかなというのが私の意見です。同書はタイトル通りまさに「マシン語入門」であって、「Pentium入門」ではありません。そのため中級者以上からは「内容が簡単すぎる」とあまり評判がよろしく無いようですが、逆に初心者向けとしては非常にシンプルで分かりやすい本です。
また本記事で解説したとおり、2017年現在でも、無償でVisual Studio 2017で手を動かして色々試すことができますから、マシン語への入り口へはぴったりだと私は思います。