**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!