 Assembler course part 2

 by Wanja Gayk

 Hi everyone! I hope you got along well with the first part
 and that you still want to go on. This time we're going to
 really start off. So get your monitors warmed up! Let's
 recall the program from last course in which we switched the
 color of frames and the background from black to white and
 back again. It looked like this (you had to start it with
 SYS 8192 from BASIC or G 2000 from your ML monitor):

 .A2000 LDA #$00        ; value of black into the
 accumulator,
 .A2002 STA $D020    ; loads value of accumulator into
 register for frame colors,
 .A2005 STA $D021    ; loads value of accumulator into
 register for background colors,
 .A2008 LDA #$01        ; value of white into the
 accumulator,
 .A200A STA $D020    ; loads value of accumulator into
 register for frame colors,
 .A200D STA $D021    ; loads value of accumulator into
 register for background colors,
 .A2010 JMP $2000    ; jump back to $2000

 Of course there's a much easier way to do this - because you
 have various registers: accumulator, X and Y. Load and Store
 commands exist also for the X and Y registers. They are
 called LDX, STX and LDY, STY. LDX means LoaD X, STX means
 STore X. LDY and STY, respectively, are short for LoaD Y and
 STore Y. We can use them in the same simple way we used LDA
 and STA earlier on. Here's a short program:

 .A2000 LDX #$00        ; loads $00 (black) into the X
 register,
 .A2002 LDY #$01        ; loads $01 (white) into the Y
 register,
 .A2004 STX $D020    ; value of X register into the register
 for frame colors,
 .A2007 STX $D021    ; value of X register into the register
 for background colors,
 .A200A STY $D020    ; value of Y register into the register
 for frame colors,
 .A200D STY $D021    ; value of Y register into the register
 for background colors,
 .A2010 JMP $2004    ; jump back to $2004

 Now, where's the difference? Seemingly there is none - the
 program even has the same length - but it operates faster.
 That's because there are fewer commands in its loop to
 change the color from black to white. Compare: the first
 program has seven commands (including JMP) in its closed
 loop. Program No.2 has only five of them - by the way, it is
 one of the fastest programs possible to implement that
 effect. Let's now try a different approach to the program,
 so that we can learn some new commands. We'll stick to the
 same effect not to loose track. We' ll focus exclusively on
 the X register, and the commands we need now are INX and
 DEX.

 INX/INY

 INX stands for INcrement X. It increases the value of X by
 one. If the value in the X register is $fd (253), INX will
 raise it to $fe (254). If we use another INX the value will
 increase to $ff (255). But we know that the accumulator, X
 and Y register only have a capacity of one byte, which is
 only fit for representing a value of $00 up to $ff. When
 trying to increase a value of $ff once more the processor
 will start again at $00, so there's no problem. In the 6510,
 the same command is also available for the Y register (INY
 for INcrement Y), but not for the accumulator.

 DEX/DEY

 DEX stands for DEcrement X and has the opposite effect of
 INX. It decreases the value of the X register by one. If the
 value in the X register is $02, DEX will lower it to $01. If
 we use DEX once more $01 will be decreased to $00. Again,
 the value will jump back and the processor will start
 counting at the other end of the scale if we try to decrease
 it once more and a value of $00 will be turned into $ff. The
 corresponding command for the Y register is DEY (DEcrement
 Y).

 Let's write a short program using these two commands:

 .A2000 LDX #$00    ; loads $00 into the X register (black),
 .A2002 STX $D020    ; X register into frame color,
 .A2005 STX $D021    ; X register into background color,
 .A2008 INX        ; increases value of X register by one
 ($00 turns into $01 - white),
 .A2009 STX $D020    ; X register into frame color,
 .A200C STX $D021    ; X register into background color,
 .A200F DEX        ; decreases value of X register by one
 ($01 turns into $00 - black),
 .A2010 JMP $2002    ; and we start again at $2002

 This program is of the same length as the previous ones and
 has the same effect - but it only works as fast as the first
 one because there are seven commands in the loop that have
 to be executed, with INX and DEX taking up as much time as
 LDA - just to tell you. Now, wouldn't it be nice if we could
 increase or decrease values directly in the main storage? Of
 course this is also possible by using INC and DEC. INC and
 DEC work the same way as INX and DEX, with the difference
 that affect the contents of one single storage location,
 rather than the contents of the X or Y register. INC means
 INCrement and DEC DECrement. The next program shows the
 practical application:

 .A2000 LDA #$00
 .A2002 STA $D020    ; frame color black,
 .A2005 STA $D021    ; background color black,
 .A2008 INC $D020    ; adds one to frame color (= $01 -
 white),
 .A200B INC $D021    ; adds one to background color (= $01 -
 white),
 .A200E DEC $D020    ; subtracts one from frame color (= $00
 - black),
 .A2011 DEC $D021    ; subtracts one from background color (=
 $00 - black),
 .A2014 JMP $2008    ; jump back to $2008

 This program is a little longer than the previous ones due
 to the fact that both storage cells first have to be
 initialized with $00 in order to be able later on to change
 between $00 and $01. Even though the program's loop consists
 of only five commands this program is slower than any of the
 others, since INC as well as DEC take up six clock cycles
 each. LDA, LDX and LDY in comparison use only two, STA, STX
 and STY take up four clock cycles, INX/INY and DEX/DEY also
 use only two while JMP swallows up three clock cycles. These
 numbers are only valid for the commands already introduced
 as there are different variants of LDA and STA commands.
 This leads us to our last programs for today, for which
 we'll need two new commands.

 LDA (X-indexed) and LDA (Y-indexed)

 LDA $3000, X is a great command to read tables. It loads the
 content of the storage cell $3000 plus X into the
 accumulator. The X register is used as, well, an index. If X
 = $00, then the content of the storage cell $3000 will be
 read, if X = $35 the value will come from the storage cell
 $3035, and so on. The same thing works also for the Y
 register - with the command LDA $3000, Y.

 BEQ (Branch if EQual), BNE (Branch if Not Equal) and the
 ZERO-FLAG

 BEQ is a command that effects a jump similar to JMP, but
 only if certain conditions are fulfilled, that is, if the
 so-called ZERO-FLAG is set. BNE also jumps, but only if the
 ZERO-FLAG is clear. The ZERO-FLAG is a processor bit with
 which the value of a command resulting in zero is marked.
 That is, if you execute a DEX while a value of $01 is in the
 X register, the result will be $00, and therefore the
 ZERO-FLAG will be set. This is also true if DEC results in
 $00 or if $ff is turned into $00 by INX, INY or INC. The
 ZERO-FLAG will also be set if LDA #$00, LDX #$00 or LDY #$00
 are executed. If you load a value of $00 from main storage
 into the accumulator with an LDA, LDX, or LDY, the ZERO-FLAG
 will be set. It is cleared if the result of a command does
 not equal zero. The following short program is to clarify
 the way it works:

 .A2000 LDX #$04        ; loads X register with $04,
 .A2002 STX $D020    ; value from X register into frame
 color,
 .A2005 DEX         ; decreases X by one,
 .A2006 BNE $2002    ; jump to $2002 if result is not zero,
 .A2008 BEQ $2000

 This is what the program does: the X register is loaded with
 $04 which then goes into the frame color (setting the frame
 color to cyan). X is then decreased by one (X is now $03).
 As DEX resulted not in $00 but in $03 BNE jumps to $2002,
 which now sends the value of X (= $03) into the register for
 the frame color (now, it's red). Now X is decreased once
 more. DEX has still not reduced X to $00, therefore the
 program jumps back to $2002 where the value of X (= $02)
 again is loaded into the frame color. This process continues
 until DEX has decreased the value of the X register to $00,
 which is when the processor will automatically set the
 ZERO-FLAG. But as BNE only jumps on the condition that the
 ZERO-FLAG is CLEAR (that is, that the last operation
 resulted in something other than a zero), the program
 continues to $2008. The following command, BEQ $2000, only
 jumps if the ZERO-FLAG is set - which must the case,
 otherwise BNE would have jumped before. So BEQ carries us
 back to $2000 where the program starts anew. Now what effect
 does this program have on the screen? Same as this one:

 .A2000 LDA #$04
 .A2002 STA $D020
 .A2005 LDA #$03
 .A2007 STA $D020
 .A200A LDA #$02
 .A200C STA $D020
 .A200F LDA #$01
 .A2011 STA $D020
 .A2014 JMP $2000

 The difference is that the program that works with jumps
 controlled by certain conditions is much shorter. But now
 let's look at our last program with which we're going to
 read a table for the first time. First, type this nice
 little table:

 .M3000 06 06 04 04 0E 0E 03 03
 .M3008 0D 0D 01 0D 0D 03 03 0E
 .M3010 0E 04 04 06 06 00 00 00
 .M3018 01

 What you did just now was to set up a table of color values
 which occupies storage locations $3000 to $3018, and which
 we're now going to use to have the screen change to these
 colors. The program looks like this:

 .A2000 LDX #$19        ; number of colors plus one into the
 X register,
 .A2002 LDA $2FFF, X    ; loads value of $2fff into the
 accumulator (table starts at $3000)
 .A2005 STA $D020    ; value of the accumulator into frame
 color,
 .A2008 STA $D021    ; value of accumulator into background
 colors,
 .A200B DEX        ; decreases X register by one,
 .A200C BNE $2002
 .A200E BEQ $2000

 Well, how does this program work? It starts with the last
 value of the table and continues to the first one, loading
 the values from the table into the registers for frame and
 background colors. The X register is used to proceed from
 one value to the next in the table. First, X is loaded with
 #$19 so that LDA $2FFF,X loads the last value from the
 table, which will come from storage location $3018 ($2FFF +
 X, X=$19), into the accumulator. The value of the
 accumulator is then loaded into the screen colors ($D020 and
 $D021). Then X is decreased by one, which results in $18 in
 the second run. Since $18 does not equal $00, the BNE jumps
 to $2002. At that point, the value from $3017 ($2FFF + $18)
 is loaded into the screen colors ... and so forth.

 The interesting part of this comes when X reaches a value of
 $01. At this point, the first value of the table is read,
 which is $3000. This value is now loaded into the screen
 colors and X is decreased by one - to $00. Logically, the
 BNE does not jump anymore. If the command had been LDA
 $3000,X we now wouldn't be able to read the first value of
 the table. In any case, BNE is ignored because the ZERO-FLAG
 is set. But the following BEQ jumps to the beginning of the
 program at $2000 due to the ZERO-FLAG - and we're back in
 our old familiar closed loop.

 In the next part we will dedicate ourselves to finding out
 if we can achieve some even nicer effects concerning tables
 and colors - and by the way we'll have the chance to try
 some great new commands. Hope you're looking forward to it,
 see you next time!
