!lm10
!rm76
Loops

When you want to program repetitive code in, you write a FOR-NEXT loop or an IF loop.  For example, you might write:

     10 FOR I = 1 TO 10     or:  10 I=0
     20 ...                      20 I=1+1 : IF I > 10 THEN 100
     30 NEXT I                   30 ...
                                 90 GO TO 20
                                 100

How do you do it in assembly language?

Loop Variable in X or Y

One of the simplest kind of loops holds the loop variable in the Y- or X-register, and decrements it once each trip.

     LOOP   LDY #10    Loop for Y = 10 to 1
     .1     ...
            DEY
            BNE .1

Note that the loop variable is in the Y-reigster, and that it counts from 10 to 1, backwards.  When the DEY opcode changes Y from 1 to 0, the loop terminates.

If you want the loop to execute one more time, with Y=0, change it to this:

     LOOP   LDY #10    Loop for Y = 10 to 0
     .1     ...
            DEY
            BPL .1

Of course, a loop count of 129 or more would not work with this last example, because Y would look negative after each DEY until the value was less than 128.

If you want the loop variable to run up instead of down, like from 0 to 9, you need to add a comparison at the end of loop:

     LOOP   LDY #0     Loop for Y = 0 to 9
     .1     ...
            INY
            CPY #10
            BCC .1     Carry clear if Y < 10

All the examples above use the Y-register, but you can do the same thing with the X-register.  In fact, using the X-register, you can nest one loop inside another:

     LOOPS  LDY #0     FOR Y = 0 TO 9
     .1     LDX #10    FOR X = 10 TO 1 STEP 1
     .2     ...
            DEX
            BNE .2     NEXT X
            ...
            INY
            CPY #10    NEXT Y
            BCC .1


Loop Variable on Stack

Sometimes X and Y are needed for other purposes, and so I use the stack to save my loop variable.  Also, the step size can be larger than 1.

!lm15
LOOP   LDA #0    FOR VAR=5 TO 15 STEP 3
.1     PHA       SAVE VAR ON STACK
       ...
       PLA       GET VAR FROM STACK
       CLC
       ADC #3    ADD STEP SIZE
       CMP #16
       BCC .1    VAR <= 15

!lm10
In the Apple Monitor ROM there is a double loop using the stack to hold one of the variables.  It is used just for a delay loop, with the length of delay depending on the contents of A when you call it.  It is at $FCA8.
!lm15

WAIT   SEC
.1     PHA       outer loop
.2     SBC #1    ...inner loop
       BNE .2    ...next
       PLA
       SBC #1
       BNE .1    next
       RTS

!lm10
The outer loop runs from A down to 1, and the inner loop runs from whatever the current value of the outer loop variable is down to 1.  The delay time, by the way, is 5*A*A/2 + 27*A/2 + 13 cycles.  (A cycle in the Apple II is a little less than one microsecond.)

16-bit Loop Variables

What if you need to run a loop from $1234 to $2345?  That is a little trickier, but not too hard:
!lm15

LOOP  LDA #$1234    START AT $1234
      STA VARL
      LDA /$1234
      STA VARH
.1    ....
      INC VARL      NEXT: ADD 1
      BNE .2
      INC VARH
.2    LDA VARL
      CMP #$2346    COMPARE TO LIMIT
      LDA VARH
      SBC /$2346
      BCC .1        NOT FINISHED

!lm10
A good example of this kind of loop is in the monitor ROMs also.  The code for the end of loop incrementing and testing is at $FCB4-$FCC8.  The memory move command ("M") at $FE2C-$FE35 uses this.

Conclusion

There are as many variations on the above themes as there are problems and programmers.  Look around in the ROMs, and in programs published in AAL and other magazines; try to understand how the loops you find are working, and adapt them to your own needs. 
