gasp(1) GNU アセンブラプリプロセッサ

書式

gasp [-adpsuM] [-c CHAR] [-o OUTFILE] [-DNAME=VALUE] [-IPATH] [--alternate] [--commentchar CHAR] [--copysource] [--debug] [--mri] [-output OUTFILE] [--print] [--unreasonable] INFILE...

gasp [-hv] [--help] [--version]

説明

gasp は、INFILE 引数を処理して、as(1) に直接入力させるために 連結して標準出力に出力する。

as は、他のプログラムによって生成された出力をアセンブルすることを 目的としているので、アセンブラを手で書くときに便利なマクロや条件文といった 一般的な機能を持っていない。 gasp は、これらの (as にはない) 機能を提供する。

オプション

-a, --alternate
別のマクロ文法を使用する。
-c CHAR, --commentchar CHAR
CHAR をコメント文字として使う。デフォルトのコメント文字は `!' である。
-d, --debug
gasp が内部的に割り当てる 文字列バッファについてのデバッグ統計情報を表示する。 それぞれ定められたバッファサイズ S について、 割り当てられた文字列 N

    strings size S : N

という形式で表す。 これらの統計量はデータを前処理する時に標準エラー出力に書き出される。

-o OUTFILE, --output OUTFILE
gasp によって生成された出力を OUTFILE に書き出す。 デフォルトでは標準出力に書き出される。
-p, --print
コメントとして行番号を出力する。 -s が指定されない限り、無視される。
-s, --copysource
コメントとしてソースの行を出力する。
-u, --unreasonable
無制限の (「非現実的な」) ネスト展開を許可する。 他のマクロの定義の中に gasp のマクロを定義できる時、 プリプロセッサは通常、sanity チェックを含める。 プログラムが 1000 回以上のネストされた展開を必要とする時には、 gasp は通常、エラーメッセージを出して終了する。 このチェックをオフにして無制限のネストされた展開を許したい時には、 このオプションを使用せよ。
-M, --mri
MRI 互換モードに入る。 Microtec Research ASM68K アセンブラ文法と 疑似オペレーションを使うために必要である。
-DNAME=VALUE
プリプロセッサ定数 NAME を値 VALUE で定義する。
-IPATH
PATH をインクルードパスのリストに追加する。
-h, --help
標準出力に使用方法を出力し、正常終了する。
-v, --version
バージョン情報を標準出力に出力し,正常終了する。

プリプロセッサコマンド

コマンドは大文字と小文字を区別せず、1 行は 3 つの部分に分けられる: (任意の) ラベル、コマンド自身、コマンドの引数である。

条件文

これらの指示子により、文字列や絶対式の組の比較方法に依存してアセンブリコードの 一部を含めたり除外したりすることが出来る。 条件文の最大ネスト数は 100 である。
.AIF ARG1 CMP ARG2
.AIF ARG1 CMP ARG2

有効な CMP 比較演算子で、文字列と絶対式で表されるものは、 以下の通りである:

EQ
ARG1ARG2 は等しいか?
NE
ARG1ARG2 は異なっているか?

有効な CMP 比較演算子で、絶対式のみで表されるものは、 以下の通りである:

LT
ARG1ARG2 より小さいか?
LE
ARG1ARG2 と等しいか、それより小さいか?
GT
ARG1ARG2 より大きいか?
GE
ARG1ARG2 と等しいか、それより大きいか?
.AELSE
条件文が失敗したときに実行されるアセンブリコードの最初の部分に含まれる印。 必須ではなく、(.AIF.AENDI の間の) 条件ブロックの中でのみ 与えられる。
.AENDI
/.AIF 条件ブロックの終りを示す。

ループ

これらの指示子はコードの部分を繰り返すことを許可する。
.AREPEAT EXPR
.AENDR

/.AREPEAT.AENDR の間のアセンブリコードを 絶対式 EXPR で指定された回数だけ繰り返す。
.AWHILE ARG1 CMP ARG2
.AENDW

/.AWHILE.AENDW の間のアセンブリコードを CMP 比較演算子の結果が true である限り繰り返す。 CMP のフォーマットは.AIF のものと同じである。
.EXITM
ループから抜け出す。

変数

変数には文字列、レジスタ、式の結果が入る。 2 種類の変数がある。

 .EQU.ASSIGN により定義される変数。 アセンブラコードの出力においてこの種の変数の値を求めるには、 単に変数名を書けばよい。 これらの変数はアセンブラコードの出力をしているときにのみ計算されるので、 条件式や .AWHILE ループの中に使うべきではない。

   foo  .EQU   FLIP-64
   bar: .EQU   FLIP-64
   mov.l  foo, r0

 前処理をしている間に使われる変数で、 .ASSIGNC.ASSIGNA によって定義される。 この種の変数の値を求めるには、`\&' を前に付ける。

   opcit  .ASSIGNA  47
   .AWHILE \&opcit GT 0
   .AENDW

マクロ変数はほとんど同じ方法で扱われるが、 それらの値を求めるには、代わりに `\' を前に付ける。

PVAR .EQU EXPR
プリプロセッサ変数 PVAR に式 EXPR の値を割り当てる。再定義には、制限はない。
PVAR .ASSIGN EXPR
/.EQU と似ているが、PVAR は再定義できない。
PVAR .ASSIGNA AEXPR
前処理の間使用され、数値を定義する。 AEXPR は絶対式でなくてはならない。再定義には、制限は無い。
PVAR .ASSIGNC STR
前処理の間使用され、文字列の値を定義する。再定義には、制限はない。
PVAR .REG (REGISTER)
レジスタと同じ働きをする変数を定義する。 特に、REGISTER は式としては計算されない。 再定義には、制限はない。

これら全ての指定は、変数名として左端にある "ラベル" を受け入れる。 必要なら、上の `bar' のように、変数名の後ろにコロンを付けてもよい。

マクロ定義

.MACRO.ENDM の指示子により、 アセンブラコードの出力を生成する独自のマクロを定義出来る。
.MACRO NAME
.MACRO NAME [ARG[=DEFAULT_VALUE], ...]
NAME というマクロの定義を開始する。もしマクロの定義で引数が必要なら、 コンマかスペースで区切ってマクロの名前のあとにそれらの名前を書く。 マクロ引数のデフォルトの値は、 /ARG=VALUE というフォーマットで指定する。

マクロを呼び出すとき、引数の値をポジションかキーワードで指定できる。 たとえば、`SUM 9, 17' は `SUM TO=17, FROM=9' と同じである。 マクロ引数は .ASSIGNA.ASSIGNC で定義した値と同等なので、 それらをループのコントロールや条件式として使える。 異なっているのは、変数の値を求めるときに接頭語として付ける記号だけである : マクロ引数には `\ARG' を使い、 プリプロセッサ変数には `\&VAR' を使う。

NAME .MACRO
NAME .MACRO ( [ARG[=DEFAULT_VALUE], ...] )
マクロを定義する別の形式 : ラベル位置にマクロの名前を、 名前の後のかっこ内にすべての引数を指定する。
.ENDM
マクロ定義の終りの印。
.EXITM
現在のマクロ定義や、マクロループから抜け出す。
\@
この疑似変数は、gasp がマクロをいくつ実行したかを表す。 この変数はマクロ定義の中でのみ使うことができる。
LOCAL NAME[, NAME...]
NAME 毎に固有の文字列を生成し、 マクロ展開において NAME のインスタンスを置き換える。

文字列はマクロ展開毎に異なったものになるので、 マクロ展開の間で衝突する恐れなしに、 シンボルを定義するマクロを書くことができる。

これは --alternate を指定している時のみ有効である。

データ

これらの指示子は、メモリのワーキングエリアを指定する。 メモリを初期化する指示子は、以下の通りである:
.DATA EXPR[, EXPR...]
.DATA.B EXPR[, EXPR...]
.DATA.W EXPR[, EXPR...]
.DATA.L EXPR[, EXPR...]
EXPR 式の数値を計算し、一致する as 指示子 (LAB でラベルされている) を発行する。 無指定の .DATA.longを発行し、.DATA.B.byte を、 /.DATA.W.short を、.DATA.L.long を発行する。

例えば、`foo .DATA 1,2,3' は `foo: .long 1,2,3' を発行する。

.DATAB REPEAT, EXPR
.DATAB.B REPEAT, EXPR
.DATAB.W REPEAT, EXPR
.DATAB.L REPEAT, EXPR
(as 指示子 .fill を使って) 式 EXPR の値を /REPEAT 個作る。REPEAT は絶対値の絶対式である。 /.DATAB.B は 1 byte の値を作り、 /.DATAB.W は 2 byte の値を、.DATAB.L は 4 byte の値を作る。 サフィックス無しの .DATAB は、 ちょうど .DATAB.L と同じように 4 byte の値を作る。
.SDATA STR...
文字列のデータ。 (.SDATAZ と違い、文字列終わりの印はない) コンマ区切りのそれぞれの STR 引数の連続するバイトを発行する。
.SDATAB REPEATSTR...
繰り返された文字列のデータ。 いくつ発行されるかを特徴付ける。 STR 引数を何回発行するかを、REPEAT で指定する。
.SDATAZ STR...
NUL 文字で終端された文字列のデータ。.SDATA と同様だが、 最後に NUL 文字一つが書かれている点が異なる。
.SDATAC STR...
長さの数値が前に付いた文字列データ。 .SDATA と同様だが、文字列の前に 1 byte の数値がある。 例えば、`.SDATAC "HI"' は `.byte 2,72,73' を生成する。数値フィールドが 1 byte だけなので、.SDATAC は 256 byte 以下の長さの 文字列に対してのみ使える。

.RES, .SRES, .SRESC, .SRESZ 指示子はメモリを初期化せず予約しておくために使う。 gasp はこれらの指示子を、GNU as .space 指示子の適切なコールとして解決する。

.RES COUNT
.RES.B COUNT
.RES.W COUNT
.RES.L COUNT
/COUNT 用の初期化されていないデータ要素のためのメモリを予約する。 サフィックスはそれぞれの要素の大きさを指定している : /.RES.BCOUNT byte を予約し、 .RES.WCOUNT byte のペアを予約し、そして .RES.LCOUNT の 4 つ組を予約する。 サフィックス無しの .RES.RES.L に等しい。
.SRES COUNT
.SRES.B COUNT
.SRES.W COUNT
.SRES.L COUNT
.SRES.RES と同義である。
.SRESC COUNT
.SRESC.B COUNT
.SRESC.W COUNT
.SRESC.L COUNT
/.SRES と同じようなものだが、`COUNT+1' 要素のメモリを予約する。
.SRESZ COUNT
.SRESZ.B COUNT
.SRESZ.W COUNT
.SRESZ.L COUNT
.SRESZ.SRESC と同義である。

リスト

これらの指示子は as の list 指示子をコントロールする。
.PRINT LIST
.PRINT NOLIST
.list.nolist をその引数に従って発行する。
.FORM LIN=LN
.FORM COL=COLS
.FORM LIN=LN COL=COLS
アセンブルリストのためのページサイズ、 LNCOLS 桁 (デフォルトは 60x132) を指定する。 行と列の一方または両方を指定できる。 /.FORM の前の例で示されたどんな値でも、デフォルトとはならない。 .psizef は GNU as 指示子を発行する。
.HEADING STRING
STRING は、アセンブリリストのタイトルになる。 `.title "STRING"' を発行する。
.PAGE
アセンブリリストで新しいページに強制する。.eject を発行する。

その他のコマンド

.ALTERNATE
アセンブリの中で別のマクロ文法をこれ以降は使用する。
.ORG
このコマンドは認識されるが、まだ実装されていない。gasp は /.ORG を使用しているプログラムに対してエラーメッセージを出す。
.RADIX S
明示的に符号化の進数が指定されていない数値について、 デフォルトの基数 (radix) を指定する (デフォルトは D である)。 S は大文字小文字を区別しない。
.RADIX B
2 進数。
.RADIX Q
8 進数。
.RADIX D
10 進数。
.RADIX H
16 進数。
.EXPORT NAME
.GLOBAL NAME
NAME をグローバルに宣言する (.global NAME を発行する)。
.PROGRAM
無視される。
.END
それぞれのプリプロセッサファイルの最後の印。 ファイルの最後がこのコマンドなしで終っていた場合は、ワーニングが出る。
.INCLUDE STR
ファイル名 STR を /.INCLUDE 指示子で指定されている項目として処理する。 インクルードの最大の深さは 30 である。
.ALIGN SIZE
絶対式 SIZE を計算し、 .align evaluated_expression を発行する。

GASP の文法

(スペースかタブで、改行ではない) 空白で、 1 行が 3 つの部分に分かれている時は特に重要である。 空白はいくつあってもよい。

 最初の部分には、 必須ではない "ラベル" が必ず左寄せ (行頭には空白がない) で書かれる。 ラベルの後ろには、必須ではないコロンが付いている。

 いくつかの空白の後に 2 番目の部分があって、 そこには gaspas 指示子を含む。

 行中のそれ以降の部分は指示子の引数であり、 コンマか空白で区切られている。

特別な文法の印

gasp はいくつかの特別な印を認識する: コメントの境界を定めるもの、 次の行にステートメントを続けるもの、記号をその他のキャラクタと区別するもの、 テキストを出力に直接コピーするもの (一つの特別な印としては、`@f' はマクロの定義の中のみで使われる)。

どんなソースの行でも、その後ろに付いているものはコメントかもしれない。 コメントはクォートされないコメント文字 (デフォルトでは `!') から始まるか、エスケープされたコメント文字や 2 文字のコメント文字 (デフォルトでは、`\!' か `!!') で始まり、行末まで続く。 この 2 種類のコメント印は、取り扱いがわずかに違う :

!
1 文字のエスケープされてないコメント文字は gasp の出力の中にアセンブラコードのコメントを生成する。 gasp はどの様なプリプロセッサの変数 (マクロ引数や、その前に .ASSIGNA.ASSIGNC で定義された変数) でも計算する。 例えば、次のように始まるマクロ

   .MACRO  SUM FROM=0, TO=9
   ! \FROM \TO

は、第 1 行で呼んだマクロの値の出力を記録して、コメントとして吐き出す。

\!
!!
エスケープされたコメント文字か、2 文字のコメント文字は、 gasp のソースコメントの印である。 gasp はアセンブラコードの出力にこのようなコメントをコピーしない。

  ファイルの次の行に記述を続けるには、2 行目の先頭に `+' を付ける。 時々、ある特定の文字列を gasp に処理させたくないことがある。 gasp のソースから、その出力に 文字通りにコピーするには、`\(' をコピーしたい文字列の前に置き、 `)' を後ろに置く。 例えば、アセンブラコードの出力に `\!' 文字が欲しい時は、 `\(\!)' と書く。

プリプロセッサ変数と、その直後に続く数値の文字を分離するには、 シングルクォート (''') を書く。 例えば、`.SDATA "P'1"' は変数 P の値と数値の 1 とを連結した文字列になる。 (`P1' 自身がプリプロセッサ変数の有効な名前なので、 `\P1' と書いただけではこの結果は得られないだろう)

文字列定数と数値定数

文字列定数を書くには、2 通りの方法がある: 全くのテキストと数で示されたバイトの値である。 二重引用符 ("STR") の間で完全な文字列は指定される。 不等号記号 (<EXPR>) の間で絶対式として、 個々の NumericByte 値が指定される。 文字列を出力する指示子は、どんな種類のどんな命令でも、 結果を連結するのを許可する。

特定の進数での、あるいは最後の .RADIX 指示子によって現在選ばれる どんな進数の定数でも書ける。

特定の進数で数を書くためには、パターン `S'DDD' を使う: 進数指定文字 S の次にシングルクォートがあり、数字 DDD が続く。 進数指定文字は、.RADIXで指定できるものと一致する。

シンボル

gasp は英字または、`_' 、`$' から始まり、 同様に文字または数字が続いているようなシンボルやラベル名を認識できる。

有効なシンボルは、アルファベット・`_'・`$' から始まり、 これらの文字または数字が続く。

算術式

結果に依存した 2 つの式がある: 結果が定数 (つまり、それらは gasp が知らない値を含まない) となる 絶対式と、以下の形

   ADDSYM+CONST-SUBSYM

に変換できなければならない再配置可能式がある。 ここで ADDSYMSUBSYM は、不明な値のアセンブラシンボルであり CONST は定数である。

gasp の数値式は、C のルールにとても良く似ている。 優先順位を変える時に括弧を使える; そうでなければ、数値的な基本としては、次に記すような優先順位になる:

 1. 一つの引数 `+' (同一の場合), `-' (算術的に反対の場合), あるいは `~' (ビット否定)

 2. `*' (乗算) と `/' (除算)。 引数は、絶対式でなくてはならない。

 3. `+' (加算) と `-' (減算)。 少なくとも一つの項は絶対式でなくてはならない。

 4. `&' (ビットの AND)。両方の項は、絶対式でなくてはならない。

 5. `|' (ビットの OR) と、`~' (ビットの XOR。C における `^')。 両方の引数は、絶対式でなくてはならない。

文字列の基本

これらの関数を使って、 文字列 (gasp ステートメントの項にある) を計算できる:
.LEN(STR)
文字列 "STR" の長さを絶対式として計算する。 例えば、`.RES.B .LEN("sample")' は、 メモリの 6 byte を予約する。
.INSTR(STR, SEG, IX)
STR の中で、位置 IX より後ろの最初に出現する SEG を探す。 もし、SEGSTR 中で、位置 IX より後ろになければ、 結果は -1 になる。
.SUBSTR(STR, START, LEN)
STRSTART から始まって LEN byte まで伸びている部分文字列。

別のマクロ文法

--alternate オプションが指定されている時、 別のマクロ文法が gasp によって使われる。 この文法は、Phar Lap マクロアセンブラを想い出させるが、 これは、Phar Lap マクロのエミュレーションや、 それと似ているアセンブラであるという事を意味してはいない。 特に、gasp は DB や IRP のような指示子をサポートしていない。

 プリプロセッサ指示子を `.' ドットを前に置かずに使える。 例えば、`SDATA' と .SDATA' を同じ効果のものとして書ける。

 LOCAL が有効になっている。

 文字列の境界を、 "STRING", 'STRING', <STRING> のように書ける。

 文字列の中のどんな文字も文字通りに取り込むために、 (たとえその文字が他に特別な意味を持っていたとしても) `!' を文字の前につけられる。例えば、`"hello !"world!""

 %EXPREXPR 式の数値を求めるために書くことが出来、 その結果は文字列として使用できる。

gasp

           .MACRO  saveregs from=8 to=14
   count   .ASSIGNA \from
           ! save r\from..r\to
           .AWHILE  \&count LE \to
           mov     r\&count,@-sp
   count   .ASSIGNA  \&count + 1
           .AENDW
           .ENDM
           saveregs from=12
   bar:    mov     #H'dead+10,r0
   foo     .SDATAC "hello"<10>
           .END

を与えると、下の GNU as のコードを生成する:

           ! save r12..r14
           mov     r12,@-sp
           mov     r13,@-sp
           mov     r14,@-sp
   bar:    mov     #57005+10,r0
   foo:    .byte   6,104,101,108,108,111,10

注意

バグは <[email protected]> と <[email protected]> にレポートして欲しい。
man ページは Ragnar Hojland Espinosa <[email protected]> によって書かれた。