Ut Video Codec Suite の Mac 版におけるアセンブラ化の一環として、MASM から NASM への書き換えを行っています。Mac で MASM は使えないためなのですが、GAS に移植して2バージョンメンテするのではなく、NASM に移植して1つのソースから Visual C++ 用と gcc 用の両方を生成すべきでしょう。

NASM では MASM と違い、(複数行の)マクロの引数は名前ではなく番号でアクセスします。例えば、MASM と NASM における以下のマクロ定義は、等価なマクロとなります。

MASM_MACRO macro foo, bar
        mov eax, foo
        mov ebx, bar
endm

%macro NASM_MACRO 2
        mov eax, %1
        mov ebx, %2
%endmacro

可変個引数マクロを実現するには番号でアクセスする方が都合がいいことが多いと思うのですが、そうでない場合は名前でアクセスする方が可読性が高いです。

もちろん、以下のように引数ごとに名前をつけることは可能です。

%macro MY_MACRO 3
%push
%xdefine %$hoge %1
%xdefine %$fuga %2
%xdefine %$homu %3
        mov eax, %$hoge
        ...
%pop
%endmacro

でも複数行になってしまって、ちょっと美しくない。引数が7つあるマクロとか書かなきゃいけないし。

というわけで、1行で引数に名前をつけるために、以下のようなマクロを定義してみました

%macro MACRO_PARAM_NAME 1-*
%assign i 1
%rep %0
%xdefine %$%1 %i
%rotate 1
%assign i i + 1
%endrep
%endmacro

%macro MY_MACRO 3
%push
        MACRO_PARAM_NAME hoge, fuga, homu
        mov eax, %$hoge
        ...
%pop
%endmacro

ところがこれだと内側のマクロ MACRO_PARAM_NAME から外側のマクロ MY_MACRO の引数を参照できないのでうまく行かないんですな。というか、複数行マクロの展開は定義時ではなく使用時に行われるので、MACRO_PARAM_NAME を展開して名前をつけようとした時には、既に MY_MACRO は展開済みで消滅しておりマクロ引数もなくなります。

しょうがないので、結局妥協して以下のような方法で逃げることにしました。

%macro MULTI_CONTEXT_XDEFINE 0-*
%rep %0 / 2
%xdefine %$%1 %2
%rotate 2
%endrep
%endmacro

%macro MY_MACRO 3
%push
        MULTI_CONTEXT_XDEFINE hoge, %1, fuga, %2, homu, %3
        mov eax, %$hoge
        ...
%pop
%endmacro

見た目はあんまり美しくないですが、動作は素直なはずです。つまらない解決方法ですまん。

Trackback

no comment untill now

Add your comment now