japan.internet.comThe Internet & IT Network
RSS
  • ニュース
  • コラム
  • リサーチ
  • ヘッドライン
  • 特集
  • ブログ
  • プレスリリース
  • 専門チャンネル
  • イベント
  • ランキング
  • ニュースメール
2009年7月4日
文字サイズ文字サイズ小文字サイズ中文字サイズ大
デベロッパー2005年10月12日 11:00

MASM32によるアセンブラ入門:パート1

海外海外internet.com発の記事
  • このエントリーを含むはてなブックマーク
  • この記事をクリップ!
  • Buzzurlにブックマーク
  • Yahoo!ブックマークに登録
  • newsing it!
  • この記事をokyuuへインポート

はじめに

 たいていのプログラマは、アセンブラ(またはアセンブリ言語)と聞くと尻込みをします。一般にアセンブラは、学ぶのも使用するのも非常に難しい言語だと思われています。さらに、アセンブラの使い方を知っている人は、周囲のプログラマからある種の尊敬を集める傾向にあります。

 このチュートリアルは、アセンブラに対するこのような誤解を払拭するための3回シリーズのうちの1回目です。このチュートリアルを通して、アセンブラは本当は難しい言語ではなく、むしろ簡単な言語であることを証明したいと思います。

 第1回目では、アセンブラのコーディングを大幅に単純化するためのツールを紹介し、これをVisual Studioに統合する方法を説明します。

アセンブラとは

 そもそも、アセンブラとは一体何でしょうか。ごく簡単に言えば、アセンブラはプロセッサの言語です。これより低いレベルに下がることはできません(各命令の実際のバイト値を操作する場合は話が別ですが)。movaddなどのコマンドはすべてアセンブラプログラムによって数値に直接変換され、それがプロセッサに渡されて実行されます。

 アセンブラが他の言語より優れているのは、処理速度の速さです。アセンブラではプロセッサの実行速度をそっくりそのまま利用できるのです。最新のコンパイラを使用してコードを最適化したとしても、そのコードの実行速度は、アセンブラで記述して最適化した同等のコードにはかなわないでしょう。

 しかし、アセンブラは何にでも使用できるわけではありません。1つのアプリケーションを全部アセンブラで記述することも可能ですが、現在ではC++などの高等言語を利用できるため、そんなことをするのは物好きくらいのものです。大多数のアプリケーションでは、C++の速度、あるいは.NETの速度でも十分に許容範囲内です。

 アセンブラが利用されるのは、速度が重視されるアプリケーション、たとえばグラフィックアプリケーションなどにおいてです。大きなメモリブロックを処理する小さくて非常に高速な関数を記述する場合は、アセンブラにかなうものはありません。ビットマップ操作は、アセンブラの知識が大きく物をいうケースの代表例です。

 アセンブラという言語の概要と長所を理解したところで、次はその使い方を見ていきましょう。

Visual C++内でアセンブラを使用する

 C++内でアセンブラを記述する1つの方法は、__asmブロックを使用することです。

DWORD Function(DWORD dwValue)
{
   __asm
   {
      mov eax, dwValue
      add eax, 100
      mov dwValue, eax
   }

   return dwValue;
}

 この例では、__asmブロック内にアセンブラの命令をいくつか記述しました。C++コンパイラはこれらの命令をそれぞれのマシン語コードに直接変換します。

 コードの意味は考えなくてかまいません。addが値の加算命令で、movが値の移動命令であるということがわかれば十分です。上記のコードでは、渡された値に100を加算しているだけです。

 なんだそれだけのことか、と思った人もいるのではないでしょうか。しかし、それは間違いです。__asmブロック内にコードを記述するという方法は、短いアセンブラコードの場合は問題ないのですが、ある程度長い関数を記述しようとすると少々面倒なことになります。たとえば、if..else文は次のようになります。

DWORD Function2(DWORD dwValue1, DWORD dwValue2)
{
   DWORD dwValue3 = 0;

#if 0
   // this is the Assembler
   if (dwValue1 == dwValue2)
   {
      dwValue3 = 1;
   }
   else
   {
      dwValue3 = 2;
   }
#endif

   __asm
   {
      mov eax, dwValue1

      ; this is the test of the values, i.e. if dwValue1 == dwValue2
      cmp eax, dwValue2

      ; jump to ’Else’ if they are not equal
      jne Else

      mov eax, 1
      jmp EndIf

   Else:
      mov eax, 2

   EndIf:
      mov dwValue3, eax
   }

   return dwValue3;
}

 ここでも、実際の命令についてはあまり気にしないでください。しかし、すべてのif文についてこのようなコードを書かなければならないとしたらどうでしょうか。

 __asmコードブロックを使用するのは、メモ帳とコマンドプロンプトを使用してC++を記述するようなものです。確かにできなくはありませんが、専用ツールを使用した場合よりもはるかに時間がかかります。

MASM32

 では、アセンブラを記述するための専用ツールにはどんなものがあるのでしょうか。ここでは、Microsoft Macro Assemblerを紹介しておきます(聞き間違いではありません。Microsoftもアセンブラを提供しているのです)。実はMicrosoftは1980年からアセンブラを提供しているのですが、あまり知られてはいません。さらに重要なことに、Microsoft Macro AssemblerはVisual C++リンカと互換性のある.objファイルを生成します。デバッグ情報を含んだ.objファイルを生成し、コードをステップ実行することも可能です。

 この記事では、MASMを使うためのフリーウェアである「MASM32」というアセンブラを使用します。MASM32はhttp://www.masm32.com/から入手できます。先に進む前に、MASM32をダウンロードしてインストールしてください。

 MASM32にはどんなメリットがあるのでしょうか。

 第一に、膨大な量のヘルプファイルが付属しています(「msasm32help」ディレクトリに収録)。

 第二に、開発者が必要とするであろう各種のジョブについてのマクロが用意されています。さらに、これらのマクロを使用すれば、それぞれのタスクを実行する最も効率的な方法を選択していることが確信できます。

 たとえば、前述のコードをMASM32を使用して記述すると次のようになります。

Function proc dwValue1:DWORD, dwValue2:DWORD

   mov eax, dwValue1

   .if eax == dwValue2
      mov eax, 1
   .else
      mov eax, 2
   .endif

   ret

Function endp

 この方がずっと読みやすいはずです。

 MASM32をダウンロードしてインストールしたところで、以降では、アセンブラファイルを既存のC++プロジェクトに追加する方法と、それをコンパイルするためのプロジェクト設定の設定方法、アセンブラで記述した関数にC++からアクセスする方法について、順を追って見ていきたいと思います。

アセンブラファイルをVisual C++に追加する

 以降の手順はVisual Studio.NET 2002(英語版)のものですが、Visual C++ 6またはVisual Studio.NET 2003でも同様に実行できます。

 まず、アプリケーションの検索ディレクトリにMASM32の「bin」フォルダを含める必要があります。[Tools]→[Options]→[Projects]→[Visual C++ Directories]を選択します。MASMをインストールしたパスの下にある「bin」フォルダを追加します。たとえば、「C:MASM32」ディレクトリにインストールした場合は「C:MASM32in」となります。

 このディレクトリをリストの一番下に移動します。これが非常に重要です。このフォルダには「link.exe」というリンカアプリケーションも含まれており、このリンカがVisual Studioで既定のリンカの代わりに使用される可能性があるからです。

 次はコンソールアプリケーションを作成します。

 「test.asm」という名前のファイルをプロジェクトに追加します。ソリューションエクスプローラ内の「Source Files」フォルダを右クリックし、[Add]→[Add New Item]を選択します。

 「test.asm」と入力して[Enter]キーを押すと、「test.asm」という新規ファイルが開かれます。このファイルに次のコードを入力します。

.486
.model flat, stdcall
option casemap :none

.code

TestProc proc dwValue:DWORD

   mov eax, dwValue
   add eax, 100
   ret

TestProc endp

end

 このコードでは、入力値(dwValue)に100を加算し、結果を返しています。

 MASMアセンブラファイルには、このコード例に示した最初の4行とendを必ず入れます。さらに、.code行とend行の間にコードを記述する必要があります。

 次は、このファイルに関するビルドプロパティを設定する必要があります。デバッグビルドの状態であることを確認し、ソリューションエクスプローラ内でこのファイルを右クリックし、[Properties]を選択します。[Custom Build Step]→[General]を選択し、[Command Line]に次のコマンドラインを入力します。

ml /c /coff /Zi /Fo"$(OutDir)$(InputName).asm.obj" "$(InputFileName)"

 さらに、[Outputs]に次のパスを入力します。

$(OutDir)$(InputName).asm.obj

 設定は次のようになります。

 リリースビルドの設定はこれとほとんど同じですが、コマンドラインに「/Zi」オプションを含めない点だけが異なります。これはデバッグ情報を生成するためのオプションなので、リリースビルドでは削除します。従って次のようになります。

ml /c /coff /Fo"$(OutDir)$(InputName).asm.obj" "$(InputFileName)"

 もちろん、これをマクロやアドインにして、このプロセスを自動化することもできます。ここでは、現在使われているどのバージョンのVisual Studioにも応用できるように、手順を1つ1つ紹介しておきました。

 次は、アセンブリで書かれた関数をC++から呼び出す方法を説明します。

C++からアセンブラコードを呼び出す

 上記のアセンブラコードでは、DWORD(つまり32ビット値)の入力を受け取るTestProcという関数を定義していました。この関数を呼び出すためには、C++内で関数を宣言する必要があります。アプリケーションのmainメソッドが記述されている.cppファイル内で、先頭の#includesの後に次の行を入力します。

extern "C" unsigned int __stdcall TestProc(unsigned int dwValue);

 さらに、mainメソッド内に次のコードを記述します。

int main(int argc, _TCHAR* argv[])
{
   unsigned int dwValue = 100;
   unsigned int dwReturn = TestProc(dwValue);

   printf("%d
", dwReturn);
   getchar();

   return 0;
}

 このアプリケーションを実行すると、予想どおり、「200」という結果が返されます。さらに、TestProcを呼び出す行にブレークポイントを設定していた場合は、このメソッドにステップインし([F11]キー)、アセンブラコードをステップ実行することができます。実は、アセンブラコード内にブレークポイントを設定することも可能です。

まとめ

 第1回では、アセンブラファイルを作成し、コンパイルし、C++コードから呼び出す方法について説明しました。シリーズ第2回では、アセンブリ言語を構成している実際の命令について説明し、レジスタなどのトピックについても取り上げることにします。

 パート2へ→

著者紹介

darwen(darwen)
Windows 3.11のVisual C++/MFC 1.5の時代からWindowsプログラミングに取り組み始める。現在は、多言語展開を図っているとあるソフトウェア会社のベテラン開発者としてあらゆるプロジェクトに従事。暇さえあればプログラミングをしているのではないかという噂あり。
関連テーマ
このエントリーを含むはてなブックマーク この記事をクリップ!
BuzzurlにブックマークBuzzurlにブックマーク Yahoo!ブックマークに登録
この記事をokyuuへインポート
最新トップニュース
データメーション
【データメーション】
中国が「Green Dam」フィルタ規制を撤回(7月1日)
Graphic Design Forum
【Graphic Design Forum】
Chris Dickman(6月25日)
プライバシー ジャパン・インターネットコム版
【プライバシー ジャパン・インターネットコム版】
グーグル・ストリートビューの問題について総務省の見解(6月23日)
エンジニアの独り言
【エンジニアの独り言】
システムを「使う」時代のエンジニアに求められるもの(6月2日)
最新ハイテク講座
最新ハイテク講座
電気は家庭でつくる時代へ!燃料電池「エネファーム」(7月3日)
アクセス解析で見るWebマーケティング
アクセス解析で見るWebマーケティング
決定力を探るアクセス解析(7月3日)
百式のネットビジネス研究
百式のネットビジネス研究
ファーストフードを高級っぽく盛り付けて紹介している「Fancy Fast Food」(7月3日)
週刊-サイト別アクセス状況データ
週刊-サイト別アクセス状況データ
ビデオリサーチインタラクティブ調査(月間インターネットオーディエンスデータ)(7月2日)
成約率、反応率を上げる Web 文章術
成約率、反応率を上げる Web 文章術
言葉がダイレクトにキャッシュを生む(7月2日)
不況時代の Web ビジネス最適化講座
不況時代の Web ビジネス最適化講座
アクセス解析エキスパートここだけの話、Web コンシェルジュの“勉強法”こっそり教えます(7月2日)
「Webからの脅威」―その傾向と最新対策
「Webからの脅威」―その傾向と最新対策
不正プログラムの分類(7月1日)
DevX
DevX
JavaScriptとDOMによる動的なWebページの作成(6月30日)
エンジニア転職ノウハウ開発室
エンジニア転職ノウハウ開発室
今のままで大丈夫?3匹の子ブタ的キャリア危険度診断(6月30日)
アイレップの SEM フロンティア
アイレップの SEM フロンティア
Web サイトは「無駄な穴のたくさん開いたじょうご」〜サイト成果向上の基本的な考え方(6月30日)
Copyright 2009 Japan Internet.com K.K. All Rights Reserved.http://www.internet.com/