Chapter 17
Repeat blocks
A repeat block is a group of lines that TATARA repeats where it stands. It works like a macro without a name, which is defined and used in the same place. REPT repeats its lines a given number of times, IRP once for each item in a list, and IRPC once for each character in a piece of text.
All three end with ENDM, as a macro does, and follow the rules of chapter 16 for their body, for LOCAL and for EXITM.
17.1 REPT
REPT is followed by a count, and the lines up to ENDM are assembled that many times:
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
The listing shows the block as it was written, then each round, marked + as in a macro expansion. A label on the REPT line names the start of the first round: here is 0000h.
The count can be any expression, but TATARA works it out before it reads the lines of the block, so it must be a number TATARA already knows: a name defined further down stops TATARA with undefined symbol in an expression., and a relocatable value, such as a label in a code segment, with the relocation error of chapter 8. A count of 0 assembles nothing.
A repeat block is where DEFL (chapter 12) is most useful. A name defined with DEFL can be given a new value in each round, and so can count the rounds:
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
The listing shows each line as it was written, db n, and the bytes show the value n had in that round.
17.2 IRP
IRP is followed by a parameter name, a comma, and a list of items between angle brackets. The block is assembled once for each item, with the parameter replaced by that item:
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
The items follow the rules of a macro’s arguments (section 16.2). An item that holds a comma is written between angle brackets of its own, and % passes a value instead of text:
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'
The angle brackets round the list can be left out: irp x,1,2,3 is the same as irp x,<1,2,3>. An empty list, irp x,<>, gives one round, with the parameter empty.
IRP is most useful inside a macro, over an argument that is itself a list:
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 is followed by a parameter name, a comma, and a piece of text. The block is assembled once for each character of the text, with the parameter replaced by that character. As in a macro, a parameter inside a string needs & (section 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'
Every character counts, spaces and commas included: irpc c,<A B,C> gives five rounds, for A, a space, B, a comma and C. The angle brackets are needed only to keep a space in the text, and are not part of it. An empty text, irpc c,<>, gives no rounds at all. ! and % have no special meaning in the text of IRPC.
17.4 LOCAL, EXITM and nesting
LOCAL works in a repeat block as in a macro, and gives each round names of its own:
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
Without LOCAL, the second round would define skip again. A line that holds only a label produces no bytes, and is not shown in the expansion.
EXITM ends the whole block, including the rounds that have not run yet. This block would run ten times, but stops after three:
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
Repeat blocks can be put inside each other and inside macros, and each ENDM ends the innermost one. Together with macro expansions and include files, they can be 16 deep (section 16.7).
17.5 Messages
Table 17.1 lists the messages about repeat blocks, each with the line that causes it. When an error happens inside a repeat block, the trail that follows the message names it as a repeat block.
Line |
Message |
rept count, count defined further down |
undefined symbol in an expression. |
rept start, start a label in a code segment |
relocation error - a segment-relative value is not allowed here. |
irp x, with no comma |
bad macro parameter list. |
| macro definition not closed by ENDM. |