MASM で変数定義と PUBLIC 指定を同時にやるマクロ
2026-02-25
タグ: #asmMASM では、some_func PROC PUBLIC と書いて、関数を書くと同時に他のモジュールから参照可能な公開扱いにすることができるが、どうも変数はそうではないらしい。
例えば hoge db 0 という変数があったとき、これを公開したければ PUBLIC hoge を別に書かなくてはならない。
そこで、MASM のマクロの勉強も兼ねて PUBVAR hoge db 0 のように書くと、hoge の PUBLIC 指定も同時にしてくれる PUBVAR マクロを作ってみることにした。
MASM の変数定義は 変数名 型 初期値 の形式で、例えば hoge db 100 と書くと、初期値が 100 の 1 バイト変数 hoge が定義される。
また、初期値の部分にカンマ区切りで複数の値を書くことができるので、手っ取り早い実装は、VARARG を用いて以下のようになるだろう。
PUBVAR MACRO varname:REQ, decl:VARARG
PUBLIC varname
varname decl
ENDM
PUBVAR hoge, db 1
PUBVAR fuga, db 2, 3, 4
PUBVAR piyo, dw 10 dup (2)
実際、上記のマクロでも実用上割と問題はないと思わないではないのだが、マクロの引数が varname (変数名)と decl(変数の定義内容)に分かれているので、変数名の後にカンマが必要になっている。
PUBVAR を付けたり外したりするのに合わせてカンマを書いたり消したりするのは、個人的には面倒そうで気に食わない。
というわけで、カンマ無しで書ける版を作った。
このマクロは、変数定義のうち hoge db 1 といった変数名から1個目の初期値までの範囲を decl 引数に、さらにカンマ区切りで継続する初期値があればそれらを VARARG の decl2 引数に受け取る。
マクロ内では、decl の先頭から最初に見つかったスペースまたはタブの手前までの内容を PUBLIC に渡し、decl と decl2 の内容を使って変数定義を行う。
文字列検索は @Instr でできるが、OR 検索のようなものはないので、スペースとタブ両方で検索を行い、最初に見つかった方を採用している。
PUBVAR MACRO decl:REQ, decl2:VARARG
LOCAL pos, pos_sp, pos_tab
pos_sp = @InStr(1, <decl>, < >)
pos_tab = @InStr(1, <decl>, < >)
IF pos_sp EQ 0
IF pos_tab EQ 0
.ERR <space or tab was not found>
ELSE
pos = pos_tab
ENDIF
ELSEIF pos_tab EQ 0
pos = pos_sp
ELSE
IF pos_sp LE pos_tab
pos = pos_sp
ELSE
pos = pos_tab
ENDIF
ENDIF
PUBLIC @SubStr(<decl>, 1, pos - 1)
IFB <decl2>
decl
ELSE
decl, decl2
ENDIF
ENDM
PUBVAR hoge db 1
PUBVAR fuga db 2, 3, 4
PUBVAR piyo dw 10 dup (2)
今回の作業で、置換 + α 程度でないような MASM のマクロ機能を初めて幾つか使ってみたが結構高機能で頑張れば色々できそうなので、何か他にいい案が浮かんで便利なマクロができたら今後も類似の紹介記事を書くかもしれない。