Using REPT and IRP

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.

A REPT that acts like dup

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).

A REPT to allocate and initialize data with different values

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.

A REPT to give each byte a unique 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

Placing a REPT inside a macro

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
	

An IRP to allocate and initialize data with different values

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

Placing an IRP inside a macro

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

A for loop using IRP

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>\
>