ここではVC++6.0 Professionalを対象としていますが、その他のバージョンのVC++でも若干の修正で同じことが行えると思います(未確認)
VC++には.com形式の実行ファイルを作成する機能はありません。
そのため、まず.comを作成できる環境を用意する必要があります。
comを出力できるリンカとして16ビット用のLink.exeがありますので、これを使用します。
しかし、このリンカはVC++のコンパイラが出力するCOFF形式オブジェクトファイルを認識できません。
アセンブラのMASMがOMFオブジェクトファイルを出力できるので、コンパイラにアセンブリファイルを出力させ、それをMASMにアセンブルさせるようにします。
結局.comを作成するにはMASMと16ビット用Link.exeが必要になります。
MASMはVisual C++ 6.0 Processor Packを導入している方はVC++に含まれています。
そうでない方はこちらなどから入手して、ML.EXEとML.ERRをVC++のBINフォルダ(標準では"C:\Program
Files\Microsoft Visual Studio\VC98\Bin")に入れてください。
16ビット用リンカはここかここから入手して下さい。(自己解凍ファイル)
アーカイブを解凍したあとで、LINK.EXEをLINK16.EXEに名前変更してからVC++のBINフォルダに入れてください。
マシン語ファイルを作成する上で注意すべき点は、変数は全て自動変数を使用して、静的なデータ(静的変数や文字列など)は使用しないことです。これは、静的なデータのアドレスが分からないため、それを使用できないからです。
他にも、標準ライブラリ(マクロやインライン展開されるものは除く)やAPIは使用出来ません。
どうしても静的なデータやAPIを使いたい場合は、それをHSP側で用意してそのアドレスを引数として渡すようにします。
ウインドウプロシージャなどのように引数を渡せない関数の場合は、HSP側でリロケート(再配置)する必要があります。その場合でも、構造体を利用してリロケートする位置を一カ所ですむようにすれば、手間を最小限に出来ます。
簡単なサンプルとして、渡された数値の絶対値を記憶しておき、その合計を返すマシン語ファイルを作成します。
ソースは以下の通りです。
ファイル名:absadd.c
#include <windows.h>
//いままでに渡された絶対値の合計を返す
// i 加算する値
// all HSP側で用意した変数へのポインタ
// 戻り値 合計値
int absadd(int i,int *all)
{
return *all+=abs(i);
}
前述の通り静的変数は使用できないので、HSP側で用意した変数を使用するようにします。abs()はライブラリ関数ですが、インライン展開されるので使用できます。
関数の型にWINAPIはつけてもつけなくてもかまいません。(ll_callfuncは両方に対応しています)
関数を複数使う場合はHSPから直接呼び出される関数を1番上に持ってきてください。
マシン語ファイルを作成するには、コンパイラにアセンブリファイルを出力させ、それをMASMにアセンブルさせます。
具体的には以下のバッチファイルを実行することでマシン語ファイル(拡張子
BIN)を作成できます。
LINK : warning L4055: start address not equal to 0x100 for /TINY
という警告が出ますが気にしないでください。
ファイル名:MAKE.BAT
ソースのファイル名と拡張子、VC++のインストール先を赤字部分に設定してください。
OSが Win9x,Meの場合はバッチファイルの「プロパティ」->「メモリ」->「環境変数の初期サイズ」を1024以上にしてください。
@echo off SET file=ABSADD SET ext=C :コマンドライン用環境設定ファイル(VC++インストール時に作成されている) call "C:\Program Files\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT" cl /c /FA /O2 /Fonul %file%.%ext% if errorlevel 1 goto error ml /c /Cp %file%.asm if errorlevel 1 goto error link16 /TINY /NODEFAULTLIBRARYSEARCH /NOIGNORECASE %file%.obj,%file%.bin,nul,,, if errorlevel 1 goto error echo =====================作成成功========================== goto fin :error echo =====================エラー======================== if exist %file%.bin del %file%.bin :fin if exist %file%.asm del %file%.asm if exist %file%.obj del %file%.obj if "%OS%"=="Windows_NT" pause>nul
#include "llmod.as" #module #deffunc init ;マシン語ファイルを読み込む filename="absadd.bin" exist filename if strsize==-1:dialog filename+"がみつかりません。":end sdim func,strsize bload filename,func getptr pfunc,func ;HSP側で用意する変数 getptr pAll,all return #deffunc absadd int mref p1,0 para=p1,pAll ll_callfunc para,2,pfunc return #global init absadd -100 absadd 256 absadd -5000 mes "|-100|+|256|+|-5000|="+dllret stop