Basil’s Compendium

Publication: SyncWare News
Pub Details: SyncWare News v4 n6 (Volume 4, Issue 6)
Date: July/August 1987
Pages: 18

FOR…NEXT

This chapter will treat the machine code equivalent of the FOR…NEXT loop, and introduce the four “packaged loops” whose mnemonics end in “R”.

You may have noticed that Chapter 12 incorporated the equivalent of a FOR…NEXT loop in some of its examples. For instance, Figure 12-3 could just as well have been expressed as a loop, as shown in Figure 13-1.

1010 LET N=2
1020 FOR A=1 TO 3
1030 LET N=N+2
1040 NEXT A
1050 PRINT A

Figure 13-1. The explicit loop

One technique that is often used in machine code to implement a loop is to load some register with the number of times the loops is to be executed, and to decrement that counter each time the program goes through the loop, terminating when the register has cownted down to zero. Look at Table 12-2 when you’re choosing the register to act as counter–notice that it has to be a one-byte register, if you’re going to use DEC for keeping count. You could use a two-byter along with SUB or SBC, but that gets a little bit more complicated.

A PROBLEM

Use this technique to write a program that will calculate the fifth power of 2. You will find an answer in Figure 13-2. As always, your answer may be different–there are lots of possible solutions. And again as always, try for the most elegant solution you can find.

16514  22  -      LD D,5
16515 5 Gr 5
16516 62 Y LD A,1
16517 1 Gr 1
16518 135 Gr 3 ADD A,A
16519 21 + DEC D
16520 32 4 JR NZ,-4
16521 252 UNPLOT
16522 6 Gr T LD B,0
16523 0
16524 79 ? LD C,A
16525 201 TAN RET

Figure 13-2. The fifth power of 2

PACKAGED LOOPS

Some instructions have loops built into them; notably:

LDIR-repeat block load with INC
LDDR-same, with DEC
CPIR-block CP with INC
CPDR-same, with DEC

The codes for these instructions are given in Table 13-1.

We aren’t going to give you any practice exercises with these instructions at this time. You can see LDIR at work in Figure 9-1 of this series. It is also well worth while studying the use of this family in Tom Woods‘s excellent PRO/FILE manual. We will, however, describe their operation in enough detail so you should be able to use them when the occasion arises.

LDIR  237,176
LDDR  237,184
CPIR  237,177
CPDR  237,185

Table 13-1. The packaged loops

Let’s see how LDIR works. It’s called a block transfer function, and it moves the contents of a block of consecutive bytes to a block of memory at some other address. You designate the address of the first byte of the source, the address of the first byte of the destination, and the number of bytes to be moved. One handy use for such an instruction would be to move a block of machine code from one address to another.

To use LDIR, you load HL with the current address of the first byte of the block you want to move, and load DE with the address of the first byte of the block you’re going to move into. BE SURE THAT YOU HAVE MADE RESERVATIONS AT THE NEW ADDRESS–anything you have there will be overwritten, and the program may even crash if you destroy some of the data that the computer needs to keep itself sane. The safest approach is to make sure that there is a block of nulls at the new address–a block big enough to hold all of the stuff that you’re planning to move in.

It’s easy enough to remember which register does which during an LDIR maneuver. Just remember that DE stands for destination. HL, then, could stand for the “hole” that’s going to be left after the data is moved out. Except that it won’t really be a hole, of course. The bytes of data aren’t actually removed; they’re just copied at the new address. Just as LET B=A in BASIC doesn’t affect A at all, but only sets B equal to A.

So much for DE and HL. The only other two-byte register, BC, serves as the counter. If you can’t remember it by default, think of “abacus”.

When the LDIR sequence is triggered, the whole transaction takes place in “less than a fraction of a second”, as my son likes to say.

CPIR works in much the same way, except that it CP’s each byte of data (compares it with the contents of the “A” register) instead of moving it.

LDDR and CPDR do the same things respectively, except that they start at the top address and work down. One possible use for LDDR that immediately comes to mind is the situation where you need more bytes at the beginning of your block of machine code bytes, so you must move the existing bytes forward as far as you need. A simple thing to do when you’re using 1 REM to carry your machine code, but a little more complicated if the code is buried somewhere within the program.

Well, that’s all for now. There will be more.

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.