The REPT directive will repeat a block of code a specified number of times. A REPT does not have a name, so it cannot be called like a macro. However, by placing a REPT inside a macro, the same effect can be created.
By placing this REPT in the .DATA segment, memory can be allocated.
REPT 10 db 0 endm
This would generate 10 bytes with the value 0. However, this is not very interesting, since it is the same as db 10 dup (0).
By using the = to create an assembler variable, it is possible to create and initialize bytes with different values.
value=0 REPT 10 db value value=value+1 endm
Now, this will create a block of ten bytes initialized with the values 0 .. 9.
This REPT could be used inside the data segment as follows
list label byte value=0 REPT 4 db value value=value+1 endm
And would generate the assembler statements
list label byte db 0 db 1 db 2 db 3
It is important that the label is not included inside the REPT, or else each db would have the same label.
It is possible to label each db with a different label, by appending the number to the label name.
list label byte value=0 REPT 4 list&value db value value=value+1 endm
This would generate the following assembler
list label byte list0 db 0 list1 db 1 list2 db 2 list3 db 3
To make this even more useful, place the REPT inside a macro so that it can be called repeatedly.
define macro count value=0 REPT count db value value=value+1 endm endm
Now this can be called several times.
list label byte define 4 define 3
It would generate the following assembler
list label byte db 0 db 1 db 2 db 3 db 0 db 1 db 2
The IRP is like the REPT, except that the IRP loops over the values that you send it. If you send four elements, then the IRP will loop 4 times. Here is the same macro as above using IRP instead of REPT
IRP arg,<argList> db arg endm
It would be called like the REPT
list label byte IRP arg,<0,1,2,3> db arg endm
It would generate the same assembler as above.
list label byte db 0 db 1 db 2 db 3
It seems like more work to get this to work, since each value must be listed within the <>. Howver, IRP has more flexibility than REPT. REPT is limited to initializations that can be generated by a formula, whereas IRP can repeat over arbitrary values. The following could not be done using a REPT
IRP arg,<5,15,8,2> db arg endm
It would generate
db 5 db 15 db 8 db 2
To make the IRP more versatile, place it inside a macro
create macro argList IRP arg,<argList> db arg endm endm
Then call it several times. You can call the define macro that uses REPT as well.
table label byte create <0,5,8> define 3 create <10,15,3,7>
Which would generate
table label byte db 0 db 5 db 8 db 0 db 1 db 3 db 10 db 15 db 3 db 7
This is the macro that was developed on the macro page. Here, the staement is expanded using an IRP so that more than one statement can be included in teh macro.
forloop macro start,stop,incr,statementList local top,done push ax mov ax,start top: cmp ax,stop jge done IRP statement,<statementList> statement endm add ax,incr jmp top done: pop ax endm
Now it could be called with more than one statement. This will add the loop control varaible in bx, and subtract it in cx.
xor bx,bx xor cx,cx forloop 20,5,-4,<<add bx,ax>,<sub cx,ax>>
It would generate
push ax mov ax,20 top1: cmp ax,5 jge done1 add bx,ax sub cx,ax add ax,-4 jmp top1 done1: pop ax
By using the statement continuation operator \, it is possible to make the call more readable.
xor bx,bx xor cx,cx forloop 20,5,-4,\ <\ <add bx,ax>,\ <sub cx,ax>\ >