|
任天堂が、大画面の「ニンテンドーDSi LL」を発表。欲しいと思いますか?
|
MASM32によるアセンブラ入門:パート1はじめにたいていのプログラマは、アセンブラ(またはアセンブリ言語)と聞くと尻込みをします。一般にアセンブラは、学ぶのも使用するのも非常に難しい言語だと思われています。さらに、アセンブラの使い方を知っている人は、周囲のプログラマからある種の尊敬を集める傾向にあります。 このチュートリアルは、アセンブラに対するこのような誤解を払拭するための3回シリーズのうちの1回目です。このチュートリアルを通して、アセンブラは本当は難しい言語ではなく、むしろ簡単な言語であることを証明したいと思います。 第1回目では、アセンブラのコーディングを大幅に単純化するためのツールを紹介し、これをVisual Studioに統合する方法を説明します。 アセンブラとは そもそも、アセンブラとは一体何でしょうか。ごく簡単に言えば、アセンブラはプロセッサの言語です。これより低いレベルに下がることはできません(各命令の実際のバイト値を操作する場合は話が別ですが)。 アセンブラが他の言語より優れているのは、処理速度の速さです。アセンブラではプロセッサの実行速度をそっくりそのまま利用できるのです。最新のコンパイラを使用してコードを最適化したとしても、そのコードの実行速度は、アセンブラで記述して最適化した同等のコードにはかなわないでしょう。 しかし、アセンブラは何にでも使用できるわけではありません。1つのアプリケーションを全部アセンブラで記述することも可能ですが、現在ではC++などの高等言語を利用できるため、そんなことをするのは物好きくらいのものです。大多数のアプリケーションでは、C++の速度、あるいは.NETの速度でも十分に許容範囲内です。 アセンブラが利用されるのは、速度が重視されるアプリケーション、たとえばグラフィックアプリケーションなどにおいてです。大きなメモリブロックを処理する小さくて非常に高速な関数を記述する場合は、アセンブラにかなうものはありません。ビットマップ操作は、アセンブラの知識が大きく物をいうケースの代表例です。 アセンブラという言語の概要と長所を理解したところで、次はその使い方を見ていきましょう。 Visual C++内でアセンブラを使用する C++内でアセンブラを記述する1つの方法は、
DWORD Function(DWORD dwValue)
{
__asm
{
mov eax, dwValue
add eax, 100
mov dwValue, eax
}
return dwValue;
}
この例では、 コードの意味は考えなくてかまいません。 なんだそれだけのことか、と思った人もいるのではないでしょうか。しかし、それは間違いです。
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;
}
ここでも、実際の命令についてはあまり気にしないでください。しかし、すべての 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 このコードでは、入力値( 注
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++からアセンブラコードを呼び出す 上記のアセンブラコードでは、 extern "C" unsigned int __stdcall TestProc(unsigned int dwValue); さらに、 int main(int argc, _TCHAR* argv[]) { unsigned int dwValue = 100; unsigned int dwReturn = TestProc(dwValue); printf("%d ", dwReturn); getchar(); return 0; } このアプリケーションを実行すると、予想どおり、「200」という結果が返されます。さらに、 まとめ第1回では、アセンブラファイルを作成し、コンパイルし、C++コードから呼び出す方法について説明しました。シリーズ第2回では、アセンブリ言語を構成している実際の命令について説明し、レジスタなどのトピックについても取り上げることにします。 著者紹介darwen(darwen)
Windows 3.11のVisual C++/MFC 1.5の時代からWindowsプログラミングに取り組み始める。現在は、多言語展開を図っているとあるソフトウェア会社のベテラン開発者としてあらゆるプロジェクトに従事。暇さえあればプログラミングをしているのではないかという噂あり。
関連記事 関連テーマ 最新トップニュース
|
|