コンソール上への文字列の表示
1.実装について
コンソール上への文字列の表示には、VEFBLでこのように実現させようと思います。
print "(String)"
(String)とは、特殊な記号を除いた文字列を意味します。特殊な記号については、後で説明します。
2.アセンブリ
「vefbl」フォルダに「astest」のフォルダを作り、その中に先ほど「vefbl」フォルダにコピーした「iolib.dll」をコピーします。さらに「astest」フォルダ内に「1.asm」を新規作成してください。
+---vefbl
+---build.exe
+---build.nako
+---tokentest.nako
+---dnako.dll
+---astest.exe
+---makejapanese.bat
+---makewinjapanese.bat
+---vsvars32.bat
+---astest
+---iolib.dll
+---1.asm
+---plug-ins
+---nakofile.dll
+---nakostr.dll
以下のテキストを記述します。
.586
.model flat, stdcall
include iolib.inc
includelib iolib.lib
include kernel32.inc
includelib kernel32.lib
.code
_start:
invoke OutputString, "Hello Word!"
invoke ExitProcess, 0
end _start
OutputString関数は、「iolib.dll」の中で定義されています。「kernel32」は、ExitProcessのために必要なのでincludeしています。そしてこれをアセンブルするわけなのですが、アセンブラのコマンドラインの指定はとても複雑です。そこで、簡単にアセンブリをアセンブルできるツールを用意しました。「astest.exe」です。
まず、「astest」フォルダを右クリックして[コマンドプロンプトから開く]をクリックし、出てきたコマンドプロンプトに次のように打ち込んでください。
cd astest ..\astest 1
上記のコマンドラインは、「1.asmをアセンブルする」という意味です。ファイル名は拡張子を付加しない「1」を指定します。アセンブルに成功すると拡張子.asmが付加された「1.asm」ファイルが作成されます。
間違って「1.asm」とコマンドラインで指定すると、astest.exeは「1.asm.asmは存在しません」というメッセージを返します。ちゃんとファイルの存在まで調べてくれるのです。astest.exeでは、指定したアセンブリがカレントディレクトリ(現在パスが通っているディレクトリ)にないとリンクエラーを起こします。そのため、必ずカレントディレクトリをアセンブリのあるところに変更します。
では、改めてアセンブルした結果を見てみましょう。すると、エラーが発生していました。
C:\Documents and Settings\????????\My Documents\samples\codezine\vefbl \astest\1.asm(11) : error A2084: constant value too large C:\Documents and Settings\????????\My Documents\samples\codezine\vefbl \astest\1.asm(11) : error A2114: INVOKE argument type mismatch : argum ent : 1
エラーの種類にはいろいろありますが、以下、エラー番号(error A2084:の「A2084」の部分)のみで説明します。
A2084の発生理由は「型の指定サイズが大きすぎます」ということになります。A2114の発生理由は、「invokeで呼び出された外部DLLで定義されている型と一致しません」ということです。どこがいけないのでしょうか。エラーの発生した行を見てみましょう。
invoke OutputString, "Hello Word!"
MASMでは、何かの引数に文字列を指定する場合、一度「.data」内のデータに文字列を登録しておいて、その文字列の変数名を指定する必要があるのです。それをしなかったために、エラーが発生したようです。そのため、以下の通りに修正します。
.586
.model flat, stdcall
include iolib.inc
includelib iolib.lib
include kernel32.inc
includelib kernel32.lib
.data
PrintText db "Hello Word!", 0
.code
_start:
invoke OutputString, PrintText
invoke ExitProcess, 0
end _start
さて、もう一回アセンブルして実行してみましょう。今度はうまくいきそうです。
C:\Documents and Settings\????????\My Documents\samples\codezine\vefbl \astest\1.asm(14) : error A2114: INVOKE argument type mismatch : argum ent : 1
ところが、またエラーが発生してしまいました。エラーメッセージが指定している14行目を見た結果、さっきと同じところが原因です。
invoke OutputString, PrintText
実は、すべてがすべて、というわけではありませんが、外部DLLによっては「~のポインタを指定します」といった説明がAPIリファレンスに書かれていることがあります。「iolib.dll」は『コンパイラ入門 C#で学ぶ理論と実践』(冨沢高明 著、ソフトバンククリエイティブ、2006年2月)の筆者が製作したものですのでAPIの資料はありませんが、とりあえずポインタを指定してみます。
ポインタは、メモリのアドレス(特定の場所)を指すもので、MASMからポインタを指定するときはoffsetを使います。他にもaddrがありますが、これは非常用みたいなものです。ここではoffsetを指定してみます。
.586
.model flat, stdcall
include iolib.inc
includelib iolib.lib
include kernel32.inc
includelib kernel32.lib
.data
PrintText db "Hello Word!", 0
.code
_start:
invoke OutputString, offset PrintText
invoke ExitProcess, 0
end _start
アセンブルしてみると、今度は成功しました。文字列の格納された変数を指定する時は、よくoffsetを使います。また同時に、「以下のプロジェクトファイルを生成しました」と表示され、「1.exe」という実行ファイルも作成されました。さっそくコマンドラインに
1.exe
と打ち込みます。すると、
と、きちんと「Hello Word!」が表示されました。「iolibが見つかりません」とでてきた人は、「iolib.dll」を「astest」フォルダに移動しているか確認してください。

