japan.internet.com The Internet & IT Network


RSSニュース検索
カテゴリ
> トップページ
> Webビジネス
> Eコマース
> Webファイナンス
> Webマーケティング
> パブリック
> Webテクノロジー
> 携帯・ワイヤレス
> Linux Today
> Linux Tutorial
> J.I.C.ブログ
キャリア
> 転職ならen
> 派遣ならen
> アルバイトならen
> IT求人情報
ヘッドライン
> 今日のヘッドライン
> 週間ヘッドライン
Special Link
> フォトコミュニティ
> ストックフォト
> クリップアート
> イラスト
> フェリカ
> Web2.0
> 写真
イベント&セミナー
> イベントカレンダー
> 書評「IT の耳」
> 出張・接待検索
> ニュースガジェット 注目
無料ニュースメール
> 新規登録
> 変更・解除
> オプトインメールの登録・変更・解除
インフォメーション
> パートナーサイト
転職ならエン
就職ならen
求人ならen
履歴書ならen
アルバイトならエン
CRM/SFAならオラクル
> グループ会社
株式会社アエリア
(株)サンゼロミニッツ
株式会社エアネット
> お問い合わせ
> 広告掲載について
> リンクについて
> 著作権について
> その他お問い合わせ
> 利用規約
> 個人情報保護方針
> 会社概要地図
コラム コラム一覧へ戻る

japan.internet.com 編集部 japan.internet.com 編集部
米国 Jupitermedia が運営する、プログラムコードに関する専門サイト。
多数の記事、多数のコードを掲載し、ソースコードをダウンロードすることもできる。


 メール  著者にメールする
 ホーム  http://www.codeguru.com/

最新コラム

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

著者: darwen プリンター用 記事を転送
2005年10月12日 11:00 付の記事
■海外internet.com発の記事

はじめに

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

 このチュートリアルは、アセンブラに対するこのような誤解を払拭するための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プログラミングに取り組み始める。現在は、多言語展開を図っているとあるソフトウェア会社のベテラン開発者としてあらゆるプロジェクトに従事。暇さえあればプログラミングをしているのではないかという噂あり。

過去コラム集
シェル活動をログに記録する
LicenseProvider によるソフトウェアのライセンス制御
C#のデバッグテクニック
フォームに合わせて DataGridView を自動的にサイズ変更する
BSTR およびC文字列の変換
デスクバンドと Internet Explorer バーの実装
Windows のスレッドプーリング
別のプロセスにコードを割り込ませる3つの方法
Nullを許容するDateTimePickerコントロール
海外のインターネットコム アメリカ韓国ドイツトルコ
関連企業のサイト:ストックフォト イラスト ネットストリート ホテル予約サイト タウン情報 出張 事業継承 シミュレーション トランクルーム 優待映画チケット 田舎暮らしガイド オリジナルデザインTシャツ ニタコエ
Copyright 2008 Jupitermedia Corporation All Rights Reserved. http://www.internet.com/
space.gif space.gif