MCS6500
Microcomputer Family
Programming Manual
CHAPTER 4
TEST, BRANCH AND JUMP INSTRUCTIONS
4.0 CONCEPTS OFPROGRAM SEQUENCE
In all the discussions up until now, there has been little discussion
about how the microprocessor understands the instructions used to
perform various arithmetic and accumulator manipulations. However, it
is appropriate that the concept of a program and how the microprocessor
determines each instruction be developed. More registers are required
in the machine as shown in the figure below.
Although two 8 bit registers have been added, they are the only
registers in the machine that act as though they are one 16 bit register.
They implement a concept known as program count or program
sequence and subsequently their value will be referred to as PC or
program count. In certain operations it may be convenient to talk
about how one affects the program count low (PCL) which will be the
lower 8 bit register or the program count high (PCH) which will be the
higher 8 bit register. The reason for this register being 16 bits in
length is that if it had only 8 bits it would only be able to reference
256 locations. Since it is through the address bus that one accesses
memory, the program counter which defines the addressable location,
should be as wide a word as possible.
The accessing of a memory location is called "addressing". It is
Lue selection of a particular eight-bit data word (byte) out of the
65,536 possibilities for memory data locations. This selection is transmitted
to the memory through the 16 address lines (ADH, ADL) of the microprocessor.
For a more detailed discussion of how an individual memory byte is
selected by the address lines, the reader is referred to Chapter 1 of
the Hardware Manual.
If the program counter was only 1 byte and if the bit pattern which
allows the microprocessor to choose which instruction it wants to act on
next, such as "LDA" as opposed to an "AND", was contained in one byte of
data we could only have 256 program steps. Although the machine of this
length might make an interesting toy, it would have no real practical
value. Therefore, almost all of the competitive 8 bit microprocessors
have chosen to go to a double length program counter. Even though some
of the microprocessors of the MCS650X family do not have all of the output
address lines necessary to allow the user to address 65K bytes of
program (due to package pinout constraints) , in all cases the program
counter is capable of addressing a full 65K by virtue of it's 16 bit
length.
4.0.1 Use of the Program Counter to Fetch an Instruction
The microprocessor contains an internal timing and state control
counter. This counter, along with a decode matrix, governs the
operation of the microprocessor on each clock cycle. When the state
of the microprocessor indicates that a new instruction is needed,
the program counter (program address pointer) is used to choose
(address) the next memory location and the value which the memory
sends back is decoded in order to determine what operation the
MCS650X is going to perform next.
To use the program counter to perform this operation correctly,
it must always be addressing the operation the user wants
to perform next. This operation may be an instruction or may be
data on which the instruction will operate.
In the MCS650X family, the program counter is set with the
value of the address of an instruction. The microprocessor then
puts the value of the program counter onto the address bus, transferring
the 8 bits of data at that memory address into the instruction
decode. The program counter then automatically increments by
one and the microprocessor fetches further data for address operation
necessary to complete the instruction. In the simple example below.
Example 4.1: Accessing Instructions with the P Counter Value
P Counter* Location Contents
0100** LDA *Program Counter
0101 ADC **Hexadecimal
0102 STA Notation
one can see how the program counter is used to access the instruction
sequence load A, add with carry, and store the result. In this
example, the program counter would start out containing 0100. The
microprocessor would read location 0100 by using the program counter
to access memory and would then interpret and implement the LDA instruction
as previously described. The program counter will automatically
increment by one on each instruction fetch, stepping to
0101. After performing the LDA, the microprocessor would fetch the
next instruction addressing memory with the program counter. This
would pick up the ADC instruction, the add would then be performed,
the program counter which has been incremented to 0102 would be used
to address the next instruction, STA. The P counter incrementing
once with each instruction is an oversimplified view of what actually
transpires within the microprocessor.
The MCS650X processors usually require more than one byte to
correctly interpret an instruction. The first byte of an instruction
is called the OP CODE and is coded to contain the basic operation
such as LDA (load accumulator with memory) and also the data necessary
to allow the microprocessor to interpret the address of the data
on which the operation will occur. In most cases, this address will
appear in memory right after the OP CODE byte. This allows the microprocessor
to use the program counter to access the address as well as
the OP CODE.
The following example shows how the program counter picks up
the instruction and the address of data located at address 5155.
Example 4.2: Accessing Data Address With P Counter Value
P Counter Location Contents
0100 LDA
0101 55
0102 51
0103 Next Instruction
The OP CODE appears in Location Address 0100. The code for the 55
would appear next in Location Address 0101 and the 51 would appear
in Location Address 0102, and the OP CODE for the next instruction
appears in Location Address 0103. In this example, we see that the
program counter is used not only to pick up the operation code, LDA,
but is also used to pick up the address of the memory location from
which the LDA is going to obtain its data. In this case, the program
counter automatically is incremented three times to pick up the full
instruction with the microprocessor interpreting each of the individual
fetches as the appropriate data. In other words, the first
fetch is used to pick up the OP CODE, LDA, the second fetch is used to
pick up the low order address byte of the data and the third fetch is
used to pick up the high order address byte of the data. This is the
form in which many of the microprocessor instructions will appear as
it is the most simple form of addressing in the machine and allows
referencing to any memory location.
Assuming that the microprocessor has the ability to start the
program counter at a known instruction, it should be fairly obvious
that the program counter would then continue to advance from that
location up to the maximum memory location, roll over to the least
memory location and continue incrementing through the memory, fetching
instructions and addresses as it went. This would give us an
interesting sequential program but one which lacked one tremendously
powerful concept. The program would have no ability to perform tests
or implement various options based on the results of those tests.
In the previous section, the concept of flags which are set as
a result of the microprocessor operations was developed.
To use these flags, the program should be able to test them
and then change the sequence of operations which are being performed
depending on the result of the test. The program counter is going
to continually put out an address, the microprocessor is going to
fetch the instruction stored at that address and perform operations
based on that instruction. In order to change a sequence of performed
instructions by the microprocessor, the programmer must change the
value in the program counter. Therefore, test instructions are incorporated
which may result in a change of program count sequence as
a result of performing one of the tests. The simplest way to change
program sequence is to substitute a new value into the program counter
location. In the MCS650X microprocessors the simplest way to change
the program count sequence is with a JMP instruction.
4.0.2 JMP--Jump to New Location
In this instruction, the data from the memory location
located in the program sequence after the OP CODE is loaded into the
low order byte of the program counter (PCL) and the data from the
next memory location after that is loaded into the high order byte
of the program counter (PCH).
The symbolic notation for jump is (PC + 1)->^PCL, (PC + 2)->PCH.
As stated earlier, the "( )" means "contents of" a memory location.
PC indicates the contents of the program counter at the time the
OP CODE is fetched. Therefore (PC + 2)^PCH reads, "the contents of
the program counter two locations beyond the OP CODE fetch location
are transferred to the new PC high order byte."
The addressing modes are Absolute and Absolute Indirect.
The JMP instruction affects no flags and only PCL and PCH.
The JMP instruction allows use of the program counter to access
the new program counter value as illustrated by the following example:
Example 4.3: Use of JMP Instruction (Absolute Addressing Mode)
Address Data Comments
0100 JMP Jump to Location 3625
0101 25 (New PCL byte)
0102 36 (New PCH byte)
3625 OP CODE Next Instruction
The program counter in the example starts out at location 100. The
microprocessor loads a jump instruction. The program counter automatically
increments to 101 where the microprocessor picks up and
temporarily stores the 25. The program counter automatically increments
to 102 where the microprocessor picks up the 36.
The 3625 is substituted into the program counter and is used
to address the next instruction. Therefore, the JMP instruction
contains within its address the new program counter location.
Although the jump allows the change of program sequence, it
does so without performing my test. So it is a JMP instruction that
employed when it is desired to change the program counter no matter
what conditions have occurred.
Another JMP addressing Mode in the Indirect Addressing Mode.
Before this technique can be understood, the basis of indirect addressing
found in Chapter 6 must be reviewed. The JMP Indirect instruction is
detailed in Chapter 9, page 141.
4.1 BRANCHING
To allow for conditional program sequence change, there are a series
of branch instructions which test and perform optional changes of the program
counter based on the status of the flags. To perform a conditional
change of sequence, the microprocessor must interpret the instruction,
test the value of a flag, and then change the P counter if the value
agrees with the instruction. If the condition is not met, the program
counter continues to increment in its normal fashion. Figure 4.2
illustrates how a conditional test might be used.
In this example, it is seen that generation of a carry from the add
operation will allow an out-of-sequence branch to a new location.
4.1.1 Basic Concept of Relative Addressing
If one considers that the instruction JMP required three
bytes, one for OP CODE, one for new program counter low (PCL) and
one for new program counter high (PCH) it is seen that jump on carry
set would also require three bytes. Because most programs for control
require many continual jumps or branches, the MCS650X uses
"relative" addressing for all conditional test instructions. To
perform any branch, the program counter must be changed. In relative
addressing, however, we add the value in the memory location
following the OP CODE to the program counter. This allows us to
specify a new program counter location with only two bytes, one
for the OP CODE and one for the value to be added.
To illustrate this, in the following example, the branch on
carry set (BCS) illustration is followed by a value of 50. If the
carry is set, the new program location would be 108 + 50 = 158; in
other words, it will take the branch.
Example 4.4: Illustration of "Branch on Carry Set"
Address Data Comments
0100 LDA Load First Value
0101 ADL1 First Number, low byte
0102 ADH1 First Number, high byte
0103 ADC Add Second Value
0104 ADL2 Second Number, low byte
0105 ADH2 Second Number, high byte
0106 BCS Test for Carry Set. If
yes, branch to 0158
0107 +50
0108 STA If not, store results
of add
0109 ADL3 Third Number, low byte
010A ADH3 Third Number, high byte
0158 OP CODE New instruction
The 0108 represents the value of the program counter after
reading the offset value. The program counter automatically increments
so it can reference the next memory location on the next cycle.
The add of the offset is a signed binary add as discussed in the arithmetic
section. A positive branch is indicated by a in bit 7 of the
relative value, and a minus branch is in two's complement form and is
indicated by a 1 in bit 7. The inherent capabilities of this type of
notation system allow branch conditionally forward 127 bytes from
the next instruction and back 128 bytes from that instruction. All
branches in the MCS650X series are conditional relative branches
and all have the form shown above. The advantage of relative addressing
is best shown in the following example:
Example 4.5: Sequencing Two Branch Instructions
Address Data Comments
0100 LDA Load First Value
0101 ADL1
0102 ADH1
0103 ADC Add Second Value
0104 ADL2
0105 ADH2
0106 BCS Test for Carry Set. If
yes, branch to 0158
0107 +50
0108 BMI Test for Minus Number. If
yes, branch to 0095
0109 -75
010A STA If not, Store
010B ADL3
010C ADH3
In this example, the previous single-branch example was modified
to also test the resulting number to see if it is negative. In
sequencing two-branch instructions, this loop is 2 bytes shorter by
use of relative branches rather than 3 byte branches.
4.1.2 Branch Instructions
4.1.2.1 BMI - Branch on Result Minus
This instruction takes the conditional branch if the N bit
is set.
BMI does not affect any of the flags or any other part of
the machine other than the program counter and then only if the
N bit is on.
The mode of addressing for BMI is Relative.
4.1.2.2 BPL - Branch on Result Plus
This instruction is the complementary branch to branch on
result minus. It is a conditional branch which takes the branch when
the N bit is reset (0) . BPL is used to test if the previous result
bit 7 was off (0) and branch on result minus is used to determine if
the previous result was minus or bit 7 was on (1).
The instruction affects no flags or other registers other
than the P counter and only affects the P counter when the N bit is
reset.
The addressing mode is Relative.
4.1.2.3 BCC - Branch on Carry Clear
This instruction tests the state of the carry bit and takes
a conditional branch if the carry bit is reset.
It affects no flags or registers other than the program
counter and then only if the C flag is not on.
The addressing mode is Relative.
4.1.2.4 BCS - Branch on Carry Set
This instruction takes the conditional branch if the carry
flag is on.
BCS does not affect any of the flags or registers except for
the program counter and only then if the carry flag is on.
The addressing mode is Relative.
4.1.2.5 BEQ - Branch on Result Zero
This instruction could also be called "Branch on Equal."
It takes a conditional branch whenever the Z flag is on or the previous
result is equal to 0.
BEQ does not affect any of the flags or registers other than
the program counter and only then when the Z flag is set.
The addressing mode is Relative.
4.1.2.6 BNE - Branch on Result Not Zero
This instruction could also be called "Branch on Not Equal."
It tests the Z flag and takes the conditional branch if the Z flag is
not on, indicating that the previous result was not zero.
BNE does not affect any of the flags or registers other than
the program counter and only then if the Z flag is reset.
The addressing mode is Relative
4.1.2.7 BVS - Branch on Overflow Set
This instruction tests the V flag and takes the conditional
branch if V is on.
BVS does not affect any flags or registers other than the
program counter and only when the overflow flag is set.
The addressing mode is Relative.
4.1.2.8 BVC - Branch on Overflow Clear
This instruction tests the status of the V flag and takes
the conditional branch if the flag is not set.
BVC does not affect any of the flags and registers other
than the program counter and only when the overflow flag is reset.
The addressing mode is Relative.
4.1.3 Branch Summary
To summarize, the MCS650X branches have two characteristics;
each of them tests the state of a flag and then either accesses the
next instruction in program sequence if the flag is not in the test
state or adds the offset value to the PC value at the OP CODE of the
next instruction (PC + 1) to allow the program to change operations.
This allows the programmer the full ability to make decisions. By
writing a sequence of branch instructions, any combination of conditions
of the microprocessor may be determined and new action taken
as a result of the tests.
There are four branch conditions in the MCS6501-5 microprocessors.
These are branch on carry flag, branch of overflow flag,
branch on N flag, and branch on zero flag. Each of the branches has
a branch on flag set (1) or branch on flag clear (0).
4.1.4 Solution to Branch Out of Range
The branch relative instruction is unlike the jump instruction
which can reach anywhere in memory, since branch relative is
limited to +127 or -128 from the current program counter location.
Although for many loops and many tests this is sufficient range,
longer programs will occasionally find it necessary to conditionally
branch to a location that is significantly further away than
the branch command will directly reach. This is one of the uses
of complementary branches. If a program should find it necessary
to branch to a location which was significantly further away than
127, the following solution would facilitate the branch:
Example 4.6: Use of JMP to Branch Out of Range
Address Data Comments
100 LDA Load First Value
101 ADL1
102 ADH1
103 ADC Add Second Value
104 ADL2
105 ADH2
106 BCC Branch, if no carry,
ahead 3 (to Point 2)
107 +3
108 JMP If carry set, jump to
location specified by
ADH4, ADL4
109 ADL4
10A ADH4
Point 2 10B BMI Check for Minus
10C Offset
10D STA
10E ADL3 If not minus, Store
Result
10F ADH3
In this example, carry set is being checked. In order to accomplish
this when the branch command would have to reach outside of the 128
range, the use of a complementary branch is required. Instead of
doing the "branch on carry set" to the location, the "branch on
carry clear" is utilized (a complementary instruction) which branches
past the jump. If the complementary branch is not taken, the jump is
the "branch on carry set" function.
This technique of branching past a jump with the complementary
branch is a universal solution to the branch out of range problem.
Another solution is to find a like branch to the same location
that is within range and although this involves two branches to transfer
control, it does save memory locations.
By use of the relative branch less bytes of code are used than
if a conditional jump had been used. However, in large programs, the
branch out of range occurs more frequently. If the user can determine
that a branch will be out of range by inspection, he should use the
jump solution at the time he is writing the code. Otherwise, the
various assemblers indicate an out of range branch which will
require recoding to use the jump solution.
NOTE: The jump solution causes 5 bytes of code to be
substituted for 2 bytes of branch which in a symbolic
assembly may force other branches to go out of range.
This might cause several consecutive reassemblies but
this technique will solve the problem.
4.2 TEST INSTRUCTIONS
Although most of the normal operations of the microprocessor involve
setting of flags, there are specific instructions which are designed only
to set flags for testing with the branch instruction.
4.2.1 CMP - Compare Memory and Accumulator
This instruction subtracts the contents of memory from the
contents of the accumulator.
Its symbolic notation is A - M.
The use of the CMP affects the following flags: Z flag is
set on an equal comparison, reset otherwise; the N flag is set or
reset by the result bit 7, the carry flag is set when the value in
memory is less than or equal to the accumulator, reset when it is
greater than the accumulator. The accumulator is not affected.
It is a "Group One" instruction and therefore has as its
addressing modes: Immediate; Zero Page; Zero Page,X; Absolute;
Absolute, X; Absolute, Y; (Indirect, X) ; (Indirect),!.
The purpose of the compare instruction is to allow the user
to compare a value in memory to the accumulator without changing
the value of the accumulator. An example of where this becomes
extremely important is when one is receiving command instructions
from an external device. In this case, an input byte may have
several values. Each value can cause the program to perform a
different operation. The only rapid way to determine the value of
the input data is to compare the memory with a series of constants.
It is fairly simple to perform "compare to constant" operations.
By use of the immediate addressing mode which will be developed
later, the following example compares an input to three values
and branches to different locations for each:
Example 4.7: Using the CMP instruction
Data Comments
LDA Load Value
ADL Address Low
ADH Address High
CMP Compare COUNT 1 to Accumulator
COUNT 1
BEQ If Equal, take the branch of OFFSET 1
OFFSET 1
CMP Compare COUNT 2 to Accumulator
COUNT 2
BEQ If equal, take the branch to OFFSET 2
OFFSET 2
CMP Compare COUNT 3 to Accumulator
COUNT 3
BEQ If equal, take the branch to OFFSET 3
OFFSET 3
Next Inst. Otherwise, go to Next Instruction
based on default value (COUNT 4).
This example shows how to use the default option. A value
was compared against 3 values and if none were equal a fourth, or
default value, is assumed. This is a useful technique for code
minimization.
The compare instruction is designed to allow a signed comparison
between 2 values assuming one makes appropriate use of the Z and
N and C flags. In order to give maximum flexibility to the instruction,
the instruction performs an effective subtract between the value
in memory and the value in the accumulator. The reason it is an effective
subtract is that subtraction allows the user to compare equal
or less with one instruction.
The results of a compare are:
N C Z V
Accumulator < Memory Either Reset Reset Unchanged
Accumulator = Memory Reset Set Set Unchanged
Accumulator > Memory Either Set Reset Unchanged
So, to check if the accumulator is less than memory, the compare
is followed by a BCC; to check if equal to is followed by a BEQ;
and to check if greater it is followed by a BEQ followed by a BCS.
Greater than or equal is checked by BCS.
4.2.2 Bit Testing
The comparison instruction is designed for cases when byte or
multiple bytes of values are being compared; however, in the analysis
of logic functions, it is very often necessary to determine the condition
of an individual bit. One of the ways to accomplish this is
with the use of the AND instruction as previously discussed. In other
words, the user can load a value into the accumulator and AND it with
a field that contains a one bit only in the corresponding bit position
to the bit under test. By using a Branch on Zero Flag after
the AND, the status of the bit in memory is testable by this technique.
However, the use of this technique involves destroying the
accumulator value with the AND instruction. Therefore, searching a
table looking for a single bit in a given position would necessitate
the reloading of the test value (mask) after each AND instruction.
In order to allow memory sampling without disturbing the accumulator,
the BIT instruction is used.
4.2.2.1 BIT - Test Bits in Memory with Accumulator
This instruction performs an AND between a memory location
and the accumulator but does not store the result of the AND into
the accumulator.
The symbolic notation is M ^ A.
The bit instruction affects the N flag with N being set to
the value of bit 7 of the memory being tested, the V flag with V
being set equal to bit 6 of the memory being tested and Z being set
by the result of the AND operation between the accumulator and the
memory if the result is Zero, Z is reset otherwise. It does not
affect the accumulator.
The addressing modes are Zero Page and Absolute.
The BIT instruction actually combines two instructions from
the PDP-11 and MC6800, that of TST (Test Memory) and (BIT Test).
This, like the compare test, allows the examination of an individual
bit without disturbing the value in the accumulator and is illustrated
by the example below:
Example 4.8: Sample Program Using the BIT Test
Data Comments
LDA Load MASK into Accumulator
MASK
BIT Test First Memory Value for Mask Bit
ADL1
ADH1
BNE Branch if Set
+50
BIT Test Second Memory Value for Mask Bit
ADL2
ADH2
BNE Branch if Set
-75
etc.
The value "MASK" loaded into the accumulator in this example
is actually a descriptive title since, this byte is 8 bits, only one
of which is a 1. Using this byte in the AND operation inherent in the
BIT test will effectively mask out all bits in the memory location under
test except that bit position corresponding to the 1 residing in the
accumulator. In Example 4.8, the MASK byte is AND'ed to the data
found in location ADHl, ADLl and if the bit under test is a 1, the
branch will be taken; if not a 1, the second memory location will be
tested with the same mask, etc.
In addition to the nondestructive feature of the bit which
allows us to isolate an individual bit by use of the branch equal or
branch no equal test, two modifications to the PDP-11 version of that
instruction have been made in the MCS650X microprocessor. These are
to allow a test of bit 7 and bit 6 of the field examined with the BIT
test. This feature is particularly useful in serving polled interrupts
and particularly in dealing with the MCS6520 (Peripheral Interface
Device) . This device has an interrupt sense bit in bit 6 and bit 7
of the status words. It is a standard of the M6800 bus that whenever
possible, bit 7 reflects the interrupt status of an I/O device. This
means that under normal circumstances, an analysis of the N flag
after a load or BIT instruction should indicate the status of the
bit 7 on the I/O device being sampled. To facilitate this test using
the Bit instruction, bit 7 from the memory being tested is set
into the N flag irrespective of the value in the accumulator.
This is different from the bit instruction in the M6800 which requires
that bit 7 also be set on the accumulator to set N. The
advantage to the user is that if he decides to test bit 7 in the
memory J it is done directly by sampling the N bit with a Bit followed
by branch minus or branch plus instruction. This means that
I/O sampling can be accomplished at any time during the operation
of instructions irrespective of the value preloaded in the accumulator.
Another feature of the BIT test is the setting of bit 6 into
the V flag. As indicated previously, the V flag is normally reserved
for overflow into the sign position during an add and subtract instruction.
In other words, the V flag is not disturbed by normal
instructions. When the BIT instruction is used, it is assumed that
the user is trying to examine the memory that he is testing with the
BIT instruction. In order to receive maximum value from a BIT instruction,
bit 6 from the memory being tested is set into the V flag.
In the case of a normal memory operation, this just means that the
user should organize his memory such that both of his flags to be
tested are in either bit 6 or bit 7, in which case an appropriate
mask does not have to be loaded into the accumulator prior to implementing
the BIT instruction. In the case of the MCS6520, the BIT
instruction can be used for sampling interrupt, irrespective of the
mask. This allows the programmer to totally interrogate both bit 6 and
bit 7 of the MCS6520 without disturbing the accumulator. In the case
of the concurrent interrupts, i.e., bit 6 and bit 7 both on, the fact
that the V flag is automatically set by the BIT instruction allows
the user to postpone testing for the "6th bit on" until after he has
totally handled the interrupt "for bit 7 on" unless he performs an
arithmetic operation subsequent to the BIT operation.