Tatara

第17章
繰り返しブロック

繰り返しブロック(repeat block)は、TATARAがその場で繰り返す行のまとまりです。その場で定義して使う、名前のないマクロのように働きます。REPTは指定した回数だけ、IRPはリストの項目ごとに1回ずつ、IRPCはテキストの文字ごとに1回ずつ、その行を繰り返します。

3つとも、マクロと同じようにENDMで終わり、本体、LOCAL、EXITMについては16章の規則に従います。

17.1 REPT

REPTのあとには回数を書きます。ENDMまでの行が、その回数だけアセンブルされます。

                cseg 
here:           rept    3 
                nop 
                endm 
                dw      here
 
                                here:           rept    3 
                                                nop 
                                                endm 
  0000'   00              +                     nop 
  0001'   00              +                     nop 
  0002'   00              +                     nop 
  0003'   00 00                                 dw      here
 

リスティングには、書いたとおりのブロックに続いて、それぞれの回が、マクロの展開と同じように+の印付きで表示されます。REPTの行のラベルは、最初の回の始まりを示します。hereは0000hです。

回数にはどんな式でも書けますが、TATARAはブロックの行を読む前にそれを計算するので、すでにわかっている数でなければなりません。あとで定義される名前を使うと、TATARAはundefined symbol in an expression.と表示して止まり、コード・セグメントのラベルのようなリロケータブルな値を使うと、8章のリロケーション・エラーで止まります。回数が0なら、何もアセンブルされません。

DEFL(12章)がいちばん役に立つのは、繰り返しブロックの中です。DEFLで定義した名前には回ごとに新しい値を与えられるので、回数を数えられます。

n               defl    0 
                rept    4 
                db      n 
n               defl    n+1 
                endm
 
  0000'   00              +                     db      n 
  0001'   01              +                     db      n 
  0002'   02              +                     db      n 
  0003'   03              +                     db      n
 

リスティングにはそれぞれの行が書いたとおりdb nと表示され、バイトはその回でのnの値を示しています。

17.2 IRP

IRPのあとには、パラメーター名、コンマ、山かっこで囲んだ項目のリストを書きます。ブロックは項目ごとに1回ずつ、パラメーターをその項目に置き換えてアセンブルされます。

                irp     x,<1,2,4,8> 
                db      x 
                endm
 
  0000'   01              +                     db      1 
  0001'   02              +                     db      2 
  0002'   04              +                     db      4 
  0003'   08              +                     db      8
 

項目は、マクロの引数と同じ規則に従います(16.2節)。コンマを含む項目は、それ自身の山かっこで囲みます。また、%を付けると、テキストの代わりに値が渡されます。

five            equ     5 
                irp     s,<'ab',<'c,d'>> 
                db      s 
                endm 
                irp     v,<five*2,%five*2> 
                db      '&v' 
                endm
 
  0005'   61 62           +                     db      'ab' 
  0007'   63 2C 64        +                     db      'c,d' 
  000A'   66 69 76 65     +                     db      'five*2' 
  000E'   2A 32           + 
  0010'   31 30           +                     db      '10'
 

リストを囲む山かっこは省略できます。irp x,1,2,3はirp x,<1,2,3>と同じです。空のリストirp x,<>では、パラメーターが空のまま1回実行されます。

IRPがいちばん役に立つのは、マクロの中で、それ自体がリストである引数に対して使うときです。

bytes           macro   list 
                irp     b,<list> 
                db      b 
                endm 
                endm
 
                                                bytes   <10,20,30> 
  0000'   0A              +                     db      10 
  0001'   14              +                     db      20 
  0002'   1E              +                     db      30
 

17.3 IRPC

IRPCのあとには、パラメーター名、コンマ、テキストを書きます。ブロックはテキストの文字ごとに1回ずつ、パラメーターをその文字に置き換えてアセンブルされます。マクロと同じように、文字列の中のパラメーターには&が必要です(16.3節)。

                irpc    c,TATARA 
                db      '&c' 
                endm
 
  0000'   54              +                     db      'T' 
  0001'   41              +                     db      'A' 
  0002'   54              +                     db      'T' 
  0003'   41              +                     db      'A' 
  0004'   52              +                     db      'R' 
  0005'   41              +                     db      'A'
 

空白やコンマも含めて、すべての文字が数えられます。irpc c,<A B,C>は、A、空白、B、コンマ、Cの 5回になります。山かっこはテキストに空白を入れるときにだけ必要で、テキストには含まれません。空のテキストirpc c,<>では、1回も実行されません。IRPCのテキストでは、!と%に特別な意味はありません。

17.4 LOCAL、EXITM、入れ子

LOCALは、繰り返しブロックでもマクロと同じように働き、回ごとに別の名前を与えます。

                rept    2 
                local   skip 
                jr      skip 
                nop 
skip: 
                endm
 
  0000'   18 01           +                     jr      ??0000 
  0002'   00              +                     nop 
  0003'   18 01           +                     jr      ??0001 
  0005'   00              +                     nop
 

LOCALがなければ、2回目でskipをもう一度定義することになります。ラベルだけの行はバイトを作らないので、展開には表示されません。

EXITMは、まだ実行していない回も含めて、ブロック全体を終わらせます。次のブロックは10回実行されるはずですが、3回で止まります。

n               defl    0 
                rept    10 
                if      n eq 3 
                exitm 
                endif 
                db      n 
n               defl    n+1 
                endm 
                db      0ffh
 
  0000'   00              +                     db      n 
  0001'   01              +                     db      n 
  0002'   02              +                     db      n 
  0003'   FF                                    db      0ffh
 

繰り返しブロックは、ほかの繰り返しブロックやマクロの中に入れることができ、それぞれのENDMはいちばん内側のものを終わらせます。マクロの展開やインクルード・ファイルと合わせて、16段まで重ねられます(16.7節)。

17.5 メッセージ

繰り返しブロックについてのメッセージを、それぞれの原因となる行とともに表17.1に示します。繰り返しブロックの中でエラーが起きると、メッセージのあとの経路にはブロックがa repeat blockと表示されます。

行

メッセージ

rept count
(countはあとで定義)

undefined symbol in an expression.

rept start
(startはコード・
セグメントのラベル)

relocation error - a segment-relative value is not allowed here.

irp x
(コンマがない)

bad macro parameter list.

ENDMのない
繰り返しブロック

macro definition not closed by ENDM.

表 17.1: 繰り返しブロックについてのメッセージ