Visual C++(VC++)でマシン語ファイルを作成

ここではVC++6.0 Professionalを対象としていますが、その他のバージョンのVC++でも若干の修正で同じことが行えると思います(未確認)

その1:準備と作成方法 (その2) (IDEを使用)

必要な準備

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
という警告が出ますが気にしないでください。

バッチファイルではなくIDEを使う方法


ファイル名: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

次へ