プリプロセッサ

プリプロセッサ
プリプロセッサは、コンパイルする前の、前段階の処理です。
マクロの展開や、条件分岐、インクルードファイルの読み込みなどが行われます。

プリプロセッサは、すべて % で始まります。
条件
条件によって、コードを分けたりする時に使います。

%if <条件> 
...
%elif <条件> 
...
%else 
...
%endif

%ifn   ; %if !
%elifn ; %elif !

%ifdef <macro> ; 単一行マクロが定義されている
%ifndef        ; 単一行マクロが定義されていない
%elifdef
%elifndef

%ifmacro <macro> [引数仕様] ; 複数行マクロが定義されている
%ifnmacro
%elifmacro
%elifnmacro

%ifidn <text1>, <text2> ; テキストが同一か
%ifidni                 ; 大文字小文字区別しない
%elifidn, %ifnidn, %elifnidn    ; 否定形 (区別あり)
%elifidni, %ifnidni, %elifnidni ; 否定形 (区別なし)

%iftoken ; 一つのトークンか
%eliftoken, %ifntoken, %elifntoken

%ifempty ; 空のトークンか
%elifempty, %ifnempty, %elifnempty

%ifenv  ; 環境変数が存在するか
%elifenv, %ifnenv, %elifnenv
%if
数値式の値が 0 以外であれば真となり、後続のコードが出力されます。

%ifn, %elifn は否定形で、値が 0 の場合、真となります。
%ifdef
%ifdef は、指定された単一行マクロが定義されているかどうかを判断します。
%ifmacro
%ifmacro は、指定されたマクロ名と引数仕様に一致する複数行マクロが定義されているかを判断します。
%ifidn
%ifidn は、(マクロ展開後の) 2つのテキストが同一であるかどうかを判断します。
%ifidni は、大文字小文字を区別しません。

対象が文字列ではないことに注意してください。前後の空白は含みません。

%ifidn __?OUTPUT_FORMAT?__, elf64
!elf64
%else
!else
%endif

; -f elf64 時とそれ以外

__?OUTPUT_FORMAT?__ の値は文字列ではないので、これを使います。
%ifid, %ifnum, %ifstr
%ifid は、1つの引数 (空白の場合もあり) を受け取り、その最初のトークンが存在し、かつ、識別子 (予約語やラベルなど) であるかどうかを判断します。
$ と $$ は、識別子とは見なされません。

%ifnum は、トークンが整数値定数かどうかを判断します。
(式は評価されないので、式を指定すると、false になります)。

%ifstr は、引用符で囲まれた文字列であるかどうかを判断します。
%iftoken
%iftoken は、渡されたものが、一つのトークンで構成されているかを判断します。

例えば、「1」は一つのトークンですが、「-1」は "-" (マイナス) と "1" の2つのトークンで構成されています。
%ifempty
%ifempty は、渡されたものが空 (トークンがまったく含まれていない) の場合に真となります。
%ifenv
%ifenv は、指定された環境変数が存在するかどうかを判断します。

環境変数の名前を、そのまま記述します (LANG など)。
NASM において、識別子として使用できない文字が含まれている場合は、文字列として記述する必要があります。
ソース関連
%include
%include "inc.asm"

指定したソースファイルをインクルードします。

インクルードファイルは、現在のディレクトリ (作業ディレクトリ) に加えて、-i/-I オプションで指定された検索パスからも検索されます。
%pathsearch
%pathsearch FPATH "foo.bin"

%pathsearch は、マクロ名とファイル名を指定します。

指定されたファイルが存在する場合は、ファイルにインクルードパスを加えた形の文字列を生成し、単一行マクロとして定義します (絶対パスではなく、オプションで指定されたパスを追加する)。
ファイルが存在しない場合は、そのままのファイル名で、単一行マクロを定義します。
%depend
%depend はファイル名を指定し、-M オプションとその関連オプションが使用されたときに、依存関係として出力されるファイルのリストに、指定ファイルを追加します。
%use
%use は、名前付きの標準マクロパッケージをインクルードします。

パッケージ名の指定には引用符は必要ありませんが、引用符で囲むこともできます。
エラー関連
%error <str> は、アセンブリを終了し、エラーを報告します。
%warning <str> は、警告メッセージを表示します。
%fatal <str> は、直ちにアセンブリを終了し、メッセージを表示します。

メッセージを引用符で囲むかは、オプションです。
引用符で囲まなくても、空白はそのまま出力できます。
繰り返し
NASM の TIMES プレフィックスでは、複数行のマクロを、複数回呼び出すために使用することはできません。
代わりに、プリプロセッサレベルでの %rep を使います。

%rep から %endrep で囲まれた範囲を、指定回数繰り返すことができます。
(%rep は数値の引数を受け取ります。これは、式にすることができます)

途中で抜け出したい場合は、%exitrep を使います。

%assign i 0
%rep  4
  add eax, [table+i*2] ; table+i*2 は NASM の式
  %assign i (i+1)      ; +1 した値を i に定義
%endrep

ここでは、マクロ i は、カウンタ変数のような扱いになります。

繰り返しの最大回数は、--limit-rep オプション、または「%pragma limit rep <N>」で指定された値に制限されます。
ほか
%!<NAME>
%!<NAME> を使用すると、環境変数の値を参照することができます。
環境変数の名前に、NASM において識別子として使用できない文字が含まれている場合は、NAME の部分を引用符で囲みます。

%defstr を使うと、値を文字列に変換して、マクロに定義することができます。

%defstr LANG %!LANG
LANG ; 'ja_JP.UTF-8'
%clear
%clear は、指定したタイプの、すべてのマクロ定義をクリアします (NASM 自身によって定義されたものも含む)。

%clear [global|context] type1 [type2...]

context は、ローカルマクロが対象です。デフォルトは global です。

define単一行マクロ
defalias単一行マクロのエイリアス。
下位互換のためのエイリアスを削除するのに使えます。
alldefinedefine defalias を2つ指定するのと同じ
macro複数行マクロ
allすべて。alldefine macro と同じ (デフォルト)

NASM 2.14 以前では、%clear のみがサポートされていました (%clear global all と同等)。
%line
プリプロセッサを出力すると、この行をよく見かけますが、%line は、元のソースファイル名と行番号を NASM に通知するために出力されるものです。
プログラマが直接使用する必要はありません。

%line nnn[+mmm] [filename]

nnn元のソースファイルの行番号
mmmnnn に対応する、プリプロセッサ後の入力ファイルの行番号
filename元のソースファイルのファイル名

オプションで --no-line を指定すると、すべての %line が無視されます。