0% found this document useful (0 votes)
590 views

6809 Assembly Language Programming

kch

Uploaded by

sdaid
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
590 views

6809 Assembly Language Programming

kch

Uploaded by

sdaid
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 578

- · -----

6809
Assembly Language
Programming

Lance A. Leventhal

OSBORNE/McGraw-Hill
Berkeley, California

·-
· · - -- · - -------
Published by
Osborne/McGraw-Hill
2600 Tenth Street
Berkeley, California 94710

For information on translations and book distributors outside of the U. S. A. .

please write OSBORNE/McGraw-Hill at the above address.

6809 Assembly Language Programming


Copyright © 1981 McGraw-Hill, Inc. All rights reserved. Printed in the United States of America. No
part of this publication may be reproduced, stored in a retrieval system. or transmitted in any form or
by any means. electronic. mechanical. photocopying, recording or otherwise without the prior written
permission of the publishers.

4567890 DODO 89876543

ISBN 0-931988-35-7

Cover design by Tim Sullivan.

- --- -· --· · --···· ---- ··-· -- - -�-


Acknowledgments

Mr. Irvin Stafford of Burroughs Corporation constructed the 6809-based com­


puter, tried all the examples, and suggested numerous corrections and improvements.
Mr. Curt Ingraham, Ms. Susanna Jacobson, Ms. Denise Penrose, and Ms. Janice Enger
of Osborne/McGraw-Hill contributed greatly to this project; Susanna Jacobson and Curt
Ingraham insisted on a high level of clarity and accuracy. Mr. Lothar Stern and Mr.
Marshall Rothen of Motorola's Technical Information Center (Phoenix) were very
generous in providing materials. Others who helped include Ms. Marielle Carter, Mr.
Romeo Favreau, and Mr. Gary Hankins of Sorrento Valley Associates; Mr. Michael
Lehman and Mr. Winthrop Saville of MT MicroSystems; and my wife Donna, who has
been both patient and understanding.
Special thanks go to Mr. Terry Ritter of Motorola (Austin, Texas), the original
architect of the 6809 microprocessor, who was kind enough to review the manuscript.
Also Dr. Jack Lipovski of the University of Texas at Austin provided me with a
preliminary version of his 6809-based book Microcomputer Interfacing: Principles and
Practices (Lexington Books, Lexington, Mass., 1980); it is an excellent book and I have
borrowed heavily from the ideas in it.
Mr. Allan Robbins, P.E., of SDS Technical Services, Ltd., Winnepeg, Canada,
contributed material for Chapter 3, Chapter 22, and the appendices.
I would like to take this opportunity to thank those who have reviewed previous
books in this series. In particular, I should mention Mark Bernstein, Jim Butterfield, Art
Childs, James Demas, and Philip Hooper. Of course, my initial reaction to their negative
comments was defensive. However, after some complaining and some prodding from
my editors, I have responded to their criticism in this book. I have revised several chap­
ters considerably and I have stressed clear, concise explanations and interesting exam­
ples. Reviewing is a thankless job, so I want these people to know that I have learned
from their efforts.
This book is dedicated to the friends I made along South Highway 101 in Solana
Beach, California: Don and Hazel Cahoon, Lou and Marge DiCarlo, and Bob and June
Vallery.

- Lance A. Leventhal

This book's assembler listings were generated on a 6809-based EXORciser system


loaned to the publisher by Motorola Microsystems, Mesa, Arizona.
The publisher also wishes to thank Mr. Bernard Lohr for assembling and testing
the programs in this book.
About the Author

Lance A. Leventhal is a partner in Emulative Systems Company, Inc., a San Diego­


based consulting firm specializing in microprocessors and microprogramming. He is a
national lecturer on microprocessors for the IEEE, the author of ten books and over
sixty articles on microprocessors, and a regular contributor to such publications as
Simulation and Microcomputing. He also serves as technical editor for the Society for
Computer Simulation and as contributing editor for Digital Design magazine.

Dr. Leventhal has authored four previous books in this series and has just begun work
on a new series, Some Common Assembly Language Programs. He received a B.A.
degree from Washington University in St. Louis, and M.S. and Ph.D. degrees from the
University of California at San Diego. He is a member of SCS, ACM, IEEE, and the
IEEE Computer Society.

. .
--- - - ----··---
Contents

Section I. Fundamental Concepts


1. Introduction Assembly Language Programming
A Computer Program 1-2
High-Level Languages 1-8

2. Assemblers
Features of Assembiers 2-1
Types of Assemblers 2-15
Errors 2-16
Loaders 2-17

3. 6809 Machine Structure and Assembly Language


6809 Registers and Flags 3-3
6809 Addressing Modes 3-6
Modes Which Do Not Specify Memory Locations 3-8
Memory Addressing Modes 3-9
Indexed Memory Addressing Modes 3-16
Program Relative Addressing for Branches 3-36
6809 Instruction Set 3-38
6800/6809 Compatibility 3-38
6801/6809 Compatibility 3-44
6502/6809 Compatibility 3-45
Motorola 6809 Assembler Conventions 3-45
vi

Section II. Introductory Problems


4. Beginning Programs
Program Examples 4-1
Problems 4-11

5. Simple Program Loops


Program Examples 5-4
Problems 5-15

6. Character-Coded Data
Handling Data in ASCII 6-1
Program Examples 6-3
Problems 6-13

7. Code Conversion
Program Examples 7-2
Problems 7-10

8. Arithmetic Problems
Program Examples 8-2
Problems 8-16

9. Tables and Lists


Program Examples 9-1
Problems 9-14

Section Ill. Advanced Topics


1 0. Subroutines
Program Examples 10-3
Position-Independent Code 10-15
Nested Subroutines 10-16
Problems 10-16

11. Parameter Passing Techniques


The PSH and PUL Instructions 11-1
General Parameter Passing Techniques 11-3
Types of Parameters 11-14

12. Input/Output Considerations


110 Device Categories 12-2
Time Intervals 12-9
Logical and Physical Devices 12-13
Standard Interfaces 12-14
6809 Input/Output Chips 12-14

13. Using the 6820 Peripheral Interface Adapter (PIA)


Initializing a PIA 13-6
Using the PIA to Transfer Data 13-10
Program Examples 13-1
More Complex I/0 Devices 13-29
Problems 13-52
vii

14. Using the 6850 Asynchronous Communications Interface Adapter (ACIA)


Program Examples 14-5

15. Interrupts
Characteristics of Interrupt Systems 15-1
6809 Interrupt System 15-3
6820 PIA Interrupts 15-8
6850 ACIA Interrupts 15-8
6809 Polling Interrupt Systems 15-9
6809 Vectored Interrupt Systems 15-10
Communications Between Main Program and Service Routines 15-10
Enabling and Disabling Interrupts 15-11
Changing Values in the Stack 15-13
Interrupt Overhead 15-15
Program Examples 15-15
More General Service Routines 15-30
Problems 15-31

Section IV. Software Development


16. Problem Definition
Inputs 16-1
Outputs 16-2
Processing Section 16-2
Error Handling 16-3
Human Factors/Operator Interaction 16-3
Examples 16-4
Review 16-14

1 7. Program Design
Basic Principles 17-1
Flowcharting 17-2
Modular Programming 17-11
Structured Programming 17-15
Top-Down Design 17-26
Designing Data Structures 17-31
Review of Problem Definition and Program Design 17-32

18. Documentation
Self-Documenting Programs 18-1
Comments 18-2
Flowcharts as Documentation 18-7
Structured Programs as Documentation 18-7
Memory Maps 18-7
Parameter and Definition Lists 18-8
Library Routines 18-9
Total Documentation 18-12
viii

19. Debugging
Simple Debugging Tools 19-2
Advanced Debugging Tools 19-8
Debugging With Checklists 19-10
Looking for Errors 19-11
Examples 19-17

20. Testing
Selecting Test Data 20-2
Examples 20-3
Rules for Testing 20-4
Conclusions 20-4

21. Maintenance and Redesign


Saving Memory 21-2
Saving Execution Time 21-4
Major Reorganization 21-4

Section V. 6809 Instruction Set


22. The Instruction Set
(For page number reference, see the list of 6809 instructions at
the back of the book.)

Appendices
A. Summary of the 6809 Instruction Set

B. Summary of 6809 Indexed and Indirect Addressing Modes

C. 6809 Instruction Codes, Memory Requirements, and Execution Times

D. 6809 Instruction Object Codes in Numerical Order

E. 6809 Post Bytes in Numerical Order

Index

- -----
· --·-
Program Examples

4-1. 8-Bit Data Transfer 4-1


4-2. 8-Bit Addition 4-2
4-3. Shift Left One Bit 4-2
4-4. Mask Off Most Significant Four Bits 4-3
4-5. Clear a Memory Location 4-4
4-6. Byte Disassembly 4-4
4-7. Find Larger of Two Numbers 4-5
4-8. 16-Bit Addition 4-7
4-9. Table of Squares 4-8
4-10. 16-Bit Ones Complement 4-11

5-1. Sum of Data 5-4


5-2. 16-Bit Sum of Data 5-6
5-3. Number of Negative Elements 5-9
5-4. Maximum Value 5-10
5-5. Justify a Binary Fraction 5-12

6-1. Length of a String of Characters 6-3


6-2. Find First N-Biank Character 6-5
6-3. Replace Leading Zeros with Blanks 6-7
6-4. Add Even Parity to ASCII Characters 6-8
6-5. Pattern Match 6-11

7-1. Hexadecimal to ASCII 7-2


7-2. Decimal to Seven-Segment 7-3
7-3. ASCII to Decimal 7-6
7-4. BCD to Binary 7-8
7-5. Binary Number to ASCII String 7-8
X

8-l. Multiple-Precision Binary Addition 8-2


8-2. Decimal Addition 8-4
8-3. 8-Bit by 16-Bit Binary Multiplication 8-17
8-4. Binary Division 8-8
8-5. Self-Checking Numbers Double Add Double Mod 10 8-12

9-1. Add Entry to List 9-1


9-2. Check an Ordered List 9-3
9-3. Remove Element from Queue 9-5
9-4. 8-Bit Sort 9-9
9-5. Using an Ordered Jump Table 9-12

10-1. Converting Hexadecimal to ASCII 10-3


10-2. Length of a String of Characters 10-7
10-3. Maximum Value 10-9
10-4. Pattern Match 10-11
10-5. Multiple-Precision Addition 10-13

13-1. A Pushbutton 13-12


13-2. A Multi-Position (Rotary, Selector, or Thumbwheel) Switch 13-16
13-3. A Single LED 13-20
13-4. Seven-Segment LED Display 13-22
13-5. An Unencoded Keyboard 13-32
13-6. An Encoded Keyboard 13-38
13-7. Digital-to-Analog Converter 13-40
13-8. Analog-to-Digital Converter 13-43
13-9. A Teletypewriter (TTY) 13-47

14-1. Receive Data from TTY 14-5


14-2. Send Data to TTY 14-6

15-1. A Startup Interrupt 15-15


15-2. A Keyboard Interrupt 15-17
15-3. A Printer Interrupt 15-20
15-4. A Real-Time Clock Interrupt 15-23
15-5. A Teletypewriter Interrupt 15-28

18-1. Commenting a Multiple-Precision Addition Routine 18-4


18-2. Commenting a Teletypewriter Output Routine 18-5
18-3. Sum of Data/Library Routine 18-10
18-4. Decimal to Seven-Segment Conversion/Library Routine 18-11
18-5. Decimal Sum/Library Routine 18-11

19-l. Debugging a Code Conversion Program 19-17


19-2. Debugging a Sort Program 19-22

20-1. Testing a Sort Program 20-3


20-2. Testing an Arithmetic Program 20-4
I
Fundamental Concepts

This book describes assembly language programming. It assumes that you are
familiar with An Introduction to Microcomputers: Volume 1 - Basic Concepts
(Berkeley: Osborne/McGraw-Hill, 1980). Chapters 6 and 7 of that book are
especially relevant. This book does not discuss the general features of computers,
microcomputers, addressing methods, or instruction sets; you should refer to An
Introduction to Microcomputers: Volume 1 for that information.
The chapters in this section provide basic information on assembly language in
general and the 6809 in particular. Chapter 1 discusses the purpose of assembly
language and compares it with higher-level computer languages. Chapter 2 discusses as­
semblers and, briefly, loaders. Chapter 3 describes the architecture of the 6809
microprocessor, compares it with similar processors, and discusses important features of
Motorola's 6809 assemblers.

HOW THIS BOOK HAS BEEN PRINTED

This book contains both boldface and lightface type. The material in lightface
type only expands on information presented in the previous boldface type. Thus you
can skip subject areas with which you are familiar by skipping the material in lightface
type. When you reach an unfamiliar subject, read both the material in boldface type and
the material in lightface type.
1
Introduction to
Assembly Language Programming

A computer program is ultimately a series of numbers and therefore has very little
meaning to a human being. In this chapter we will discuss the levels of human-like
language in which a computer program may be expressed. We will further discuss the
reasons for and uses of assembly language, which is the subject of this book.

THE MEANING OF INSTRUCTIONS

The instruction set of a microprocessor is the set of binary inputs that produce
defined actions during an instruction cycle. An instruction set is to a microprocessor
what a function table is to a logic device such as a gate, adder, or shift register. Of
course, the actions that the microprocessor performs in response to its instruction
inputs are far more complex than the actions that logic devices perform in response to
their inputs.

Binary Instructions

An instruction is a binary digit pattern - it must be available at the data


inputs to the microprocessor at the proper time in order to be interpreted as an
instruction. For example, when the 6809 microprocessor receives the 8-bit binary pat­
tern 01001111 as the input during an instruction fetch operation, the pattern means:

"Clear (put zero in) Accumulator A"

Similarly, the pattern 10000110 means:


1-2 6809 Assembly Language Programming

The microprocessor (like any other computer ) only recognizes binary patterns as
instructions or data; it does not recognize words or octal, decimal, or hexadecimal num­
bers.

A COMPUTER PROGRAM

A program is a series of instructions that causes a computer to perform a partie·


ular task.
Actually, a computer program includes more than instructions; it also contains
the data and memory addresses that the microprocessor needs to accomplish the tasks
defined by the instructions. Clearly, if the microprocessor is to perform an addition, it
must have two numbers to add and a place to put the result. The computer program
must determine the sources of the data and the destination of the result as well as the
operation to be performed.
All microprocessors execute instructions sequentially unless an instruction
changes the order of execution or halts the processor. That is, the processor gets its next
instruction from the next higher memory address unless the current instruction
specifically directs it to do otherwise.
Ultimately, every program is a set of binary numbers. For example, this is a
6809 program that adds the contents of memory locations 006016 and 006116 and
places the result in memory location 006216:

10110110
00000000
01100000
10111011
00000000
01100001
10110111
00000000
01100010

This is a machine language, or object, program. If this program were entered into the
memory of a 6809-based microcomputer, the microcomputer would be able to execute it
directly.

THE BINARY PROGRAMMING PROBLEM

There are many difficulties associated with creating programs as object, or bin·
ary machine language, programs. These are some of the problems:

1. The programs are difficult to understand or debug. ( Binary numbers all look
the same, particularly after you have looked at them for a few hours. )

2. The programs are slow to enter since you must set a front panel switch for
each bit and load memory one byte at a time.

3. The programs do not describe the task which you want the computer to per­
form in anything resembling a human-readable format.

4. The programs are long and tiresome to write.


Introduction to Assembly Language Programming 1-3

5. The programmer often makes careless errors that are very difficult to locate
and correct.

For example, the following version of the addition object program contains a
single bit error. Try to find it:
10110110
00000000
01100000
10111011
00000000
01110001
10110111
00000000
01100010

Although the computer handles binary numbers with ease, people do not. People
find binary programs long, tiresome, confusing, and meaningless. Eventually, a pro­
grammer may start remembering some of the binary codes, but such effort should be
spent more productively.

USING OCTAL OR HEXADECIMAL

We can improve the situation somewhat by writing instructions using octal or


hexadecimal numbers, rather than binary. We will use hexadecimal numbers in this
book because they are shorter, and because they are the standard for the microprocessor
industry. Table 1-1 defines the hexadecimal digits and their binary equivalents. The
6809 program to add two numbers now becomes:
B6
00
60
BB
00
61
B7
00
62

At the very least, the hexadecimal version is shorter to write and not quite so tiring to
examine.

Table 1-1. Hexadecimal Conversion Table

Hexadecimal Binary Decimal


Digit Equivalent Equivalent

0 0000 0
1 0001 1
2 0010 2
3 0011 3
4 0100 4
5 0101 5
6 0110 6
7 0111 7
8 1000 8
9 1001 9
A 1010 10
B 1011 11
c 1100 12
D 1101 13
E 1110 14
F 11 11 15
1-4 6809 Assembly Language Programming

Errors are somewhat easier to find in a sequence of hexadecimal digits. The


erroneous version of the addition program, in hexadecimal form, becomes:
B6
00
60
BB
00
71
87
00
62

The mistake is far more obvious.


What do we do with this hexadecimal program? The microprocessor under­
stands only binary instruction codes. If your front panel has a hexadecimal keyboard
instead of bit switches, you can key the hexadecimal program directly into memory -
the keyboard logic translates the hexadecimal digits into binary numbers. But what if
your front panel has only bit switches? You can con vert the hexadecimal digits to binary
by yourself, but this is a repetitive, tiresome task. People who attempt it make all sorts of
petty mistakes, such as looking at the wrong line, dropping a bit, or transposing a bit or a
digit. Besides, once we have converted our hexadecimal program we must still place the
bits in memory through the switches on the front panel.

Hexadecimal Loader

These repetitive, grueling tasks are, however, perfect jobs for a computer. The
computer never gets tired or bored and never makes silly mistakes. The idea then is to
write a program that accepts hexadecimal numbers, converts them into binary num­
bers, and places them in memory. This is a standard program provided with many
microcomputers; it is called a hexadecimal loader.
The hexadecimal loader is a program like any other. It occupies memory space. In
some systems, it resides in memory just long enough to load another program; in
others, it occupies a reserved, read-only section of memory. Your microcomputer may
not have bit switches on its front panel; it may not even have a front panel. This reflects
the machine designer's decision that binary programming is not only impossibly tedious
but also wholly unnecessary. The hexadecimal loader in your system may be part of a
larger program called a monitor, which also provides a number of tools for program
debugging and analysis.
A hexadecimal loader certainly does not solve every programming problem. The
hexadecimal version of the program is still difficult to read or understand; for example,
it does not distinguish operations from data or addresses, nor does the program listing
provide any suggestion as to what the program does. What does B6 or 3F mean?
Memorizing a card full of codes is hardly an appetizing proposition. Furthermore, the
codes will be entirely different for a different microprocessor and the program will
require a large amount of documentation.

INSTRUCTION CODE MNEMONICS

An obvious programming improvement is to assign a name to each instruction


code. The instruction code name is called a "mnemonic" or memory jogger. The
Introduction to Assembly Language Programming 1-5

instruction mnemonic should describe, in a minimum number of characters, what the


instruction does.

Devising Mnemonics

In fact, all microprocessor manufacturers (they cannot remember hexadecimal


codes either) provide a set of mnemonics for the microprocessor instruction set. You do
not have to abide by the manufacturer's mnemonics; there is nothing sacred about
them. However, they are standard for a given microprocessor, and therefore under­
stood by all users. These are the instruction codes that you will find in manuals, cards,
books, articles, and programs. The problem with selecting instruction mnemonics is that
not all instructions have "obvious" names. Some instructions do (for example, ADD,
AND, OR), others have obvious contractions (such as SUB for subtraction, XOR for
exclusive-OR), while still others have neither. The result is such mnemonics as WMP,
PCHL, and even SOB. Most manufacturers come up with some reasonable names and
some hopeless ones. However, users who devise their own mnemonics rarely do much
better.
Along with the instruction mnemonics, the manufacturer will usually assign
names to the CPU registers. As with the instruction names, some register names are
obvious (such as A for Accumulator) while others may have only historical significance.
Again, we will use the manufacturer's suggestions simply to promote standardization.

Standard Mnemonics

There is a proposed standard set of assembly language mnemonics.• The


amount of use that it will receive is uncertain, but it should at least serve as a basis for
comparing instruction sets and for selecting mnemonics for future processors.

An Assembly Language Program

If we use standard 6809 instruction and register mnemonics, as defined by


Motorola, our 6809 addition program becomes:

LDA $0060
ADDA $0061
STA $0062

The program is still far from obvious, but at least some parts are comprehensible.
ADDA is a considerable improvement over BB. LDA and ST A suggest loading and
storing the contents of an accumulator. We now see that some lines are operations and
others are data or addresses. Such a program is an assembly language program.

THE ASSEMBLER PROGRAM

How do we get the assembly language program into the computer? We have to
translate it, either into hexadecimal or into binary numbers. You can translate an as­
sembly language program by hand, instruction by instruction. This is called hand as­
sembly.
1-6 6809 Assembly Language Programming

The following table illustrates the hand assembly of the addition program:

Instruction Mnemomic Addressing Method Hexadecimal Equivalent

LOA extended direct 86


ADDA extended direct 88
ST A extended direct 87

As with hexadecimal-to-binary conversion, hand assembly is a rote task which is


uninteresting, repetitive, and subject to numerous minor errors. Picking the wrong line,
transposing digits, omitting instructions, and misreading the codes are only a few of the
mistakes that you may make. Most microprocessors complicate the task even further by
having instructions with different lengths. Some instructions are one byte long while
others may be two to five bytes long. Some instructions require data in the second and
third bytes; others require memory addresses, register numbers, or who knows what?
Assembly is another rote task that we can assign to the microcomputer. The
microcomputer never makes any mistakes when translating codes; it always knows
how many bytes and what format each instruction requires. The program that does
this job is an "assembler." The assembler program translates a user program, or
"source" program written with mnemonics, into a machine language program, or
"object" program, which the microcomputer can execute. The assembler's input is a
source program and its output is an object program.
An assembler is a program, just as the hexadecimal loader is. However, assem­
blers are more expensive, occupy more memory, and require more peripherals and
execution time than do hexadecimal loaders. While users may (and often do) write their
own loaders, few care to write their own assemblers.
Futhermore, assemblers have their own rules that you must learn. These
include the use of certain markers (such as spaces, commas, semicolons, or colons) in
appropriate places, correct spelling, the proper control of information, and perhaps even
the correct placement of names and numbers. These rules are usually simple and can be
learned quickly.

Additional Features of Assemblers

Early assemblers did little more than translate the mnemonic names of instruc­
tions and registers into their binary equivalents. However, most assemblers now pro­
vide such additional features as:

Allowing the user to assign names to memory locations, input and output
devices, and even sequences of instructions

Converting data or addresses from various number systems (for example,


decimal or hexadecimal) to binary and converting characters into their ASCII
or EBCDIC binary codes

Performing some arithmetic as part of the assembly process

Telling the loader program where in memory parts of the program or data
should be placed

Allowing the user to assign areas of memory as temporary data storage and to
place fixed data in areas of program memory
Introduction to Assembly Language Programming 1-7

Providing the information required to include standard programs from pro­


gram libraries, or programs written at some other time, in the current program

Allowing the user to control the format of the program listing and the input
and output devices employed

Choosing an Assembler

All of these features, of course, in valve additional cost and memory. Microcom­
puters generally have much simpler assemblers than do larger computers, but the ten­
dency is always for the size of assemblers to increase. You will often have a choice of as­
semblers. The important criterion is not how many off-beat features the assembler has,
but rather how convenient it is to use in normal practice.

DISADVANTAGES OF ASSEMBLY LANGUAGE

The assembler, like the hexadecimal loader, does not solve all the problems of
programming. One problem is the tremendous gap between the microcomputer
instruction set and the tasks which the microcomputer is to perform. Computer
instructions tend to do things like add the contents of two registers, shift the contents of
the Accumulator one bit, or place a new value in the Program Counter. On the other
hand, a user generally wants a microcomputer to do something like check if an analog
reading has exceeded a threshold, look for and react to a particular command from a
teletypewriter, or activate a relay at the proper time. An assembly language programmer
must translate such tasks into a sequence of simple computer instructions. The transla­
tion can be a difficult, time-consuming job.
Furthermore, if you are programming in assembly language, you must have
detailed knowledge of the particular microcomputer that you are using. You must
know what registers and instructions the microcomputers has, precisely how the instruc­
tions affect the various registers, what addressing methods the computer uses, and a
mass of other information. None of this information is relevant to the task which the
microcomputer must ultimately perform.

Lack of Portability

In addition, assembly language programs are not portable. Each microcomputer


has its own assembly language which reflects its own architecture. An assembly
language program written for the 6809 will not run on a 6502, Z80, 8080, or 3870
microprocessor. For example, the addition program written for the 8080 would be:

LOA 60H
MOV B,A
LOA 61 H
ADD B
STA 6 2H

The lack of portability not only means that you will not be able to use your assem­
bly language program on a different microcomputer, but also that you will not be able to
use any programs that were not specifically written for the microcomputer you are using.
This is a particular drawback for microcomputers, since these devices are new and few
assembly language programs exist for them. The result, too frequently, is that you are
1-8 6809 Assembly Language Programming

on your own. If you need a program to perform a particular task, you are not likely to
find it in the small program libraries that most manufacturers provide. Nor are you likely
to find it in an archive, journal article, or someone 's old program file. You will probably
have to write it yourself.

HIGH-LEVEL LANGUAGES

The solution to many of the difficulties associated with assembly language pro­
grams is to use, instead, "high-level" or "procedure-oriented" languages. Such
languages allow you to describe tasks in forms that are problem-oriented rather than
computer-oriented. Each statement in a high-level language performs a recognizable
function; it will generally correspond to many assembly language instructions. A
program called a compiler translates the high-level language source program into
object code or machine language instructions.

FORTRAN - A HIGH-LEVEL LANGUAGE

Many different high-level languages exist for different types of tasks. If, for
example, you can express what you want the computer to do in algebraic notation,
you can write your program in FORTRAN (Formula Translation Language), the
oldest and most widely used of the high-level languages. Now, if you want to add two
numbers, you just tell the computer:

SUM NUMBl + NUMB2


I
=

That is a lot simpler (and a lot shorter) than either the equivalent machine language pro­
gram or the equivalent assembly language program. Other high-level languages include
COBOL (for business applications), PASCAL (a language designed for structured pro­
gramming), PL/1 (a combination of FORTRAN and COBOL), APL and BASIC (popu­
lar for time-sharing systems), and C (a systems-programming language developed at
Bell Telephone Laboratories).

ADVANTAGES OF HIGH-LEVEL LANGUAGES

Clearly, high-level languages make programs easier and faster to write. A com­
mon estimate is that a programmer can write a program about ten times as fast in a
high-level language as in assembly language.2-4 That is just writing the program; it
does not include problem definition, program design, debugging, testing, or documen­
tation, all of which become simpler and faster. The high-level language program is, for
instance, partly self-documenting. Even if you do not know FORTRAN, you probably
could tell what the statement illustrated above does.

Machine Independence

High-level languages solve many other problems associated with assembly


language programming. The high-level language has its own syntax (usually defined by
a national or international standard). The language does not mention the instruction
Introduction to Assembly Language Programming 1-9

set, registers, or other features of a particular computer. The compiler takes care of all
such details. Programmers can concentrate on their own tasks; they do not need a
detailed understanding of the underlying CPU architecture - for that matter, they do
not need to know anything about the computer they are programming.

Portability

Programs written in a high-level language are portable - at least, in theory.


They will run on any computer that has a standard compiler for that language.
At the same time, all previous programs written in a high-level language for prior
computers are available to you when programming a new computer. This can mean
thousands of programs in the case of a common language like FORTRAN or BASIC.

DISADVANTAGES OF HIGH-LEVEL LANGUAGES

If all the good things we have said about high-level languages are true - if you
can write programs faster and make them portable besides - why bother with as­
sembly languages? Who wants to worry about registers, instruction codes,
mnemonics, and all that garbage! As usual, there are disadvantages that balance the
advantages.

Syntax

One obvious problem is that, as with assembly language, you have to learn the
"rules" or "syntax" of any high-level language you want to use. A high-level
language has a fairly complicated set of rules. You will find that it takes a lot of time just
to get a program that is syntactically correct (and even then it probably will not do what
you want). A high-level computer language is like a foreign language. lf you have talent,
you will get used to the rules and be able to turn out programs that the compiler will
accept. Still, learning the rules and trying to get the program accepted by the compiler
does not contribute directly to doing your job.
Here, for example, are some FORTRAN rules:

Labels must be numbers placed in the first five card columns

Statements must start in column 7

Integer variables must start with the letters I, J, K, L, M, or N

Cost of Compilers

Another obvious problem is that you need a compiler to translate programs writ­
ten in a high-level language into machine language. Compilers are expensive and use a
large amount of memory. While most assemblers occupy 2K to 16K bytes of memory
(lK = 1024), compilers occupy 4K to 64K bytes. So the amount of overhead involved
in using the compiler is rather large.
1-10 6809 Assembly Language Programming

Adapting Tasks to a Language

Furthermore, only some compilers will make the implementation of your task
simpler. FORTRAN, for example, is well-suited to problems that can be expressed as
algebraic formulas. If, however, your problem is controlling a printer, editing a string of
characters, or monitoring an alarm system, your problem cannot be easily expressed in
algebraic notation. In fact, formulating the solution in algebraic notation may be more
awkward and more difficult than formulating it in assembly language. The answer is, of
course, to use a more suitable high-level language. Languages specifically designed for
tasks such as those mentioned above do exist - they are called system implementation
languages. However, these languages are less widely used and standardized than
FORTRAN.

Inefficiency

High-level languages do not produce very efficient machine language programs.


The basic reason for this is that compilation is an automatic process which is riddled with
compromises to allow for many ranges of possibilities. The compiler works much like a
computerized language translator - sometimes the words are right but the sounds and
sentence structures are awkward. A simple compiler cannot know when a variable is no
longer being used and can be discarded, when a register should be used rather than a
memory location, or when variables have simple relationships. The experienced pro­
grammer can take advantage of shortcuts to shorten execution time or reduce memory
usage. A few compilers (known as optimizing compilers) can also do this, but such com­
pilers are much larger than regular compilers.

SUMMARY OF ADVANTAGES AND DISADVANTAGES

Advantages of High-Level Languages:

Easier to learn (and teach to others)


More convenient descriptions of tasks
Less time spent writing programs
Easier documentation
Standard syntax
Independence of the structure of a particular computer
Portability
Availability of library and other programs

Disadvantages of High-Level Languages:

Special rules
Extensive hardware and software support required
Orientation of common languages to algebraic or business problems
lnefficient programs
Difficulty of optimizing code to meet time and memory requirements
Inability to use special features of a computer conveniently
Introduction to Assembly Language Programming 1-11

HIGH-LEVEL LANGUAGES FOR MICROPROCESSORS

Microprocessor users will encounter several special difficulties when using


high-level languages. Among these are:

Few high-level languages exist for microprocessors. This is particularly true


for processors that are new, relatively unpopular, or intended for simple con­
trol applications.

Few standard languages are widely available.

Compilers usually require a large amount of memory or even a completely


different computer.

Most microprocessor applications are not well-suited to high-level


languages.

Many microprocessor languages produce no object program. That is, they


translate the program and run it line by line - this is referred to as interpreting
rather than compiling - or they produce an output that requires special
systems software (a run-time package) to execute. Either approach may result
in programs that execute slowly and use a large amount of memory. BASIC
and PASCAL, the most commonly available high-level languages, generally
use one of these approaches.

Memory costs are often critical in microprocessor applications.

The relatively small number of high-level languages for microcomputers is a


result of the short history of microprocessors and their origin in the semiconductor
industry, rather than in the computer industry. Among the high-level languages that are
most often available are BASICS, PASCAL6. 7, FORTRAN, 0, and the PL/1-type
languages such as PL/M9.
Many of the high-level languages that exist do not conform to recognized stan­
dards, so the microprocessor user cannot expect to gain much program portability,
access to program libraries, or use of previous experience or programs. The main advan­
tages remaining are the reduction in programming effort, easier documentation, and the
smaller amount of detailed understanding of the computer architecture that is necess­
ary.

Overhead for High-Level Languages

The overhead involved in using a high-level language with microprocessors is


considerable. Until very recently, microprocessors have been better suited to control
and slow interactive applications than to the character manipulation and language
analysis involved in compilation. Therefore, compilers for some microprocessors will
not run on a microprocessor-based system. Instead, they require a much larger com­
puter; that is, they are cross-compilers rather than self-compilers. A user must not only
bear the expense of the larger computer, but must also transfer the program from the
larger computer to the micro.
Some self-compilers are available. These compilers run on the microcomputer for
which they produce object code. Unfortunately, they usually require large amounts of
memory ( 16K or more), plus special supporting hardware and software.
1-12 6809 Assembly Language Programming

Unsuitability of High-Level Languages

High-level languages also are not generally well-suited to microprocessor applica­


tions. Most of the common languages were devised either to help solve scientific prob­
lems or to handle large-scale business data processing. Few microprocessor applications
fall in either of these areas. Most microprocessor applications involve sending data and
control information to output devices and receiving data and status information from
input devices. Often the control and status information consists of a few binary digits
with very precise hardware-related meanings. If you try to write a typical control pro­
gram in a high-level language, you may feel like someone who is trying to eat soup with
chopsticks. For tasks in such areas as test equipment, terminals, navigation systems,
signal processing, and business equipment, the high-level languages work much better
than they do in instrumentation, communications, peripherals, and automotive applica­
tions.

Application Areas for Language Levels

Applications better suited to high-level languages are those which require large
memories. If, as in a valve controller, electronic game, appliance controller, or small
instrument, the cost of a single memory chip is important, then the inefficient memory
use of high-level languages is intolerable. If, on the other hand, as in a terminal or test
equipment, the system has many thousands of bytes of memory anyway, this ineffi­
ciency is not as important. Clearly the size and volume of the product are important fac­
tors as well. A large program will greatly increase the advantages of high-level
languages. On the other hand, a high-volume application will mean that fixed software
development costs are not as important as memory costs that are part of each system.

WHICH LEVEL SHOULD YOU USE?

Which language level you use depends on your particular application. Let us
briefly note some of the factors which may favor particular levels:

Applications for Machine Language:

Virtually no one programs in machine language because it wastes human time


and is difficult to document. An assembler costs very little and greatly reduces
programming time.

Applications for Assembly Language:

Short to moderate-sized programs


Applications where memory cost is a factor
Real-time control applications
Limited data processing
High-volume applications
Applications involving more input/output or control than computation

Applications for High-Level Language:

Long programs
Introduction to Assembly Language Programming 1-13

Low-volume applications
Applications where the amount of memory required is already very large

Applications involving more computation than input/output or control


Compatibility with similar applications using larger computers

Availability of specific programs in a high-level language which can be used in


the application

Other Considerations

Many other factors are also important, such as the availability of a large computer
for use in development, experience with particular languages, and compatibility with
other applications.
If hardware will ultimately be the largest cost in your application, or if speed is crit­
ical, you should favor assembly language. But be prepared to spend much extra time in
software development in exchange for lower memory costs and higher execution
speeds. If software will be the largest cost in your application, you should favor a high­
level language. But be prepared to spend the extra money required for the supporting
hardware and software.
Of course, no one except some theorists will object if you use both assembly and
high-level languages. You can write the program originally in a high-level language and
then patch some sections in assembly language.1o. " However, most users prefer not to
do this because it can create havoc in debugging, testing, and documentation.

FUTURE TRENDS IN LANGUAGE LEVELS

We expect the future will favor high-level languages for the following reasons:

Programs always add extra features and grow larger

Hardware and memory are becoming less expensive


Software and programmers are becoming more expensive

Memory chips are becoming available in larger sizes, at lower "per bit" cost,
so actual savings in chips are less likely
More suitable and more efficient high-level languages are being developed
More standardization of high-level languages will occur

Assembly language programming of microprocessors will not be a dying art any


more than it is for large computers. But longer programs, cheaper memory, and more
expensive programmers will make software costs a larger part of most applications. The
edge in many applications will therefore go to high-level languages.

WHY THIS BOOK?

If the future favors high-level languages, why have a book on assembly language
programming? The reasons are:

l. Most industrial microcomputer users program in assembly language (almost


two thirds, according to a recent survey).
1-14 6809 Assembly Language Programming

2. Many microcomputer users will continue to program in assembly language


since they need the detailed control that it provides.

3. No suitable high-level language has yet become widely available or standard­


ized.

4. Many applications require the efficiency of assembly language.

5. An understanding of assembly language can help in evaluating high-level


languages.

6. Almost all microcomputer programmers ultimately find that they need


some knowledge of assembly language, most often to debug programs, write
110 routines, speed up or shorten critical sections of programs written in high­
level languages, utilize or modify operating system functions, and understand
other people's programs.

The rest of this book will deal exclusively with assemblers and assembly language
programming. However, we do want readers to know that assembly language is not the
only alternative. You should watch for new developments that may significantly reduce
programming costs if such costs are a major factor in your application.

REFERENCES

1. W. P. Fischer, "Microprocessor Assembly Language Draft Standard," Computer,


December 1979, pp. 96-109.

2. M. H. Halstead, Elements of Software Science, American Elsevier, New York, 1977.

3. L. H. Putnam and A. Fitzsimmons, "Estimating Software Costs," Datamation, Sep­


tember 1979, pp. 189-98.

4. M. Phister, Jr., Data Processing Technology and Economics, Santa Monica Publishing
Co., Santa Monica, Calif., 1976. Also available from Digital Press, Educational Ser­
vices, Digital Equipment Corp., Bedford, Mass.

5. Albrecht, Finkel, and Brown, BAS/C for Home Computers, Wiley, New York, 1978.

6. G. M. Schneider et al., An Introduction to Programming and Problem Solving with


PASCAL, Wiley, New York, 1978.

7. K. L. Bowles, Microcomputer Problem Solving Using PASCAL, Springer-Verlag, New


York, 1977.

8. B. W. Kernighan and D.M. Ritchie, The C Programming Language, Prentice-Hall,


Englewood Cliffs, N. J., 1978.

9. D. D. McCracken, A Guide to PL/M Programming for Microcomputer Applications,


Addison-Wesley, Reading, Mass., 1978.

10. P. Caudill, "Using Assembly Coding to Optimize High-Level Language Pro­


grams," Electronics, February 1, 1979, pp. 121-24.

11. D. B. Wecker et al., "High Level Design Language Develops Low Level
Microprocessor-Independent Software," Computer Design, June 1979, pp. 140-49.
2
Assemblers

This chapter discusses the functions performed by assemblers, beginning with


features common to most assemblers and proceeding through more elaborate
capabilities such as macros and conditional assembly. You may wish to skim this chapter
for the present and return to it when you feel more comfortable with the material.

FEATURES OF ASSEMBLERS

As we mentioned previously, today's assemblers do much more than translate


assembly language mnemonics into binary codes. But we will describe how an assem­
bler handles the translation of mnemonics before describing additional assembler
features. Finally we will explain how assemblers are used.

ASSEMBLY LANGUAGE FIELDS

Assembly language instructions (or "statements") are divided into a number


of "fields," as shown in Table 2-1.
The operation code field is the only field which can never be empty; it always
contains either an instruction mnemonic or a directive to the assembler, sometimes
called a "pseudo- instruction," "pseudo-operation," or "pseudo-op."
The operand or address field may contain an address or data, or it may be
blank.
2-2 6809 Assembly Language Programming

Table 2-1. The Fields of an Assembly Language Instruction

Label Operation Code Operand or


Field or Mnemonic Address Comment Field
Field Field

START LOA VAL1 LOAD FIRST NUMBER INTO A


ADDA VAL2 ADD SECOND NUMBER TO A
STA SUM STORE SUM
NEXT ? ? NEXT INSTRUCTION

VAL1 RMB
VAL2 RMB
SUM RMB

The comment and label fields are optional. A programmer will assign a label to
a statement or add a comment as a personal convenience: namely, to make the pro­
gram easier to read and use.
Of course, the assembler must have some way of telling where one field ends
and another begins. Assemblers that use punched card input often require that each
field start in a specific card column. This is a "fixed format." However, fixed formats are
inconvenient when the input medium is paper tape; fixed formats are also a nuisance to
programmers. The alternative is a "free format" where the fields may appear anywhere
on the line.

Delimiters

If the assembler cannot use the position on the line to tell the fields apart, it must
use something else. Most assemblers use a special symbol or "delimiter" at the
beginning or end of each field. The most common delimiter is the space character.
Commas, periods, semicolons, colons, slashes, question marks, and other characters
which would not otherwise be used in assembly language programs also may serve as
delimiters. Table 2-2 lists standard 6809 assembler delimiters.
You will have to exercise a little care with delimiters. Some assemblers are
fussy about extra spaces or the appearance of delimiters in comments or labels. A
well-written assembler will handle these minor problems, but many assemblers are
not well-written. Our recommendation is simple: avoid potential problems if you can.
The following rules will help:

Do not use extra spaces, particularly after commas that separate operands.

Do not use delimiter characters in names or labels.

Include standard delimiters even if your assembler does not require them.
Then it will be more likely that your programs are in correct form for another
assembler.
Assemblers 2-3

Table 2-2. Standard 6809 Assembler Delimiters

'space' Between label and operation code, between


operation code and address. and before
an entry in the comment field
Between operands in the address field
Before an entire line of comment

labels

The label field is the first field in an assembly language instruction; it may be
blank. If a label is present, the assembler defines the label as equivalent to the address
into which the first byte of the object code resulting from that instruction will be loaded.
You may subsequently use the label as an address or as data in another instruction's
address field. The assembler will replace the label with the assigned value when creating
an object program.
Labels are most frequently used in Jump, Call, or Branch instructions. These
instructions place a new value in the Program Counter and so alter the normal sequen­
tial execution of instructions. JUMP 1501 6 means "place the value 15016 in the Program
Counter." The next instruction to be executed will be the one in memory location 15016.
The instruction JUMP START means "place the value assigned to the label START in
the Program Counter." The next instruction to be executed will be the one at the
address corresponding to the label START. Table 2-3 contains an example.
Why use a label? Here are some reasons:

A label makes a program location easier to find and remember.

The label can easily be moved, if required, to change or correct a program. The
assembler will automatically change all instructions that use the label when the
program is reassembled.

The assembler or loader can relocate the whole program by adding a constant
(a "relocation constant") to each address in which a label was used. Thus we
can move the program to allow for the insertion of other programs or simply to
rearrange memory.

The program is easier to use as a library program; that is, it is easier for some­
one else to take your program and add it to some totally different program.

You do not have to figure out memory addresses. Figuring out memory
addresses is particularly difficult with microprocessors which have instructions
that vary in length.

You should assign a label to any instruction that you might want to refer to later.
The next question is how to choose a label. The assembler often places some
restrictions on the number of characters (usually 5 or 6), the leading character (often
must be a letter), and the trailing characters (often must be letters, numbers, or one of a
few special characters). Beyond these restrictions, the choice is up to you.
Our own preference is to use labels that suggest their purpose, i.e., mnemonic
labels. Typical examples are ADDW in a routine that adds one word into a sum, SRETX
in a routine that searches for the ASCII character ETX, or NKEYS for a location in data
memory that contains the number of key entries. Meaningful labels are easier to
2-4 6809 Assembly Language Programming

Table 2-3. Assigning and Using a Label

Assembly language Program

START LOAD ACCUMULATOR

• (MAIN PROGRAM)

JUMP START

When the machine language version of this program is executed, the instruction JUMP
START causes the address of the instruction labeled START to be placed in the program
counter. That instruction will then be executed.

remember and contribute to program documentation. Some programmers use a stan­


dard format for labels, such as starting with LOOOO. These labels are self-sequencing
(you can skip a few numbers to permit insertions), but they do not help document the
program.
Some label selection rules will keep you out of trouble. We recommend the
following:

Do not use labels that are the same as operation codes or other mnemonics.
Most assemblers will not allow this usage; others will, but it is confusing.

Do not use labels that are longer than the assembler permits. Assemblers have
various truncation rules.

Avoid special characters (non-alphabetic and non-numeric) and lower-case


letters. Some assemblers will not permit them; others allow only certain ones.
The simplest practice is to stick to capital letters and numbers.

Start each label with a letter. Such labels are always acceptable.

Do not use labels that could be confused with each other. Avoid the letters I,
0, and Z and the numbers 0, 1, and 2. Also avoid things like XXXX and
XXXXX. There's no sense in tempting fate and Murphy's Law.

When you are not sure if a label is legal, do not use it. You will not get any real
benefit from discovering exactly what the assembler will accept.

These are recommendations, not rules. You do not have to follow them but don't blame
us if you waste time on unnecessary problems.

ASSEMBLER OPERATION CODES (MNEMONICS)


The main task of the assembler is the translation of mnemonic operation codes
into their binary equivalents. The assembler performs this task using a fixed table much
as you would if you were doing the assembly by hand.
The assembler must, however, do more than just translate the operation codes. It
must also somehow determine how many operands the instruction requires and what
type they are. This may be rather complex - some instructions (like a Halt) have no
Assemblers 2-5

operands, others(like an Addition or a Jump instruction) have one, while still others
(like a transfer between registers or a multiple-bit shift) require two. Some instructions
may even allow alternatives; for example, some computers have instructions(like Shift
or Clear) which can either apply to the Accumulator or to a memory location. We will
not discuss how the assembler makes these distinctions; we will just note that it must do
so.

ASSEMBLER DIRECTIVES

Some assembly language instructions are not directly translated into machine
language instructions. These instructions are directives to the assembler; they assign
the program to certain areas in memory, define symbois, designate areas of RAM for
temporary data storage, place tables or other fixed data in memory, allow references to
other programs, and perform minor housekeeping functions.
To use these assembler directives or pseudo-operations a programmer places the
directive's mnemonic in the operation code field, and, if the specified directive requires
it, an address or data in the address field.
The most common directives are:

DATA
EQUATE(=) or DEFINE
ORIGIN
RESERVE

Linking directives(used to connect separate programs) are:

ENTRY
EXTERNAL

Different assemblers use different names for those operations but their functions
are the same. Housekeeping directives include:

END
LIST
NAME
PAGE
SPACE
TITLE
PUNCH

We will discuss these pseudo-operations briefly, although their functions are


usually obvious.
2-6 6809 Assembly Language Programming

The DATA Directive

The DATA directive allows the programmer to enter fixed data into program
memory. This data may include:

Lookup tables
Code conversion tables
Messages
Synchronization patterns
Thresholds
Names
Coefficients for equations
Commands
Conversion factors
Weighting factors
Characteristic times or frequencies
Subroutine addresses
Key identifications
Test patterns
Character generation patterns
Identification patterns
Tax tables
Standard forms
Masking patterns
State transition tables

The OATA directive treats the data as a permanent part of the program.
The format of a DATA directive is usually quite simple. An instruction like:

DZCON DATI\ 12

will place the number 12 in the next available memory location and assign that loca­
tion the name DZCON. Every OATA directive usually has a label, unless it is one of a
series. The data and label may take any form that the assembler permits.
Most assemblers allow more elaborate OATA directives that handle a large
amount of data at one time, for example:

EMESS DATA 'ERROR'


SQRS DATA 1,4,9,16,25

A single directive may fill many bytes of program memory, limited perhaps by the
length of a line or by the restrictions of a particular assembler. Of course, you can always
overcome any restrictions by following one OAT A directive with another:
I
MESSG DATA 'NOW IS THE
DATA 'TIME FOR ALL I

I
DATA 'GOOD MEN
DATA 'TO COME TO THE '
DATA 'AID OF THEIR '
DATA I COUNTRY I
Assemblers 2-7

Microprocessor assemblers typically have some variations of standard DATA direc­


tives. DEFINE BYTE or FORM CONSTANT BYTE handles 8-bit numbers; DEFINE
WORD or FORM CONSTANT WORD handles 16-bit numbers or addresses. Other
special directives may handle character-coded data.

The EQUATE (or DEFINE) Directive

The EQUATE directive allows the programmer to equate names with addresses
or data. This pseudo-operation is almost always given the mnemonic EQU or =. The
names may refer to device addresses, numeric data, starting addresses, fixed addresses,
etc.
The EQUATE directive assigns the numeric value in its operand field to the
label in its label field. Here are two examples:

TTY EQU 5
LAST EQU 5000

Most assemblers will allow you to define one label in terms of another, for example:

LAST EQU FINAL


STl EQU START+l

The label in the operand field must, of course, have been previously defined. Often, the
operand field may contain more complex expressions, as we shall see later. Double
name assignments (two names for the same data or address) may be useful in patching
together programs that use different names for the same variable (or different spellings
of what was supposed to be the same name).
Note that an EQU directive does not cause the assembler to place anything in
memory. The assembler simply enters an additional name into a table (called a
"symbol table") which the assembler maintains. This table, unlike the mnemonic
table, must be in RAM since it varies with each program. The assembler always needs
some RAM to hold the symbol table; the more RAM it has, the more symbols it can
accept. This RAM is in addition to any that the assembler needs as temporary storage.
When do you use a name? The answer is: whenever you have a parameter that
you might want to change or that has some meaning besides its ordinary numeric value.
We typically assign names to time constants, device addresses, masking patterns, con­
version factors, and the like. A name like DELAY, TTY, KBD, KROW, or OPEN not
only makes the parameter easier to change, but it also adds to program documentation.
We also assign names to memory locations that have special purposes; they may hold
data, mark the start of the program, or be available for intermediate storage.
What name do you use? The best rules are much the same as in the case of
labels, except that here meaningful names really count. Why not call the teletypewriter
TTY instead of X 15, a bit time delay BTIME or BTDL Y rather than WW, the number of
the "GO" key on a keyboard GOKEY rather than HORSE? This advice seems
straightforward, but a surprising number of programmers do not follow it.
Where do you place the EQUATE directives? The best place is at the start of
the program, under appropriate comment headings such as 110 ADDRESSES, TEM­
PORARY STORAGE, TIME CONSTANTS, or PROGRAM LOCATIONS. This
makes the definitions easy to find if you want to change them. Furthermore, another
user will be able to look up all the definitions in one centralized place. Clearly this prac­
tice improves documentation and makes the program easier to use.
Definitions used only in a specific subroutine should appear at the start of the
subroutine.
2-8 6809 Assembly Language Programming

The ORIGIN Directive

The ORIGIN directive (almost always abbreviated ORG) allows the pro­
grammer to specify the memory locations where programs, subroutines, or data will
reside. Programs and data may be located in different areas of memory depending on
the memory configuration. Startup routines, interrupt service routines, and other
required programs may be scattered around memory at fixed or convenient addresses.
The assembler maintains a Location Counter (comparable to the computer's
Program Counter) which contains the location in memory of the next instruction or
data item being processed. An ORG directive causes the Assembler to place a new
value in the Location Counter, much as a Jump instruction causes the CPU to place a
new value in the Program Counter. The output from the Assembler must not only con­
tain instructions and data, but must also indicate to the loader program where in
memory it should place the instructions and data.
Microprocessor programs often contain several ORIGIN statements for the
following purposes:

Reset (startup) address

Interrupt service addresses

Trap (software interrupt) addresses

RAM storage

Memory stack

Main program

Subroutines

Memory addresses used for input/output devices or special functions

Still other ORIGIN statements may allow room for later insertions, place tables or data
in memory, or assign vacant RAM space for data buffers. Program and data memory in
microcomputers may occupy widely scattered addresses to simplify the hardware.
Typical ORIGIN statements are:
ORG RESET
ORG 1000
ORG INT3

Some assemblers assume an origin of zero if the programmer does not put an ORG
statement at the start of the program. The convenience is slight; we recommend the
inclusion of an ORG statement to avoid confusion.

The RESERVE Directive

The RESERVE directive allows the programmer to allocate RAM for various
purposes such as data tables, temporary storage, indirect addresses, a Stack, etc.
Using the RESERVE directive, you assign a name to the memory area and de­
clare the number of locations to be assigned. Here are some examples:
NO KEY RESERVE l
TEMP RESERVE 50
VOLTG RESERVE 80
BUF'R RESERVE 100

You can use the RESERVE directive to reserve memory locations in program memory
or in data memory; however, the RESERVE directive is more meaningful when applied
to data memory.
Assemblers 2-9

In reality, all the RESERVE directive does is increase the assembler's Location
Counter by the amount declared in the operand field. The assem bier does not actually
produce any object code.
Note the following features of RESERVE:

1. The label of the RESERVE directive is assigned the value of the first
address reserved. For example, the pseudo-operation:
TEMP RESERVE 20

reserves 20 bytes of RAM and assigns the name TEMP to the address of the
first byte.

2. You must specify the number of locations to be reserved. There is no


default case.

3. No data is placed in the reserved locations. Any data that, by chance, may be
in these locations will be left there.

Some assemblers allow the programmer to specify initial values for the
RESERVE area in RAM. We strongly recommend that you do not use this feature; it
assumes that the program (along with the initial values) will be loaded from an external
device (e.g., paper tape or floppy disk) each time it is run. Microprocessor programs, on
the other hand, often reside in non-volatile ROM and start when power comes on. The
RAM in such situations does not retain its contents, nor is it reloaded. Therefore,
always include instruction sequences to initialize RAM in your program; this will insure
that initialization occurs every time the program is executed and not just during load
time.

Linking Directives

We often want statements in one program or subroutine to use names that are
defined in a different assembly. Such uses are called "external references"; a special
linking program is necessary to actually fill in the values and determine if any names are
undefined or doubly defined.
The directive EXTERNAL, usually abbreviated EXT, signifies that the name
is defined elsewhere.
The directive ENTRY, usually abbreviated ENT, signifies that the name is
available for use elsewhere; that is, it is defined in this program.
The precise way in which linking directives are implemented varies greatly from
assembler to assembler. We will not refer to such directives again, but they are very
useful in actual applications.

Output Control Directives

There are various assembler directives that affect the operation of the assem­
bler and its program listing rather than the output program itself. Common house­
keeping directives include:

END, which marks the end of the assembly language source program.

LIST, which tells the Assembler to print the source program. Some assemblers
2-10 6809 Assembly Language Programming

allow such variations as NO LIST or LIST SYMBOL TABLE to avoid long,


repetitive listings.

NAME or TITLE, which prints a name at the top of each page of the listing.

PAGE or SPACE, which skips to the next page or next line, respectively, and
improves the appearance of the listing, making it easier to read.

PUNCH, which transfers subsequent object code to the paper tape punch. This
pseudo-operation may in some cases be the default option and therefore
unnecessary.

When to Use Labels

Users often wonder if or when they can assign a label to an assembler directive.
These are our recommendations:

All EQ UATE directives must have labels; they are useless otherwise, since
the purpose of an EQUATE is to define its label.

DATA and RESERVE directives usually have labels. The label identifies the
first memory location used or assigned.

Other directives should not have labels. Some assemblers allow such labels,
but we recommend against their use because there is no standard way to
interpret them.

OPERANDS AND ADDRESSES

Most assemblers allow the programmer a lot of freedom in describing the con­
tents of the Operand or Address field. But remember that the assembler has built-in
names for registers and instructions and may have other built-in names. We will now
describe some common options for the operand field.

Decimal Numbers

Most assemblers assume all numbers to be decimal unless they are marked
otherwise. So:
ADD 100

means "add the contents of memory location 10010 to the contents of the Accumula­
tor."

Other Number Systems

Most assemblers will also accept binary, octal, or hexadecimal entries. But you
must identify these number systems in some way: for example, by preceding or
following the number with an identifying character or letter. Here are some common
idenlifters:

B or % for binary

0,@, Q, or C for octal (the letter 0 should be avoided because of the confusion
with zero)
Assemblers 2-11

H or$ for hexadecimal (or standard BCD)

D for decimal. D may be omitted; it is the default case.

Assemblers generally require hexadecimal numbers to start with a digit (for example,
OA36 instead of A36) in order to distinguish between numbers and names or labels. It is
good practice to enter numbers in the base in which their meaning is the clearest: that is,
decimal constants in decimal; addresses and BCD numbers in hexadecimal; masking
patterns or bit outputs in binary if they are short, and in hexadecimal if they are long.

Names

Names can appear in the operand field; they will be treated as the data that
they represent. Remember, however, that there is a difference between operands and
addresses. In a 6809 assembly language program the sequence:
FIVE EQU 5
ADDA FIVE

will add the contents of memory location5 (not necessarily the number 5) to the con­
tents of the accumulator. A sequence which adds in the number 5 itself would be
FIVE EQU 5
ADDA. #FIVE

The symbol# tells the assembler that the number represented by the name FIVE is the
value of the operand instead of its memory location.

The Location Counter

You can use the current value of the location counter, which is usually referred
to as * or $. This is useful mainly in Jump instructions; for example:
JUMP *+6

causes a Jump to the memory location 6 bytes beyond the byte that contains the first
byte of the JUMP instruction.

} JUMP • + 6 code stored here

6 locations

- Jump here

One reason to use this technique is to reduce the number of symbols in an assem­
bly language program. This may be necessary if the assembler can handle only a limited
number of symbols. Reducing the number of symbols may also decrease assembly time.
Such benefits are almost negligible, however, unless your program is extremely large or
your assembler rather primitive.
Most microprocessors have many two and three-byte instructions. Thus you will
have difficulty determining exactly how far apart two assembly language statements are.
2-12 6809 Assembly Language Programming

Using offsets from the location counter therefore frequently results in errors that you
can avoid if you use labels.

Character Codes

Most assemblers allow text to be entered as ASCII strings. Such strings may be
surrounded either with single or double quotation marks; strings may also use a begin­
ning or ending symbol such as A or C. A few assemblers also permit EBCDIC strings.
We recommend that you use character strings for all text. It improves the clarity
and readability of the program.

Arithmetic and Logical Expressions

Assemblers permit combinations of the data forms described above, connected


by arithmetic, logical, or special operators. These combinations are called expres­
sions. Almost all assemblers allow simple arithmetic expressions such as START + l.
Some assemblers also permit multiplication, division, logical functions, shifts, etc. Note
that the assembler evaluates expressions at assembly time. Even though an expression
in the operand field may involve division, you may not be able to use division in the
logic of your own program - unless you write a subroutine for that specific purpose.
Assemblers vary in what expressions they accept and how they interpret them.
Complex expressions make a program difficult to read and understand.
We have made some recommendations during this section but will repeat them
and add others here. In general, the user should strive for clarity and simplicity.
There is no payoff for being an expert in the intricacies of an assembler or in having the
most complex expression on the block. We suggest the following approach:

Use the clearest number system or character code for data.

Masks and BCD numbers in decimal, ASCII characters in octal, or ordinary


numerical constants in hexadecimal serve no purpose and therefore should
not be used.

Remember to distinguish data from addresses.

Don't use offsets from the Location Counter.

Keep expressions simple and obvious. Don't rely on obscure features of the
assembler.

CONDITIONAL ASSEMBLY

Some assemblers allow you to include or exclude parts of the source program,
depending on conditions existing at assembly time. This is called conditional assem­
bly; it gives the assembler some of the flexibility of a compiler. Most microcomputer
assemblers have limited capabilities for conditional assembly. A typical form is:
IF COND

(CONDITIONAL PROGRAM)

END IF
Assemblers 2-13

If the expression COND is true at assembly time, the instructions between IF and
ENDIF (two pseudo-operations) are included in the program.
Typical uses of conditional assembly are:

To include or exclude extra variables

To place diagnostics or special conditions in test runs

To allow data of various bit lengths

Unfortunately, conditional assembly tends to clutter programs and make them difficult
to read. Use conditional assembly only if it is necessary.

MACROS

You will often find that particular sequences of instructions occur many times in a
source program. Repeated instruction sequences may reflect the needs of your program
logic, or they may be compensating for deficiencies in your microprocessor's instruction
set. You can avoid repeatedly writing out the same instruction sequence by using a
"macro."
Macros allow you to assign a name to an instruction sequence. You then use
the macro name in your source program instead of the repeated instruction sequence.
The assembler will replace the macro name with the appropriate sequence of instruc­
tions. The shaded parts of Figure 2-1 illustrate the assembler's treatment of a macro in
an example program. Do not bother trying to figure out what the program or the instruc­
tions do; just observe that the assembler expands the macro MAC! into the defined
sequence.
A macro resembles a subroutine because it is a shorthand reference to a fre­
quently used instruction sequence. However, macros are not the same as subroutines.
The code for a subroutine occurs once in a program, and program execution branches to
the subroutine. In contrast, the assembler replaces each occurrence of a macro name
with the specified sequence of instructions; therefore program execution does not
branch to a macro as it does to a subroutine. A macro name is a user-defined assembler
directive; it directs assembly rather than program execution.

Advantages of Macros:

Shorter source programs


Better program documentation
Use of debugged instruction sequences. Once the macro has been debugged,
you are sure of an error-free instruction sequence every time you use the
macro.
Easier changes. Change the macro definition and the assembler makes the
change for you every time the macro is used.
Inclusion of commands, keywords, or other computer instructions in the basic
instruction set. You can use macros to extend or clarify the instruction set.
2-14 6809 Assembly Language Programming

Assembler Input Assembler Output


Source Program Object Code Corresponding Mnemonics

MACl MACR (Macro definition)


CLRA
SUBA ,Y +
ASLA
ENDM (End of macro definition)
E6 9F 2025 LDB [OFFSETl
3A ABX
(Beginning of main program)
En 84 LDB ,X
LOB
ABX
[OFFSET]
4F
-� i:L. MACl
CLRA
LOB ,X AO AO SUBA ,Y +
MACl 48 ASLA

MUL
- -
3D
-
1- MUL
-�

STO RESLOC FD 2027 STD RESLOC


ROLB 59 ROLB
AOOB u CB 01 ADOB n
-
MACl ·
- -
MACl •t;.t:;::,
ADOO RESLOC 4F CLRA
STO RESLOC AO .a.o SUBA ,Y+
-
ASLA
l
MACl -
48 --

BYTE F3 2027 ADDO RESLOC


STA
ALTER FD 2027 STD RESLOC
BCC
.. IY\ACl
4F CLRA
AO AO SUBA ,Y+
48 ASLA
- -· -

B7 2029 STA BYTE


24 OS BCC ALTER

Figure 2-1. Expansion of a Macro by the Assembler


t

Disadvantages of Macros:

Since the macro is expanded every time it is used, memory space may be
wasted by the repetition of instruction sequences.

A single macro may create a lot of instructions.

Lack of standardization makes programs difficult to read and understand.

Possible effects on registers and flags may not be clearly described.

One problem is that variables used in a macro are only known within it (i.e., they are
local rather than global). This can often create a great deal of confusion without any gain
in return. You should be aware of this problem when using macros.'

COMMENTS

All assemblers allow you to place comments in a source program. Comments


have no effect on the object code, but they help you to read, understand, and document
the program. Good commenting is an essential part of writing computer programs;
programs without comments are very difficult to understand.
We will discuss commenting along with documentation in a later chapter, but
here are some guidelines:

Use comments to tell what application task the program is performing, not
how the microcomputer executes the instructions.
Assem biers 2-15

Comments should say things like "IS TEMPERATURE ABOVE LIMIT?,"


"LINE FEED TO TTY," or "EXAMINE LOAD SWITCH."

Comments should not say things like "ADD 1 TO ACCUMULATOR,"


"JUMP TO START," or "LOOK AT CARRY." You should describe how
the program is affecting the system; internal effects on the CPU are seldom of
any interest.

Keep comments brief and to the point. Details should be available elsewhere
in the documentation.

Comment all key points.

Do not comment standard instructions or sequences that change counters or


pointers; pay special attention to instructions that may not have an obvious
meaning.

Do not use obscure abbreviations.

Make the comments neat and readable.

Comment all definitions, describing their purposes. Also mark all tables and
data storage areas.

Comment sections of the program as well as individual instructions.

Be consistent in your terminology. You can (should) be repetitive; you need


not consult a thesaurus.

Leave yourself notes at points that you find confusing: for example,
"REMEMBER CARRY WAS SET BY LAST INSTRUCTION." If such
points get cleared up later in program development, you may drop these com­
ments in the final documentation.

A well-commented program is easy to use. You will recover the time spent in comment­
ing many times over. We will try to show good commenting style in the programming
examples, although we often over-comment for instructional purposes.

TYPES OF ASSEMBLERS

Although all assemblers perform the same tasks, their implementations vary
greatly. We will not try to describe all the existing types of assemblers; we will merely
define the terms and indicate some of the choices.
A cross-assembler is an assembler that runs on a computer other than the one
for which it assembles object programs.
The computer on which the cross-assembler runs is typically a large computer
with extensive software support and fast peripherals - such as an IBM 360 or 370, a
Univac 1108, or a Burroughs 6700. The computer for which the cross-assembler assem­
bles programs is typically a micro like the 6809 or 8080. Most cross-assemblers are writ­
ten in FORTRAN so that they are portable.
A self-assembler or resident assembler is an assembler that runs on the com­
puter for which it assembles programs. The self-assembler will require some memory
and peripherals, and it may run quite slowly compared to a cross-assembler.
2-16 6809 Assembly Language Programming

A macroassembler is an assembler that allows you to define sequences of


instructions as macros.
A microassembler is an assembler used to write the microprograms which
define the instruction set of a computer. Microprogramming has nothing specifically
to do with programming microcomputers.z. 3
A meta-assembler is an assembler that can handle many different instruction
sets. The user must define the particular instruction set being used.
A one-pass assembler is an assembler that goes through the assembly language
program only once. Such an assembler must have some way of resolving forward
references, for example, Jump instructions which use labels that have not yet been
defined.
A two-pass assembler is an assembler that goes through the assembly language
source program twice. The first time the assembler simply collects and defines all the
symbols; the second time it replaces the references with the actual definitions. A two­
pass assembler has no problems with forward references but may be quite slow if no
backup storage (like a floppy disk) is available; then the assembler must physically read
the program twice from a slow input medium (like a teletypewriter paper tape reader).
Most microprocessor-based assemblers require two passes.

ERRORS

Assemblers normally provide error messages, often consisting of a single coded


letter. Some typical errors are:

Undefined name (often a misspelling or an omitted definition)

Illegal character (such as a 2 in a binary number)

Illegal format (wrong delimiter or incorrect operands)


Invalid expression (for example, two operators in a row)

Illegal value (usually too large)

Missing operand
Double definition (two different values assigned to one name)

Illegal label (such as a label on a pseudo-operation that cannot have one)

Missing label

Undefined operation code.

In interpreting assembler errors, you must remember that the assembler may get on the
wrong track if it finds a stray letter, an extra space, or incorrect punctuation. Many as­
semblers will then proceed to misinterpret the succeeding instructions and produce
meaningless error messages. Always look at the first error very carefully; subsequent
ones may depend on it. Caution and consistent adherence to standard formats will elimi­
nate many annoying mistakes.
Assemblers 2-17

LOADERS

The loader is the program which actually takes the output (object code) from
the assembler and places it in memory. Loaders range from the very simple to the very
complex. We will describe a few different types.
A "bootstrap loader" is a program that uses its own first few instructions to
load the rest of itself or another loader program into memory. The bootstrap loader
may be in ROM, or you may have to enter it into the computer memory using front
panel switches. The assembler may place a bootstrap loader at the start of the object pro­
gram that it produces.
A "relocating loader" can load programs anywhere in memory. It typically loads
each program into the memory space immediately following that used by the previous
program. The programs, however, must themselves be capable of being moved around
in this way; that is, they must be relocatable. An "absolute loader," in contrast, will
always place the programs in the same area of memory.
A "linking loader" loads programs and subroutines that have been assembled
separately; it resolves cross-references - that is, instructions in one program that
refer to a label in another program. Object programs loaded by a linking loader must be
created by an assembler that allows external references. An alternative approach is to
separate the linking and loading functions and have the linking performed by a program
called a "link editor."

REFERENCES

1. A complete monograph on macros is M. Campbell-Kelly, An Introduction to Macros,


American Elsevier, New York, 1973.

2. A. Osborne, An Introduction to Microcomputers: Volume 1 -Basic Concepts,


Osborne/McGraw-Hill, Berkeley, Calif., 1980.

3. A. K. Agrawala and T. G. Rauscher, Foundations of Microprogramming, Academic


Press, New York, 1976.

4. D. W. Barron, Assemblers and Loaders, American Elsevier, New York, 1972.

5. C. W. Gear, Computer Organization and Programming, McGraw-Hill, New York,


1974.
3
6809 Machine Structure
and Assembly Language

This chapter outlines the 6809 processor's architecture and describes the syn­
tax rules of the Motorola assembler. Chapter 9 of An Introduction to Microcomputers:
Volume 2 - Some Real Microprocessors' describes the hardware aspects of the 6809
microprocessor, including its output signals and interfaces. This book considers the
6809 from the point of view of the assembly language programmer, to whom pins and
signals are irrelevant and microcomputers and minicomputers are essentially identical.
Later chapters of this book describe the 6809's stack and interrupt system in more
detail.
Tables 3-1 through 3-3 divide the 6809 instruction set into instructions that are
frequently used (Table 3-1), occasionally used (Table 3-2), and seldom used (Table
3-3). If you are an experienced assembly language programmer, you will probably not
find this division important; you may even disagree with it. However, if you are a
novice, we recommend that you write your first programs using only the frequently
used instructions (Table 3-1). This restriction will help you overcome the obstacle of
learning both the entire 6809 instruction set and the basic methods of assembly
language programming at the same time. Once you have mastered the concepts of as­
sembly language programming, you should start using other instructions (Tables 3-2
and 3-3).
3-2 6809 Assembly Language Programming

Table 3-1. Frequently Used Instructions of the 6809

Operation Code Meaning

ADC Add with Carry


ADD Add
AND Logical AND
ASL or LSL Arithmetic (Logical) Shift Left
BCC or BHS Branch if Carry Clear ("Higher or Same")
BCS or BLO Branch if Carry Set ("Lower")
BEQ Branch if Zero Set ("Equal")
BMI Branch if Sign (Negative) Set ("Minus")
BNE Branch if Zero Clear ("Not Equal")
BPL Branch if Sign (Negative) Clear ("Plus")
BRA Branch Always
BSR Branch to Subroutine
CLR Clear
CMP Compare
DEC Decrement by 1
INC Increment by 1
JSR Jump to Subroutine
LD Load
LSR Logical Shift Right
PSH Push Data onto Stack
PUL Pull Data from Stack
ROL Rotate Left
ROR Rotate Right
RTS Return from Subroutine
ST Store
SUB Subtract

Table 3-2. Occasionally Used Instructions of the 6809

Operation Code Meaning

AN DCC Logical AND Mask with Status Register (Clear Flags)


ASR Arithmetic Shift Right
BGE Branch if Greater Than or Equal
BGT Branch if Greater Than
BHI Branch if Higher
BIT Bit Test (Logical AND)
BLE Branch if Less Than or Equal
BLS Branch if Lower or Same
BLT Branch if Less Than
COM Ones Complement
DAA Decimal Adjust Accumulator A
EOR Exelusive OR
EXG Exchange Registers
JMP Jump
LEA Load Effective Address
MUL Multiply
NEG Twos Complement ("Negate")
NOP No Operation
OR Logical (Inclusive) OR
ORCC Logical OR Mask with Status Register (Set Flags)
RTI Return from Interrupt
SWI Softw are Interrupt
TFR Transfer Register to Register
TST Test for Zero or Minus
6809 Machine Structure and Assembly Language 3-3

Table 3-3. Seldom Used Instructions of the 6809

Operation Code Meaning

ABX Add Accumulator B to Index Register X


BRN Branch N ever (No Operation)
BV C Branch if Overflow Clear
BVS Branch if OverflowSet
CWAI Clear Condition Code Register Bits and Wait
for Interrupt
SBC Subtract with Carry (Borrow)
SEX Sign Extend
SYNC Synchronize with Interrupt Line

6809 REGISTERS AND FLAGS

The 6809 microprocessor has two accumulators, a status (or "condition code")
register, two index registers, two stack pointers, a program counter, and a direct page
register. The following diagram summarizes the 6809 registers. Note that the index
registers, stack pointers, and program counter are 16 bits long, whereas the accumula­
tors, direct page register, and condition code register are eight bits long.

8 bits Accumulator A } Double Accumulator D


8 bits Accumulator B

16 bits Index Register X

16 bits Index Register Y

16 bits UserStack Pointer U

16 bits HardwareStack PointerS (or SP)

16 bits Program Counter PC

8 bits Direct Page Register DP

8 bits Condition Code Register CC

The 6809's Condition Code register contains five status flags, two interrupt
control bits (one for the regular IRQ interrupt and one for the fast FIRQ interrupt), and
one bit used to differentiate between the regular and fast interrupts. The five status
flags are:
Carry/Borrow (C)
Overflow (0 or Vl
Zero (Z)
Sign S
I or N for Negative)
Half-Carry (H)

The flags occupy the following bit positions in the Condition Code register:

7 6 5 4 3 2 0 4 Bit No.

I I I I I I I I cl..
E F H I N
z v 4e- - -6809 Condition Code Register

E is the entire flag used to differentiate between regular and fast interrupts, F is the fast
interrupt mask bit, and I is the regular interrupt mask bit.
3-4 6809 Assembly Language Programming

6809 REGISTERS

The two accumulators, A and B, are both primary accumulators. The only
instructions that treat the accumulators differently are ABX (Add Accumulator B to
Index Register X), DAA (Decimal Adjust Accumulator A), and SEX (Sign Extend
Accumulator B into Accumulator A).
The two 8-bit Accumulators A and B can be referred to as a single 16-bit Double
Accumulator D. Within D, A contains the most significant bits and B the least signifi­
cant bits. The 6809 has special instructions for loading (LDD), storing {STD), adding
(ADDD), comparing (CMPD), and subtracting (SUBD) the Double Accumulator D.
Index Registers X and Y are typical microcomputer index registers, as de­
scribed in An Introduction to Microcomputers: Volume I.2 The X register is preferred over
theY register only because a few operation codes (such as CMP, LD, and ST) execute
more slowly when applied to Y than when applied to X.
Stack Pointer U is a cross between the typical microcomputer index register
and the typical microcomputer stack pointer as described in An Introduction to
Microcomputers: Volume I. Registers may be pushed onto or pulled from the User Stack
{indexed by the User Stack Pointer). However, the processor does not employ the User
Stack to store subroutine return addresses or the status of interrupted tasks� the pro­
cessor uses only the Hardware Stack for those purposes.
The 6809 has a Stack implemented in memory and indexed by the Hardware
Stack Pointer S as described in Volume 1 of An Introduction to Microcomputers. The
instruction set allows S, as well as U, to be used as a data counter or index register.
Memory reference instructions make it easy to store the contents of either
stack pointer or either index register in read/write memory. By assigning some
memory locations on the base (direct) page as storage for these four address registers,
you can put them all to multiple use. Another easy storage method is pushing the
registers onto a stack.
The program counter is a typical program counter, as described in Volume 1 of
An Introduction to Microcomputers.
The Direct Page Register DP generalizes the concept of a base page as described
in An Introduction to Microcomputers: Volume I. This register provides the eight most
significant bits of a 16-bit address in the direct (base page) addressing mode. In most
microprocessors (including the 6800), the base page is always page zero. The 6809
maintains compatibility with this concept by clearing the Direct Page register on hard­
ware Reset. The Direct Page register allows the programmer to move the base page any­
where in memory and thus take advantage of short paged addresses without being
limited to the first 256 bytes of memory. Different programs can have different base
pages, thus both making it unnecessary to apportion page zero and reducing the chance
of interference.

6809 FLAGS

The Carry flag holds the carry from the most significant bit produced by
arithmetic operations or shifts. Like most microprocessors, the 6809 inverts the actual
carry after subtraction so that the Carry flag also acts as a Borrow. The 6809 multiplica­
tion instruction, MUL, affects the Carry flag in yet another way: Carry represents bit 7
of the 16-bit result. This makes rounding to an 8-bit result very simple.
6809 Machine Structure and Assembly Language 3-5

The Zero flag is standard. It is set to 1 when any operation produces a zero
result. It is set to 0 when any operation produces a non-zero result.
The Sign (Negative) flag is standard. It takes on the value of the most signifi­
cant bit of any result. Thus, a Sign flag value of 1 identifies a negative result and a
Sign flag value of 0 identifies a positive result if the standard twos complement nota­
tion is being used. The Sign flag will be set or reset on the assumption that you are using
signed binary arithmetic. If you are not using signed binary arithmetic, you can ignore
the Sign flag or you can use it to identify the value of the most significant bit of the
result.
The Half-Carry flag holds any carry from bit 3 to 4 resulting from the execution
of an 8-bit addition instruction (ADC or ADD). The purpose of this flag is to simplify
Binary-Coded-Decimal (BCD) operations. This is the standard use of a Half-Carry flag
as described in An Introduction to Microcomputers: Volume I, Chapter 4 (the flag is re­
ferred to there as an "intermediate carry").
The Overflow flag represents standard arithmetic overflow as described in
Volume 1 of An Introduction to Microcomputers; that is, the flag is set when an
arithmetic result is greater in magnitude than can be represented in the register. A
processor implements this function by setting the overflow flag when the carry out of the
most significant bit is different from the carry out of the next most significant bit; that is,
an overflow is the exclusive-OR of the carries into and out of the sign bit. In the 6809,
logical operations clear the Overflow flag, as do loads and stores.
The I and F flags are standard interrupt disable or interrupt mask flags. When I or
F is 1, interrupts are disabled from the corresponding source (IRQ or FIRQ). When I
or F is 0, the corresponding interrupt is enabled.
The E (or Entire) flag differentiates between regular interrupts and fast inter­
rupts. E is set to 1 when any interrupt occurs that stacks the entire set of registers; E is
set to 0 when an FIRQ occurs, stacking only the program counter and Condition Code
register. The E flag thus allows proper unstacking of the registers by the RTI (return
from interrupt) instruction.
The flags do not change until the processor executes an instruction that
modifies them. Logical instructions, for example, do not affect the Carry or Half-Carry,
but they do affect the Sign, Zero, and Overflow flags. Any of the flags can be specifically ·";
set or cleared by means of an ORCC or ANDCC instruction with the appropriate mask. ;_. ·
You must use the bit positions shown earlier to create the mask; executing an ORCC
with a I in a particular bit position will set a flag, while executing an ANDCC with a 0 in a
particular bit position will clear a flag.
6809 literature refers to the Sign flag as a Negative flag and uses the symbol N for
it. We will follow this convention to be compatible with the literature and to avoid con­
fusion with the Hardware Stack Pointer (or S register). We will also follow the 6809
literature in referring to the Overflow flag by the symbol V (0 leads to continual confu­
sion) and the Half-Carry flag (sometimes called an Auxiliary or Intermediate Carry) by
the symbol H. The 6809's flags are set and reset as described for the hypothetical
microcomputer in An Introduction to Microcomputers: Volume 1.
3-6 6809 Assembly Language Programming

6809 ADDRESSING MODES

Assembly language instructions tell the processor what operation to perform


and what addresses to use in performing the operation - that is, where to find the
data to be operated upon. The part of an instruction that tells the processor what opera­
tion to perform is the "operation code." Appendix C lists the 6809 microprocessor's
mnemonic operation codes and their numerical equivalents. The part of an instruction
that tells the processor what addresses to use is the "operand" or "address field." The
processor may use this part of an instruction to determine where to obtain the operands
or where to store the result.

GENERAL DESCRIPTION OF ADDRESSING MODES

There are many different ways to specify what addresses the processor is to
use. These ways are called "addressing modes." We will describe them generally
before discussing how the 6809 processor implements them. The following two modes
do not involve memory at all:

1. Inherent addressing means that the operation code alone tells the processor
what to do. Typical inherent addressing instructions are Halt, No Operation,
and instructions that use specific registers.
2. Register addressing means that only registers are involved in the operation.
Typical of such operations are moving data from one register to another and
exchanging registers.

Common addressing modes that involve memory are as follows:

3. Immediate addressing means that the operand is located immediately after


the operation code in program memory.

4. Direct addressing means that the address to be used follows the operation
code in program memory.

5. Indexed addressing means that the address to be used is the sum of a base
address and an index or offset.

6. Indirect addressing means that the address to be used is either in a register or


in memory. That is, the instruction tells the processor where the address is,
not where the data is.

7. Relative addressing means that the operand is located a certain distance from
the current position in the program.

Chapter 6 of Volume 1 of An Introduction to Microcomputers describes all these


addressing modes plus their common combinations.
6809 Machine Structure and Assembly Language 3-7

6809 Addressing Modes

The 6809 microprocessor has a powerful and versatile set of addressing modes.
The available modes are the following, listed in the order in which we will describe
them:

1. Inherent operand (instructions that require no addresses)


2. Registers as operands (instructions that use only register contents as
operands)

The other modes specify memory addresses; they are:

3. Immediate

4. Base page direct

5. Extended direct
6. Extended indirect

7. Constant offset from base register

8. Indirect with constant offset from base register

9. Accumulator offset from base register

10. Indirect with accumulator offset from base register

II. Autoincrement or autodecrement

12. Indirect with autoincrement or autodecrement

13. Program relative for branches

EFFECTIVE ADDRESS

In describing how the processor executes these modes and how the programmer
uses them, we must often refer to the actual address that the processor ultimately
uses to perform the specified operation. We call that address the "effective address":
it is the place from which the processor obtains an operand or in which the processor
stores the result. In some modes (for example, immediate) the effective address is
simply the location immediately following the operation code. In other modes, deter­
mining the effective address may be complicated. The address may be part of the
instruction, the contents of a base register, or the contents of a pair of memory loca­
tions. Determining the effective address may involve computations, such as adding an
offset to a base register. Some of the addressing modes are difficult to understand, since
they involve sequences of operations that finally culminate in an effective address. We
will explain why these sequences are useful and we will describe typical cases from real
applications. You should try to trace each sequence, since the various addressing modes
are the keys to writing programs that are both general and powerful. Remember, the
processor always determines the effective address correctly, no matter how complex the
required operations are.
In the following discussion, we will describe each addressing mode, explain at
least one of its common uses, present a diagram of how it is executed, and discuss a
specific example. All of these together should give you a picture of the power of the
6809 microprocessor.
3-8 6809 Assembly Language Programming

MODES WHICH DO NOT SPECIFY


MEMORY LOCATIONS

INHERENT ADDRESSING

In this mode, the processor knows from the operation code alone which
addresses to use. For example, the instruction ABX (Add Accumulator B to Index
Register X) tells the processor where to get both operands for the addition. Similarly,
the instructions DAA (Decimal Adjust Accumulator A), MUL (Multiply), and SEX
(Sign Extend) also tell the processor which registers to use. NOP (No Operation) and
SYNC (Synchronize to External Event) require no operands, whereas RTI (Return
from Interrupt), RTS (Return from Subroutine), and SWI (Software Interrupt) all force
the processor to use the Hardware Stack Pointer to move data to or from memory. In all
these instructions, the operation codes are complete by themselves; no further address­
ing information is necessary.

REGISTER ADDRESSING

Single-operand instructions can be applied to either Accumulator A or


Accumulator B; the accumulator to be used is specified in the operation mnemonic.
Typical examples are CLRB (Clear Accumulator B) and INCA (Increment Accumula­
tor A). One bit in the actual operation code selects the accumulator. The following
instructions fall in this category: ASL or LSL (Logical Shift Left), ASR (Arithmetic
Shift Right), CLR (Clear: Set to Zero), COM (Ones Complement), DEC (Decrement:
Subtract l), INC (Increment: Add I), LSR (Logical Shift Right), NEG (Negate: Twos
Complement), ROL (Rotate Left), ROR (Rotate Right), and TST (Test for Zero or
Minus).
The instructions TFR (Transfer Registers) and EXG (Exchange Registers)
must have two registers of the same size as operands. For example, EXG X, U causes
the processor to exchange the contents of Index Register X and the User Stack Pointer.
The byte following the operation code designates On coded form) which registers
EXG or TFR is to use. We can illustrate these instructions as follows:

Memory

Operation Code mmmm


Register)Register 1
1 I 2 mmmm +

For details on how the registers are coded, see the descriptions of EXG and TFR
in Chapter 22.
The instructions PSH (Store Data in Stack) and PUL (Load Data from Stack)
also require a second byte that designates which registers are to be stored or loaded.
These instructions, however, may load or store any number of user registers. Each bit
of the second byte represents a register; if the bit is set, the processor will store the cor­
responding register in the stack or load it from the stack. For details on how the register
addressing byte is organized, see the descriptions of the PSH and PUL instructions in
Chapters 11 and 22.
6809 Machine Structure and Assembly Language 3-9

MEMORY ADDRESSING MODES

IMMEDIATE ADDRESSING

In immediate addressing, the data follows immediately after the operation


code. That is, the effective address is simply the contents of the program counter after
the processor has fetched the operation code. We can illustrate this mode as follows:

Memory

Operation Code mmmm


Effective Address =

mmmm + 1---i� Data mmmm + 1

In standard 6809 assembly language, we specify immediate addressing by pre­


ceding the operand with the #symbol. Instructions may require either 8-bit or 16-bit
immediate operands; 16-bit operands are stored with the most significant bits in the first
byte. For example, the 6809 assembler converts the statement

ADDll � S30

(#means "immediate addressing" and $ means "hexadecimal") into an ADD instruc­


tion that adds the value 3016 to Accumulator A. The following diagram illustrates the
execution of the instruction.

E F H N Z V C

ccR (.._.__ l _,_ x .._I_.._


.. _ l .... x l_.._ x .._I_xI
x l_. ..

D{: XX � _(
..
--- XX + 30 ) Program
Memory

\_
X

y mmmm
8B

u 30 mmmm + 1

s mmmm + 2

PC mm mm
.....-
-:t. mmmm + 2 mmmm + 3

DP

Immediate Addressing
ADDA #$30
One-byte Operand

As a specific example, assume that Accumulator A contains B716 initially. After the pro­
cessor executes ADDA #$30, the contents of Accumulator A will be B716 + 3016 =

E716• The processor increments its program counter twice, once after fetching the opera­
tion code and once after fetching the immediate data, 3016 in this example.
3-10 6809 Assembly Language Programming

16-Bit Operations

Instructions that handle 16 bits at a time require a double-byte immediate


operand. For example, the instruction

ADDD K$1057

causes the processor to add the 16-bit value 105716 to the Double Accumulator D.
Remember, D consists of Accumulators A and B with A holding the high-order byte.
The following diagram shows how the processor executes the instruction.

E F H N Z V C

ccR ._I ....


...__ .. ....__.__
l x...._
l .x..._l_x.._I __,x J

Program
jA XX
Memory
D
�B yy

y C3 mmmm

{
u 10 mmmm + 1

s 57 m;Tlmm + 2

PC mm mm mmmm + 3

P
D

Immediate Addressing
ADDD :lf$1057
Two-byte Operand

As a specific example, assume that the initial contents of the Double Accumulator
are 3A4816• After the processor executes the instruction ADDD ::#:$1057, the contents
of the Double Accumulator will be 3A4816 + 105716 = 4A9F16• The processor incre­
ments its program counter three times while executing the instruction, once after fetch­
ing the operation code and once after fetching each byte of the immediate operand.

Two-Byte Operation Codes

Some instructions require a two-byte operation code. Typical· examples are


CMPD, CMPY, LDS, and LOY. Since these instructions also require a 16-bit
immediate operand, the immediate versions are four bytes long. For example, the
instruction
LDS KS3F2A

has a two-byte operation code (IO CE ) , followed by a 16-bit (two-byte ) immediate


operand. We can illustrate the execution of this instruction as follows .
6809 Machine Structure and Assembly Language 3-11

E F H N Z V C

ccR ._I ..-'-


...._ -.._...&.- l_..�.
x l_. x..�..
1_o....
I.

Program
Memory
o{:
X

y mmmm
10
u
mmmm + 1

CE

{
s
3F mmmm + 2
PC mm mm
---
� mmmm + 4
2A mmmm + 3

DP

I mmedtate Addressmg
LOS #$3F2A
Two-byte Operation Code

Instructions that Lack an Immediate Mode

Some instructions do not make sense with immediate addressing.

1. You cannot store the contents of a register in a number, so Store instructions


cannot use immediate addressing.
2. You cannot transfer control to a number, so Jump and Jump-to-Subroutine
instructions cannot use immediate addressing.
3. You cannot clear or shift a specific number, so single-operand instructions
cannot use immediate addressing.

You should refer to Appendix Cor to your instruction set summary card if you are
not sure whether an instruction allows immediate addressing.

BASE PAGE DIRECT ADDRESSING

In this mode, the effective address is on the base or direct page as defined by the
contents of the direct page register. The low-order half of the address (that is, the
address on the direct page) follows the operation code in memory. We can illustrate
base page direct addressing as follows:

Memory

DP

Operation Code mmmm

qq mmmm + 1

Effective Address =p� qq

You should note that 6809 manufacturers usually refer to this mode as "direct,"
whereas Volume 1 of An Introduction to Microcomputers refers to it as "base page."
3-12 6809 Assembly Language Programming

This mode provides a short, quick way to use temporary storage on the direct
page. It is short and quick because the page number is in the direct page register on the
processor chip, thus saving a byte of program memory and a read cycle. Obviously, there
is an overall savings of time and memory only if the programmer rarely changes the con­
tents of the direct page register. Otherwise the instructions that load the direct page
register more than offset the savings from using it.
The standard 6809 assembler uses direct addressing whenever the mode is
available, no other mode is specified, and the address is on the direct page. The as­
sembler assumes that the direct page is page zero (thus maintaining compatibility with
the earlier 6800 microprocessor, which has no direct page register) unless told other­
wise; the programmer may specify a different direct page with a SETDP assembler
directive. The programmer may also force the assembler to use direct addressing by pre­
ceding an address with the symbol "<", but this is rarely necessary.
For example, the assembler converts the statement
ADDA #S30

into an ADD instruction that adds the contents of memory location pp3016 to
Accumulator A, where pp is the contents of the Direct Page register as shown in the
following diagram: Data
Memor y

E F H N Z V C

yy pp30

XX
o{:
X
Program
y
Memory

PC mm mm 98 mmmm

DP pp 30 mmmm + 1

mmmm + 2

mmmm + 3
Direct Addressing
ADDA $30

As a specific example, let us assume the initial contents of Accumulator A are


4716, the contents of the Direct Page register are 2B16, and the contents of memory
address 283016 are 6A16• After the processor executes the instruction, the sum in
Accumulator A will be 4716 + (pp3016) = 4716 + (2B3016) = 4716 + 6A16 = 8116. The
processor increments its program counter twice, once after fetching the operation code
and once after fetching the direct address.
6809 Machine Structure and Assembly Language 3-13

The direct address occupies only one byte even if the instruction ( such as
ADDD, LOS, or STX ) handles 16-bit operands. In that case, the processor uses the
addresses ppqq and ppqq + 1 to fetch or store the high-order and low-order bytes of the
data, respectively. Instructions such as LDY and STS require a two-byte operation code,
in which case the base page direct form occupies three bytes of program memory.

EXTENDED DIRECT ADDRESSING

In this mode, the effective address occupies the two bytes of program memory
immediately following the operation code. The high-order half of the address is in the
first byte; this is standard 6809 format. We can illustrate extended direct addressing as
follows:
Memory

Operation Code mmmm

pp mmmm + 1

qq mmmm + 2

You should note that 6809 manufacturers usually refer to this mode as "extended,"
whereas Volume 1 of An Introduction to Microcomputers refers to it as "direct" or
"extended direct."
This mode allows the processor to access any specific memory location. Of course,
you need not use extended addressing for memory locations that are on the direct page,
since the base page direct mode is shorter and faster. However, extended addressing is
the usual approach for handling a fixed address that is not on the direct page. This
mode is often used in performing input and output, since the memory addresses
assigned to 1/0 devices are rarely on the direct page.
The standard 6809 assembler uses extended addressing whenever the mode is
available, no other mode is specified, and the address is not on the direct page. Thus
extended addressing is the general default mode. The programmer may force the assem­
.
bler to use extended addressing by preceding the address with the symbol "> " , but this
is rarely needed.
For example, the assembler converts the statement

ADDA $1C48

into an ADD instruction that adds the contents of memory location 1C4810 to
Accumulator A as shown in the following diagram.
3-14 6809 Assembly Language Programming

Data
Memory

E F H N Z V C

CCR I I I I I I I I
X X X X X
yy 1C48

XX

o{:
X
Program
y Memory

PC mm mm BB mmmm

DP 1C mmmm + 1

48 mmmm + 2

mmmm + 3
Extended Addressing
ADDA $1C48

As a specific example, assume the initial contents of Accumulator A are F416 and
the contents of memory address 1C4816 are 3A16. After the processor executes the
instruction ADDA $1C48, the sum in Accumulator A will be F416 + 3A16 = 2E16. The
processor increments its program counter three times, once after fetching the operation
code and once after fetching each byte of the direct address.
If the instruction (for instance, CMPX or SUBD) handles 16-bit operands, the
addresses used are ppqq and ppqq + 1. If the instruction (for example, CMPY) requires
a two-byte operation code, the extended direct form requires four bytes of program
memory.

EXTENDED INDIRECT ADDRESSING

In this mode, the effective address is located at the address in the two bytes of
program memory immediately following the operation code. That is, the instruction
tells the processor where to find the address, not what its value is. You may compare
indirect addressing to a treasure hunt in which one clue tells you where to look for the
next clue, not where to find the actual treasure. If, as shown in the next illustration, the
two bytes following the operation code contain pp (first byte) and qq (second byte), the
effective address is located in addresses ppqq (first byte) and ppqq + 1 (second byte). So
the effective address in the illustration is rrss.
6809 Machine Structure and Assembly Language 3-15

Memory

Operation Code mmmm

pp mmmm + 1

�----�-:----�1:��
55 ppqq + 1

Effective Address = rr ss

The important point here is to see what this added complication does for us,
besides provide some confusion. Indirection allows a program to use different effec­
tive addresses without being changed, since all the program contains is the location of
the effective address, not its value. Why is that useful? Assume, for example, that our
application involves printing some results, as most applications do. We write a single
routine that takes the results from memory and sends them to an output device. (The
6809 uses memory-mapped input/output, so an output device is addressed using
memory addresses.) However, sometimes those results must be sent to a printer (for
permanent records), while at other times the results are merely displayed (to the opera­
tor) or reported via a remote line (to a central computer). If our routine sends the
results using extended indirect addressing, it can send them to any output device. All
the main program must do is place the address of the output device in the specified
memory locations. The approach is the same as that of television commercials which tell
you to call the telephone number that will appear on your screen. The same commercial
can be used nationwide; all the local station does is display the correct local number.
In the standard 6809 assembler format, you specify extended indirect address­
ing by placing the address in square brackets: for example, [D58A]. The address is
always interpreted as a 16-bit value and always occupies two bytes of program
memory. Instructions that use extended indirect addressing require a post byte after
the operation code, and this post byte must contain 9F w We will discuss post bytes in
more detail as part of the description of the indexed addressing modes.
For example, the assembler converts the statement

ADDA [$D58A]

into an ADD instruction that adds the contents of memory location rrss to Accumulator
A, where rr is the contents of address D58A1 6 and ss is the contents of address 058816 .
The following diagram illustrates the execution of the instruction.
3-16 6809 Assembly Language Programming

Data
Memory

yy rrss

E F H N z v c

CCR I I I I I I I I
X X X X X
rr 058A

ss 0588

o{: XX

X
Program
y Memory

PC mm mm AB mmmm

DP 9F mmmm + 1

05 mmmm + 2

SA mmmm + 3

Indirect Addressing
AOOA [$058AI

As a specific example, let us assume the initial contents of Accumulator A are


1F16 and the contents of memory addresses 058A16, 058B16, and 06E416 are 0616, E416,
and 3516 respectively. After the processor executes the instruction ADDA [$D58A], the
sum in Accumulator A will be 1F16 + ((D58A16):(058B16)) 1F16 + (06E416 )
=

=
IF16 + 3 516 5416• The processor increments its program counter four times, once
=

after fetching the operation code, once after fetching the post byte, and once after fetch­
ing each byte of the indirect address. Clearly this instruction takes extra time to execute
(see Appendix B), since the processor must go through a complex sequence to obtain
the actual data.

INDEXED MEMORY ADDRESSING MODES

In all the indexed addressing modes, the processor uses a base register. This
register may be one of the two index registers, one of the two stack pointers, or the
program counter. The instruction tells the processor which base register to use,
whether to add an offset to the contents of the base register, where to obtain the offset
if one is necessary, whether to change the contents of the base register, and whether
to use the indexed address directly or indirectly. Volume 1 of An Introduction to
Microcomputers describes the use of base registers in detail; their use allows program-
6809 Machine Structure and Assembly Language 3-17

mers to handle data structures that are defined by a base address and to write position­
independent code in which the location of the program itself is defined only by a base
address.

OBJECT CODE POST BYTE

The 6809's indexed and indirect addressing modes require that the operation
code be followed by a byte that differentiates among the various modes. We refer to
this extra byte as a "post byte." Figure 3- 1 shows the placement of the post byte in the
object code. Table 3-4 describes the meanings of the bit positions within the post byte. If
you wish more details, Appendix B contains a summary of the indexed modes and
Appendix E describes the meanings of all possible post bytes in numerical order.

Information in the Post Byte

Let us summarize the information contained in the post byte:

1. Which base register to use: Index Register X, Index Register Y, Stack


Pointer U, Stack Pointer S, or the program counter. Of course, extended
indirect addressing uses no base register at all.
2. Whether to add an offset to the base register.
3. Where to find the offset if it is necessary. The choices here are: within the
post byte itself, in the next one or two bytes of program memory, in
Accumulator A, in Accumulator B, or in Double Accumulator D.
4. Whether to change the base register's contents. The choices here are to add
1 or 2 to the base register after using it (sometimes called "postincrement")
or to subtract 1 or 2 from the base register before using it (sometimes called
"predecrement ").
5. Whether to use the address obtained so far directly or indirectly. That is,
whether to use the address to obtain the data or the address of the data. Using
an indexed address indirectly is often referred to as "preindexing" or
"indirect indexed addressing."

Unimplemented and Illegal Indexed Modes

Not all combinations are implemented. For example, there is no mode that both
changes the base register and adds an offset. Nor are there modes that use the program
counter as a base register and also change the base register or obtain the offset from
within the post byte or from an accumulator. Furthermore, adding 1 to a base register
that is used indirectly or subtracting 1 from it is illegal. This is because the base register
must point to a 2-byte address, and adding 1 to it or subtracing 1 from it would therefore
cause it to point to the middle of an address. We will describe the valid forms and their
uses as we proceed.
3-18 6809 Assembly Language Programming

Memory

Operation Code 7 6 5 4 3 2 1 0 ..___Bit No.

Post Byte --J


I I '_.-'
I l 1 1 1 J

Offset 1 •

t

Offset 2
Addressing Mode Field

Indirect Field
(Sign bit when bit 7 = 0)

Register Field

Figure 3-1. 6809 Post Byte for Indexed and Indirect Addressing

Table 3-4. 6809 Post Byte Bit Assignments for Indexed and Indirect Addressing

Bit Number
Addressing Mode
7 6 5 4 3 2 1 0

0 R R X X X X X 5-Bit Offset
1 R R 0 0 0 0 0 Autoincrement by One
1 R R I 0 0 0 1 Autoincrement by Two
1 R R 0 0 0 1 0 Autodecrement by One
1 R R I 0 0 1 1 Auto Decrement by Two
1 R R I 0 1 0 0 Zero Offset
1 R R I 0 1 0 1 Accumulator B Offset
1 R R I 0 1 1 0 Accumulator A Offset
1 R R I 1 0 0 0 8-Bit Offset
1 R R I 1 0 0 1 16-B it Offset
1 R R I 1 0 1 1 Accumulator D Offset
1 X X I 1 1 0 0 Program Counter 8-Bit Offset
1 X X I 1 1 0 1 Program Counter 16-Bit Offset
1 X X 1 1 1 1 1 Extended Indirect

� "'- r"'
I "v"'

t
t Addressing M ode Field

Indirect Field I= 1 for indirect. I = 0 for


direct (Sign bit when bit 7= 0)

Register Field
00 R=X
01 R=Y
10 R=U
11 R = S
6809 Machine Structure and Assembly Language 3-19

NOTATION FOR INDEXED ADDRESSING MODES

The standard 6809 assembier uses the following special notation in referring to
indexed addressing modes:

,R means that the 16-bit register R (X, Y, U,S, or PC) is to be used as the
base register.

OFFSET,R means that the number OFFSET is to be added to the contents


of base register R. A zero offset can be omitted unless the base register is the
program counter.

LABEL,PCR means that the program counter is to be used as the base


register and the offset is to be the distance from the location of the instruction
to the address LABEL. That is, the address LABEL is specified "program
counter relative."

,R + means that the 16-bit base register R (X, Y, U, or S) is to be incre­


mented (once for one plus sign, twice for two plus signs) after its contents are
used in determining the effective address.

, - R means that the 16-bit base register R (X, Y, U, orS) is to be decre­


mented (once for one minus sign, twice for two minus signs) before its con­
tents are used in determining the effective address.

Square brackets - I 1- around an indexed address indicate that it is to be


used indirectly.

CONSTANT OFFSET FROM BASE REGISTER

In this mode, the effective address is the sum of a fixed offset and the contents
of a base register. The base register can be any of the following: Index Register X,
Index Register Y, Stack Pointer U, Stack PointerS, or the program counter. Since
the purpose of the method is different when the base register is the program counter, we
will discuss that option separately. The procedure for obtaining the effective address,
however, is always as shown in this diagram:

Memory
Base Register

� �{
Operation Code mmmm

r-- rr -f mmmm + 1
--

ss mmmm + 2

t
Effective Address = ppqq + rrss

The offset follows the operation code, which includes the post byte, in program
memory. It is a constant since program memory generally does not change during
program execution. The contents of the base register may vary; the program can deter­
mine the values in the index registers and stack pointers, whereas the program counter
contents depend on the placement of the program.
3-20 6809 Assembly Language Programming

When used with an index register or stack pointer, this addressing mode allows
us to refer to a particular element in an array or list. For example, we may have a set
of ten temperature readings taken at different points in a tank; to change or display a
particular one, we must know where the set of readings starts (base address) and which
reading we want (index or offset). If, as is usual, we store the readings in successive
memory locations, we can find one by using a constant offset from the base.
Similarly, we may store a record in memory consisting of a person's name,
address, identification number, age, and job classification. If we want to send notices of
change of wage rate to all people in a particular job classification, we can find the job
classification by specifying how far it is from the start of the record (for example, 97
bytes further). This is much like telling all the students who are taking an examination
to put their names on the top line, their class levels on the fifth line, and their dates of
birth on the tenth line. Each student locates the required lines relative to the top of his
or her form. So, in our records, the name might occupy the first 16 bytes, the address
the next 70, the identification number the next 9, and the age the next 2. We can locate
a particular field in a particular record (for example, employee ::jj: 4's identification
number) by specifying the base address On this case, where employee #4's record
starts) and how far beyond that we must go for the desired field (in our example, 86
bytes to the identification number).

Short Constant Offset Modes

Although we have described situations in which the offset could be large, offsets
are usually small. We are more likely to want something that is a few locations away than
something that is thousands of locations away. So the 6809 microprocessor provides
special short modes to handle the cases where:

1. The offset is zero. We want to use the base register as an implied memory
address, as described extensively in An Introduction to Microcomputers:
Volume 1.
2. The offset is small enough to fit in the post byte. Since we need one bit to
indicate whether this case holds, and two bits to designate which index
register or stack pointer is the base register, the offset must fit in five bits. The
6809 microprocessor interprets these five bits (the least significant bits of the
post byte) as a sign (bit 4) and a 4-bit twos complement number (bits 0
through 3). Thus the range is -1610 (100002) <offset::;;+ 1510 (011112).

The advantages of these short modes are obvious: they save time and memory,
since no additional bytes are needed for the offset. Furthermore, if the offset is zero, the
processor does not have to go through the motions of adding it to the base.
6809 Machine Structure and Assembly Language 3-21

Zero Offset (No Offset)

As an example of the zero offset mode, the assembler converts the statement
ADDA , X

into an ADD instruction that adds the contents of the address in Index Register X to
Accumulator A. The following diagram illustrates the execution of the instruction.
Data
Memory

E F H N z v c
CCR I I I I I [I I
X
x x x x
yy ppqq

)( pp
Program
y Memory

PC mm mm AB mmmm

DP 84 mmmm + 1

mmmm + 2

Indexed Addressing mmmm + 3


ADDA .X
Zero Offset

The effective address here is simply the contents of Index RegisterX. If, for example,
Accumulator A contains B716, Index Register X contains 01El16, and memory address
01E116 contains 1516, then after the processor executes ADDA ,X Accumulator A will
contain B716 + ((X)) 8716 + (01El16)
= B716 + 1516 CC16. The processor incre­
= =

ments its program counter twice, once after fetching the operation code and once after
fetching the post byte.

Five-Bit Offset

As an example of the short offset mode, the assembler converts the statement
ADDA -1, Y

into an ADD instruction that adds the contents of the address one less than that
specified by Index Register Y to Accumulator A. That is, the effective address is the
contents of Index Register Y minus 1. The following diagram illustrates the execution of
the instruction.
3-22 6809 Assembly Language Programming

Data
Memory

E F H I N z v c

CCR
I I I I I xI xI x j·x I
X
- yy ppqq -1

o{: XX
Jl//lf'" XX + yy

(
X
Program
y pp qq + Memory

l
u

PC + 2 AB
mm mm
-
-I mmmm mmmm

DP _,,.__ 3F mmmm + 1

mmmm + 2

+ 3
Indexed Addressing
mmmm

ADDA -l.Y
Short Offset

As a specific example, assume that Accumulator A contains 9416, Index Register


Y contains A0 4816, and memory address A0 4716 contains 3216• After the processor
executes the instruction ADDA -l,Y , Accumulator A will contain 9416 + ((Y)- l) =

9416 + (A04816- l) 9410 + (A04716)


= 9416 + 321 6 C616. = =

This mode takes longer for the processor to execute than the zero offset does
because of the address addition. That is, the processor must add the offset (-1 in this
case) to the contents of the base register (Index Register Y). What if the offset is zero?
The processor adds it in anyway, thus wasting some time. In 6809 assembler notation
the difference is between
ADDA ,X

which tells the processor to use the zero offset mode, and
ADDA 0, X

which tells the processor to use the 5-bit offset mode with a value of zero. Obviously,
you should always use the first notation instead of the second because the first executes
faster: Both are legal, but the second has no advantage. Motorola's 6809 assemblers
automatically optimize to the zero offset mode; thus, a Motorola assembler would
produce the same object code - AB 84- for both ADDA ,X and ADDA O,X. Not all
6809 assemblers have this desirable feature, however; you will save yourself poten­
tial trouble by using the special zero offset notation exclusively.

larger Constant Offset Modes

If the offset is not zero or small enough to fit in the post byte, one or two extra
bytes of program memory beyond the post byte must be used to hold it. An 8-bit mode
and a 16-bit mode allow offsets of any length: Of course, the frequency of use goes
down as the length of the offset increases. Furthermore, the longer the offset, the
6809 Machine Structure and Assembly Language 3-23

more extra time and memory the instruction requires (see Appendix B). So we use the
longer modes as seldom as possible.
As an example of the 8-bit offset mode, the assembler converts the statement
ADDA $20,U

into an ADD instruction that adds the contents of the address 2016 beyond the address
in Stack Pointer U to Accumulator A. The 8-bit offset (2016) is located immediately after
the post byte in program memory. The following diagram illustrates the execution of the
instruction.
Data
Memory

E F H N z v c

CCR I I I lxlxlxlxl
X

,yy ppqq + 20

XX

o{:
X
Program
y Memory

u pp qq +

mm mm AB mmmm
PC

DP CB mmmm + 1

20 mmmm + 2

mmmm + 3
Indexed Addressing
ADDA $20,U
One-byte Offset

The effective address here is the contents of Stack Pointer U plus 2016. The processor
interprets bit 7 of the offset as a sign and the remaining seven bits as a twos complement
number. Thus the range of the offset is -128 1000 00002 < offset < + 127
=
=

Olll 11112. As a specific example, assume that Accumulator A contains 4D1 6, Stack
Pointer U contains 054E16, and memory address 056E16 contains 2A16• After the pro­
cessor executes ADDA $20,U Accumulator A will contain 4D16 + ((U) + 2016) =

4D16 + (0 54E16 + 20 16) 4D16 + (056 E16)


= 4D16 + 2A16 =
7716. =

The extension of this mode to a 16-bit offset occupying two bytes is obvious; we
will not discuss it further.

Constant Offset from the Program Counter

The modes that use a constant offset from the program counter help us write
position-independent code: that is, programs that work regardless of where they are
placed in memory. Such programs can be moved, without changes, to any available
memory locations and used with any combination of other programs. The easiest way to
make a program position-independent is for it to specify any addresses it uses relative to
its own position. How does a program know its own position? By looking at the contents
of the program counter. The idea here is the same as a repair manual that first orients
3-24 6809 Assembly Language Programming

the user properly (for example, by telling the person to face the equipment as shown in a
particular picture) and then refers to things as being "in back," "in the top left-hand
corner," or "fourth from the left in the bottom row." These descriptions are all relative
to the user's position.
We can move an entire program along with its data if we refer to addresses relative
to the program counter. The idea here is to refer to data as being "20 locations from
where we are," rather than at a particular address. If we then move everything, the rela­
tive positions of instructions and data remain the same, even though their absolute
addresses change. This is like telling someone that the dining car on a train is two cars
ahead; the relative positions of the cars remain the same, even though the entire train is
moving.
The 6809 microprocessor allows either an 8-bit or a 16-bit offset from the pro­
gram counter. No special zero or 5-bit modes are provided, as with the index registers
and stack pointers. In fact, offsets from the program counter are likely to be large,
since data areas are usually separated from program areas. In the 8-bit offset, bit 7 is
the sign and bits 0 through 6 are a twos complement number. As an example of this
mode, let us discuss the execution of the instruction
ADDA $10,PC

which adds the contents of the address 1316 beyond the initial value of the program
counter to Accumulator A. Why is the offset 1316, not 1016? The reason is that the pro­
cessor fetches the entire 3-byte instruction (operation code, post byte, and 8-bit offset)
before calculating the effective address. Thus it has already added 3 to the program
counter by the time it uses that register for addressing. In the 16-bit offset mode, the
extra factor is 4 since the instruction occupies four bytes (operation code, post byte, and
16-bit offset). The following diagram illustrates the execution of the instruction ADDA
$10,PC.

E F H N Z V C Memory

cc R _I """"'-�l- _x_l--'-l_x "- I ....�x �...


1 _x ..._ l _,x. l AB mmmm

SC mmmm + 1

10 mmmm + 2
XX
o{: mmmm + 3

PC mm mm

DP
Indexed Addressing
ADDA $10,PC
One-byte offset from Program Counter

The effective address here is the final contents of the program counter plus 1016. As a
specific example, assume that Accumulator A contains CA 16, the program counter con­
tains 78 0916, and memory address 7 81C16 contains 0516• After the processor executes
ADDA $10,PC Accumulator A will contain CA16 + ((PC) + 3 + 1016) =

CA16 + (780916 + 3 + 1016) =


CA16 + (781C16) = CA16 + 0516 = CF16• The diagram
6809 Machine Structure and Assembly Language 3-25

and this example show clearly that the result does not depend on where the instruction
is located in program memory, as long as the instruction and the data are moved as a
unit. Here again, the extension to a 16-bit offset is obvious and we will not discuss it
further.

Program Counter Relative (PCR) Notation

The extra three or four bytes involved in calculating an offset from the program
counter are a nuisance, particularly if the offset is negative. Furthermore, if the opera­
tion code is two bytes long, the numbers become four or five since the instructions then
occupy an extra byte of program memory. We would like to have the assembler handle
this for us, since the procedure is simple to explain but difficult to perform correctly.
The standard 6809 assembler will calculate the program counter offset for you if you
designate the address as "program counter relative," or PCR. For example, if you
write
ADDA LOCUS,PCH

the assembler will figure out the distance from the instruction to address LOCUS
(including the proper factor of three or four) and make that distance into an 8-bit or 16-
bit offset. This is the standard approach to writing position-independent 6809 code
efficiently.

INDIRECT WITH CONSTANT OFFSET FROM BASE REGISTER

We can add indirection to the constant-offset modes. The only change is that
there is no special 5-bit mode with indirection - because the 5-bit offset occupies the
bit used to differentiate between non-indirect and indirect modes - so we must use the
8-bit mode instead. The process of determining the effective address becomes complex
here, since it involves an addition followed by two memory accesses. We can illustrate it
as follows:
Memory

Operation Code mmmm

.---- {1----rr----1 mmmm + 1

ss mmmm + 2
+ �

tt

uu

The indirection allows us to handle items in arrays, lists, or records which are
addresses rather than data. For example, a microcomputer might be monitoring data
from several remote stations. To each station, we assign a block of memory locations
that contain:

l. Station number
2. Interval between readings
3-26 6809 Assembly Language Programming

3. Address in which next reading will be stored

4. Minimum valid reading

5. Maximum valid reading


6. Starting address of routine that handles invalid readings
7. Number of readings taken since last report
8. Number of readings per report

9. Address of output device on which report is printed


l 0. Starting address of routine that processes readings for a report

Some items in the block are data, whereas others (#3, #6, #9, and #10) are
addresses. The use of this block allows the operator to change any of the parameters
without affecting the overall program. The operator can vary the time interval between
readings (item #2), the data area used for temporary storage (item #3), the procedure
for handling invalid readings (item #6), or the output device on which the occasional re­
ports are printed (item #9). We can handle the data with non-indirect indexed address­
ing, whereas we must handle the addresses with indirect indexed addressing. For exam­
ple, if the next reading is in Accumulator A and the address in which that reading is to
be stored (item #3) occupies bytes 4 and 5 of the block, we can store the reading with
the sequence
LDX #BLOCK GET STARTING ADDRESS OF BLOCK
STA [4,X] STORE READING IN MEMORY

If later we want to take that reading (its address is item #3) and send it to the output
device (its address is item #9), we can use the sequence
LOX #BLOCK GET STARTING ADDRESS OF BLOCK
LDA [ 4 X]
I GET MOST RECENT READING
STA [OUT,X] REPORT MOST RECENT READING

Here OUT is the offset for item #9, the address of the output device.
As an example of the indirect indexed mode with constant offset, let us examine
the execution of the instruction
ADDA [5,X]

which adds to Accumulator A the contents of the address stored five bytes beyond the
address in Index Register X. That is, Index Register X is the base; the instruction adds 5
(the offset) to the base and uses the sum as an indirect address. This mode obviously
requires extra execution time (see Appendix B) because of the addition and the subse­
quent memory accesses. The following diagram illustrates the execution of the instruc­
tion.
6809 Machine Structure and Assembly Language 3-27

Data
Memory

yy rrss

E H N z v c

CCR I I I I I I I I
X
X
X X
X
rr ppqq + 5

o{:
{r ss ppqq + 6

X r-----------------�.. +

Program
y Memory

PC mm mm AB mmmm

DP 98 mmmm + 1

05 mmmm + 2

mmmm + 3
Indirect Indexed Addressing
ADDA [5.X]
Constant Offset from Index Register

As a specific example, let us assume that Accumulator A contains 1816, Index


Register X contains OC3316, memory address OC3816 contains A016, memory address
OC3916 contains 0216, and memory address AOD216 contains 4716• After the processor
executes the instruction ADDA [5,X], Accumulator A will contain
1816 + (((X)+5):((X)+6)) = 1 816 + (( O C 33 16+5) : ( 0 C 3316+6))
1816 +((OC3816):(0C3916)) = 1816 +(AOD211,) = 1816 + 4716 = 6216.
The other indirect modes with a constant offset are:

Zero offset from an index register or stack pointer


16-bit offset from an index register or stack pointer
8-bit offset from the program counter
16-bit offset from the program counter

The processor executes all these similarly to the 8-bit offset mode described ear­
lier. Note that there is no special zero offset mode using the program counter. We can
use the PCR (program counter relative) notation to simplify the specification of rela­
tive addresses as we discussed previously.
3-28 6809 Assembly Language Programming

ACCUMULATOR OFFSET FROM BASE REGISTER

This mode allows the offset, as well as the base register contents, to vary. The
offset may be in either accumulator or in the double accumulator; the base register
may be either index register or either stack pointer. Note, however, that the base
register cannot be the program counter. As shown in the following illustration, the
instruction does not contain any address at all.

Memory

Operation Code mmmm

Accumulator mmmm
+ 1

�+
,
Effective Address = ppqq + rr

A common use of this mode is to access lookup tables. Let us assume, for exam­
ple, that we have a lookup table in memory that converts 8-bit ASCII character codes to
8-bit EBCDIC character codes. The table consists of EBCDIC codes, organized accord­
ing to the ASCII codes to which they correspond. For instance, the Oth entry is the
EBCDIC code corresponding to the ASCII code 0, the 15th entry is the EBCDIC code
corresponding to the ASCII code 15 (OF16), and the 43rd entry is the EBCDIC code cor­
responding to the ASCII code 43 (2B16). To convert an ASCII code to EBCDIC, we
need to know where the table starts (let's call it address EBCDIC) and the value of the
ASCII code (let's assume it is stored temporarily in address CHAR). Then we can use
the accumulator offset mode to fetch the EBCDIC code from the table. A typical pro­
gram is:
LOX #EBCDIC GET BASE ADDRESS OF EBCDIC CODE TABLE
LOB CHAR GET ASCII CODE (ELEMENT NUMBER)
LOA B,X GET CORRESPONDING EBCDIC CODE FROM TABLE

For more details on character codes, see Chapter 6 of this book and Chapter 3 of
Volume 1 of An Introduction to Microcomputers. For further discussions of lookup tables,
see Chapters 4, 7, and 8 of this book.
Note the difference between this mode and the constant offset modes. In this
mode, the offset is a variable. In the example, the ASCII code could have any value;
typically the microprocessor would be receiving a string of ASCII data from an input
device and converting it into a string of EBCDIC data for an output device. In the cons­
tant offset modes, the offset does not change. In our example of an employee record, a
person's identification number or job classification is always located a specific number of
bytes from the start of the record.
As an example of the accumulator offset mode, let us consider the instruction
LDJ\ B,X

which loads Accumulator A from the address obtained by adding Accumulator B and
Index Register X. The mode using Accumulator A for the offset clearly works the same
way; the double accumulator offset mode is similar except for the offset's length. Note,
however, that the processor interprets the contents of a single accumulator as an 8-bit
6809 Machine Structure and Assembly Language 3-29

signed twos complement number. Thus the accumulator offset mode has a slightly
different effect than the ABX instruction, which interprets the contents of
Accumulator Bas an 8-bit unsigned number. Accumulator offset addressing requires
extra time because the processor must add the offset and the base; it does not require
any extra memory since the offset is in an accumulator or double accumulator. The
double accumulator version is necessary when the table occupies more than 256 bytes.
The following diagram illustrates the execution of the LOA B,X instruction.
Data
Memory

E F H N z v c

CCR I X X
I I I I 0
yy
pp
qq
XX
+

D {: t--
----

yy -;_ _ __ __...._

X
pp Program
y qq
Memory

s
�-----+-----�

PC mm mm A6 mmmrn

DP 85 mmmm + 1

m;nmm + 2

Indexed Addressing mmmm + 3


LDA B.X
Accumulator Offset

As a specific example, let us assume Accumulator B contains 2B16 (the ASCII


code for + ), Index Register X contains C30016 (starting address of an ASCII-to­
EBCDIC conversion table), and memory address C32B16 contains 4E16 (the EBCDIC
code for +).Then after the processor executes LOA B,X Accumulator A will contain
((X)+ (B)) = (C30016 +2B16) = (C32B16) = 4E16• We have converted an ASCII code
in Accumulator B into the corresponding EBCDIC code in Accumulator A. If you wish
to test this approach on other characters, use the character code tables in Appendix A of
An Introduction to Microcomputers: Volume 1.

INDIRECT WITH ACCUMULATOR OFFSET FROM BASE


REGISTER

We can add indirection to the accumulator offset mode to handle the case in
which the table contains addresses rather than data. For example, the table might
'
contain the actual addresses corresponding to numbered input and output devices.
The operator of the microcomputer-based system will ask the system to "read data
from device *4" or "print results on device =#=6." The microcomputer will use the
table to determine which addresses correspond to devices 4 and 6. This approach (see
Chapter 12 for further discussion) allows the operator to change 1/0 devices by
3-30 6809 Assembly Language Programming

changing the table. For example, the operator could let device :t1=6 be a CRT display for
a test run (thus showing test results without wasting paper), a printer for a run with local
output (thus providing a permanent record), and a modem for a run that must be re­
ported to central headquarters (thus sending the data over a communications link).
The procedure for reading data from a numbered input device is:

1. Load the starting address of the device table into an index register or stack
pointer.
2. Load the device number (a variable) into an accumulator.
3. Read the data from the address obtained from the device table using indirect
addressing with accumulator offset.

For example, if the starting address is IOTBL and the device number (assumed to
be even) is in memory address IODEV, a typical program is:

LOX #IOTBL GET BASE ADDRESS OF DEVICE TABLE


LOB IODEV GET I/0 DEVICE NUMBER
LOA [B,Xl GET DATA FROM J/0 DEVICE VIA TABLE

Remember, the elements in the table are 2-byte addresses and we want to transfer
data to or from those addresses, not to or from the table itself. The entries in the table
tell us where to send data or obtain data, not the value of the data as in the code con­
version example shown in the non-indirect case. Here again, the offset is a variable,
since the same program must be able to convert various device numbers into actual 1/0
addresses.
As an example of the indirect accumulator offset mode, we will discuss the
instruction
LOA [ B, X)

which loads Accumulator A from the address starting at the address obtained by adding
Accumulator Band Index Register X. The next diagram illustrates the execution of the
instruction. The Accumulator A and double accumulator offsets are handled similarly,
so we will not describe them in detail. The double accumulator offset is used for tables
that exceed 256 bytes in length, a relatively infrequent situation. Clearly this mode
takes extra time (see Appendix 8) because of the indirection. The processor must
calculate where the indirect address is and fetch the indirect address from memory
before it can actually execute the instruction. As with the non-indirect version, no
additional program memory is necessary since the offset is in an accumulator or double
accumulator.
6809 Machine Structure and Assembly Language 3-31

Data
Memory

xx rrss

E F H N z v c

CCR I I I I I
X X
0
rr pp qq + yy

ss ppqq + yy + 1

o{: yy

X pp qq
Program
y Memory

PC mm mm A6 mmmm

DP 95 mmmm + 1

mmmm + 2

mmmm + 3
Indirect Indexed Addressing
LDA [B.X]
Accumulator Offset

As a specific example, let us assume that Index Register X contains 03C616 (the
starting address of the l/0 device table), Accumulator B contains 04 (device #4), and
memory addresses 03CA16 and 03CB16 (which hold the address corresponding to device
#4) contain 8016 and 1216 respectively. Let us further assume that the data currently at
address 801216 (the input device port) is 4316 (an ASCII C). Then after the processor
exe c u t e s the instruction LOA [B,X] Accumulator A will contain
(((X) + (B)):((X) + (B) + 1)) = ((03C616 + 0416):(03C616 + 051(,)) =

((03CA16):(03CB16)) = (801216) = 4316 (ASCII C, the data from the input port). The
idea here is to use the table to determine where to find the data. The end result is that
Accumulator A contains the data read from input device #4, which is accessed through
memory address 801216, the corresponding entry in the device table.

AUTOINCREMENT AND AUTODECREMENT

In processing arrays, strings, or lists, we frequently want to process one byte


and then proceed to the next byte which is located at the next higher address (if we
are moving forward) or at the next lower address (if we are moving backwards). For
example, if we are printing a string of characters (a message such as WATCH OUT -
BOILER #6 IS REACHING CRITICAL TEMPERATURE), we must send the charac­
ters one by one to the printer (that is, first W, then A, then T, etc.). Similarly, if we are
3-32 6809 Assembly Language Programming

averaging a set of ten readings, we must add them together one by one (for instance,
start with zero, add the first reading, add the second reading, add the third reading, etc.)
and finally divide by 10.
Thus to handle one byte and move forward, we must:

Reach the byte using the address in an index register or stack pointer.
Add 1 to the index register or stack pointer to make it point to the next byte.

The effect is like the action of a typewriter, which both prints the character for the key
you press and moves the carriage along to the next position. Subtracting 1 from the
index register or stack pointer would correspond to backspacing the typewriter's car­
riage. Unlike the typewriter, the computer does not prefer forward over backwards.
Autoincrementing and autodecrementing are the modes most like the indexed address­
ing described in Volume 1 of An Introduction to Microcomputers.

Variations of Autoincrement and Autodecrement

The 6809 offers different step sizes for autoincrementing and autodecrement-
ing. The base address may be:

Incremented by 1 after it is used.

Incremented by 2 after it is used.

Decremented by 1 before it is used.

Decremented by 2 before it is used.

The increment or decrement by 2 approach is useful when the array consists of 16-bit
data or addresses. The processor thus moves on to the next element automatically,
even though that element is located two bytes away from the current element. Applying
the increment after using the base but applying the decrement before using the base
maintains compatibility with the automatic use of the stack pointers (in JSR, PSH,
PUL, RTI, RTS, and SWI instructions and in interrupt responses). Any access/change­
pointer sequence could be implemented, but this is the most popular approach. All the
user must remember is to load the base register with the starting address of the array or
string for autoincrementing, but with the ending address plus 1 or 2 for autodecrement­
ing (because the first autodecrement will reduce the base register before using it).
This form of indexed addressing is really a variety of implied memory addressing,
since no offset is involved. Instructions using this mode take extra time (see Appendix
B), since the processor must update the pointer register as well as execute the instruc­
tion. Autoincrementing or autodecrementing is the simplest way to process arrays or
strings since it provides automatic updating of the implied memory address (or data
pointer) as part of instruction execution. See Chapters 5 and 6 for further discussion of
autoincrementing and autodecrementing.

Autoincrement with a Step of One

As one example, consider the instruction


ADDll ,X+

This instruction adds to Accumulator A the contents of the address in Index Register X.
It also adds 1 to Index Register X, thus updating that address for the next operation in a
summation or averaging program. The following diagram shows how the processor
executes the instruction.
6809 Machine Structure and Assembly Language 3-33

Data
Memory

E F H N Z V
C
CCR _I ......
...._ _
l ._ x ....l -'
.. �.... j _x.._ ....l __.
x l_x. .. .. x I
yy ppqq

ppqq + 1

0 {: t-
--_
xx __ -f

X PP qq
Program
y Memory

AB mmmm

80 mmmm + 1

mmmm + 2

Indexed Addressing mmmm + 3


ADDA .X+
Autoincrement by One

As a specific example, assume that Accumulator A contains 0316, Index Register


X contains 07E416, and memory location 07E416 contains 0516. Then, after the processor
executes ADDA ,X+ Accumulator A will contain 0316 + ((X)) 0316 + (07E416) = =

0316 + 0516 0816• Furthermore, Index Register X will contain 07E416 + 1


= 07E516. =

Thus the instruction both adds an element to Accumulator A and updates Index
Register X so it points to the next element.

Autodecrement with a Step of Two

As an example of both autodecrementing and a step of2, let us show how the pro­
cessor executes the instruction
ADDD ,--Y

This instruction adds to the double accumulator the contents of the address obtained by
subtracting 2 from Index Register Y. It also places the result of the subtraction back in
Index Register Y. Here the elements are 16 bits long, so a subtraction of 2 is necessary
to reach the next element in the array. The step of 2 takes a little extra time (see Appen­
dix B). The processor, of course, has no preference between autoincrementing and
autodecrementing, since it lacks human or cultural preferences such as positive over
negative, forward over backwards, left-to-right over right-to-left, or top-to-bottom over
bottom-to-top. The following diagram illustrates the execution of the instruction.
3-34 6809 Assembly Language Programming

Data
Memory

E F H N Z V C

l_�.....__,_....
l__ ._ x...,
_l x ..�.._ x· I
I x.._I __,
{
ccR ww ppqq- 2

zz ppqq - 1

ppqq

X
Program
y pp qq Memory

PC mm mm E3 mmmm

DP A3 mmmm + 1

mmmm + 2

Indexed Addressing mmmm + 3


ADDD .--Y
Autodecrement by Two

As a specific example, let us assume that the double accumulator contains 10E816, Index
Register Y contains 042016, and memory locations 042B16 and 042C16 contain 0916 and
5C16 respectively. Then, after the processor executes ADDD,--Y the double
accumulator will contain 10E816 + ((Y)-2):((Y)- l ) = 10E816 + (042B16):(042C16)
= 10E816 + 095C16 = 1A4416• Furthermore, Index Register Y will contain 042D16- 2
= 042B16. Thus the instruction first updates Index Register Y and then adds the current
element to the double accumulator. The update by 2 is essential: decrement by 1 would
point Index Register Y to the least significant half of the current element.

INDIRECT WITH AUTOINCREMENT OR AUTODECREMENT

This addressing mode allows us to handle arrays of addresses. For example, we


have already described a table of 1/0 device addresses in which an entry is the actual
address corresponding to a particular 1/0 device number. That is, entry 2 is the address
corresponding to 110 device :#=2; by changing entry 2 ( for instance, from a port that con­
trols a machine to a port that is connected to a video display) , we can change 1/0 devices
and thus test the system, use the system as a remote terminal, or choose temporary or
hard-copy output without making any changes in the underlying program. Let us
assume that we want to fetch data from one device after another or test input devices
until we find one that has new data available. We can fetch data from the first input
device in a table INDEV with the sequence of instructions.

LOU ijiNDEV GET BASE ADDRESS OF INPUT DEVICE TABLE


LOA [ ,U++] GET DATA FROM DEVICE #0

After the processor executes these instructions, Accumulator A contains the data from
device :#=0 and Stack Pointer U points to the address corresponding to device #2. Thus
we can continue through the table of 110 devices, incrementing the pointer by 2 after
6809 Machine Structure and Assembly Language 3-35

fetching data from a particular device. Obviously, we could equally well start two beyond
the end of the table and use autodecrementing by 2 to move through the table back­
wards.
Since an address always occupies two bytes of memory, incrementing or decre­
menting by 1 makes no sense; it would result in the processor picking up half of one
address and half of another. This mode is therefore not aJiowed with indirection, and the
assembler will give you an error message if you try to use it. The only valid options are:

1. Increment the base register by 2 after using it.


2. Decrement the base register by 2 before using it.

As an example, let us show how the processor executes the instruction


LOA r,u++l

This instruction loads Accumulator A from the address starting at the address in Stack
Pointer U. It also adds 2 to Stack Pointer U. Here Stack Pointer U points to an address;
that is, it tells the processor where the address is, not where the data is. The following
diagram illustrates the execution of the instruction:
Data
Memory

xx r r ss

E F H N Z V C

ccR ._I
_.......
._ .,&.._
_... _
._ ....
x_x_...o l l l l
._ _..._
._
rr ppqq

ss ppqq + 1

ppqq + 2
o{:
X
Program
y Memory

u pp qq

PC mm mm A6 mmmm

DP 01 mmmm + 1

mmmm + 2

mmmm +3
Indirect Indexed Addressing
LDA [,U++]
Autoincrement Re gister U

As a specific example, assume that Stack Pointer U contains 27EE16, memory


address 27EE16 contains C016, memory address 27EF16 contains 0716, and memory
address C00716 (the actual 1/0 port) contains 8016. After the processor executes LDA
[,U + +] Accumulator A will contain ( ( (U)): ( (U) + 1)) = ( ( 27EE16) : ( 27EF16)) =

(C00716) = 8016• Furthermore, Stack Pointer U wiJI contain 27EE16 + 2 = 27F016• Thus
3-36 6809 Assembly Language Programming

the instruction loads Accumulator A from an indirect address obtained from the table
and updates Stack Pointer U so it points to the next indirect address. Of course, this pro­
cess of picking up an indirect address from the table, loading the data from that
address, and updating the pointer takes many extra clock cycles (see Appendix B).
Note, however, that no extra bytes of program memory are needed, since no offset is
involved.

PROGRAM RELATIVE ADDRESSING FOR BRANCHES

Branch, Branch-on-Condition, and Branch-to-Subroutine instructions use only


program relative addressing in which the address value is the offset from the current
value of the program counter. Thus branches are specified by "how far from where we
are," rather than by an actual destination address. This mode allows us to relocate an
entire program, since such a move does not change any relative addresses. Relative
branches are a key element in producing relocatable or position-independent code.
Furthermore, since most branches in programs are short, relative addressing allows
shorter addresses (usually eight bits), thus reducing memory usage.
The following illustration shows how the 6809 microprocessor executes relative
branch instructions. The value ppqq is the contents of the program counter after the
processor has fetched the entire branch instruction from memory. That instruction
includes an operation code (one or two bytes long) and an offset (one or two bytes
long).
Memory

}
Updated contents
of Program Counter = ppqq Operation Code 1
Operat ion Code: One or two bytes long
Operation Code 2

\�{ }
aa
offset (One or two bytes)
bb
+
Next
- Destination if branch is not taken
instruction

ppqq
l + �
aabb----
.. ....t-
. - Destination if branch is taken

The 6809 microprocessor has two forms of relative addressing: 8-bit offset and 16-bit
offset. In both forms, the value following the operation code specifies how many
memory locations to skip over from the end of the instruction. The offset is a twos com­
plement number, so the range for the 8-bit form is

- 1 28 ( =1000 00002 or 8016)�offset�+ 1 2 7 ( =0111 11112 or 7 F16)


6809 Machine Structure and Assembly Language 3-37

Since the short relative branches themselves occupy two bytes of program
memory, the range from the start of the instruction is

-126 < offset < + 129

We do not have to be concerned with this extra factor of 2 if we specify the actual
destination in the operand field. If, for example, we use the statement
BRA CHCNT

the assembler will figure how far away label CHCNT is (including the factor of 2) and
place that number in the offset. We will discuss calculating relative offsets in more detail
in Chapter 4.
As an example of how the processor executes relative branch instructions, con­
sider the instruction
BRA PLACE

where PLACE is a nearby address. If the program counter contains mmmm originally,
the offset is the 8-bit twos complement form of PLACE - (mmmm + 2) = PLACE -
mmmm - 2. The next diagram illustrates the execution of the instruction. The 16-bit
offset form is similar, except that the offset occupies two bytes and the instructions
therefore occupy either three bytes (LBRA and LBSR) or four bytes (all long condi­
tional branches). The extra factor in the address calculation is then either 3 or 4, making
hand calculations even more awkward. As we mentioned above, the assembler will
perform the calculation for you if you specify the destination address as a label; you
will seldom need to calculate offsets by hand. The 16-bit offset provides access to any
location in memory, but is not commonly needed since few branches are long enough to
require its use. Another approach to providing relative addressing with branches is to
use the Jump or Jump-to-Subroutine instructions with the indexed addressing mode
that involves an offset from the program counter. The non-indirect versions of these
instructions, however, take more time and memory than ordinary relative branches
and so are not used.

E F H N Z V C

Program

o{: Memory

X 20 mmmm

/
y Offset mmmm + 1

u mmmm+ 2

s
I
mmmm+ : I
PC mm mm
� -:I + offset

DP mmmm + 2
PLACE
+ offset

Program Relative Addressing


BRA PLACE
Short Branch (Unconditional)
3-38 6809 Assembly Language Programming

As a specific example, assume that mmmm = CSA116 and PLACE = C5BE16•


The offset is C5BE16- C5A116- 2 = 1 016 - 2 = 1B16. After the processor executes
the instruction BRA PLACE, the contents of the program counter will be (initial PC) +
2 + offset = CSA 116 + 2 + 1 B16 = C5A316 + lB16 = C5BE16 = PLACE. Note that if
we move the entire program forward or backwards by a distance REL, the new offset is
(C5BE16 + REL) - (CSA116 + REL) - 2 = C5BE16 - CSA116 - 2, the same as
before since the RELs cancel out.

6809 INSTRUCTION SET

Table 3-5 lists the 6809's instruction mnemonics, differentiating between those
that are also 6800 mnemonics and those that are new or have been modified. We will
discuss compatibility between the 6809 microprocessor and the 6800 microprocessor, as
well as compatibility between the 6809 and the 6801 microprocessors, in the next part of
this chapter. For a detailed description of the 6809 instruction set, see the last section
of this book. In Chapter 22, we discuss each instruction's operation; refer to that
chapter when you need to understand how a particular instruction works. Appendix A
summarizes the available 6809 instructions, grouping them by function. This provides a
survey of the 6809's capabilities, and will also be useful when you need a certain kind of
operation but are either unsure of the specific mnemonic or not yet familiar with what
instructions are available. The rest of the appendices serve as reference tables for
calculating program execution time and memory requirements, and for hand assembly
and disassembly; Appendix C also displays available addressing modes for each instruc­
tion.
Instructions often frighten microcomputer users who are new to programming.
Yet taken in isolation, the operations involved in the execution of a single instruction
are usually easy to follow. The purpose of the last section of this book is to isolate and
explain those operations. Furthermore, you need not attempt to understand all the
instructions at once. As you study each of the programs in this book you will learn
about the specific instructions involved.
Why are a microprocessor's instructions referred to as an instruction "set?"
Because the microprocessor designer selects the instruction complement with great
care; it must be easy to execute complex operations as a sequence of simple events, each
of which is represented by one instruction from a well-designed instruction "set."

6800/6809 COMPATIBILITY

The 6809 microprocessor is an advanced version of the 6800 microprocessor,


produced by the same manufacturers. All assembly language programs written for
the 6800 microprocessor can also be assembled for the 6809 microprocessor. In fact,
object code produced for the 6800 microprocessor is very similar to that produced for
the 6809 microprocessor; in many cases, the processors have direct object code com­
patibility. The external support devices designed for use with the 6800 microprocessor
can all be used with the 6809 as well. Chapter 9 of An Introduction to Microcomputers:
Volume 2 discusses the hardware compatibility in more detail.
6809 Machine Structure and Assembly Language 3-39

Table 3-5. 6809 Operation Code Mnemonics

Source Source Source Source


Instruction Instruction Instruction Instruction
Forms Forms Forms Forms

ABX BLS BLS DEC DECA OR ORA


ADC ADCA LBLS DECB ORB
ADCB BLT BLT DEC ORCC
ADD ADDA LBLT EOR EORA PSH PSHS11
ADDB BMI BMI EORB PSHU
AOOD LBMI EXG R1 R22 PUL PULS12
AND ANDA BNE BNE INC INCA PULU
ANDB LBNE INCB ROL ROLA
ANOCC BPL BPL INC ROLB
ASL3 ASLA LBPL JMP ROL
ASLB BRA BRA JSR ROR6 RORA
ASL LBRA LD LDA10 RORB
ASR3. 6 ASRA BAN BAN LDB10 ROR
ASRB LBRN LDD RITB
ASR BSR BSR LOS RTS
BCC BCC LBSR LOU SBC3 SBCA
LBCC BVC BVC LOX SBCB
BCS BCS LBVC LOY SEX
LBCS BVS BVS LEA LEAS ST STA10
BEQ BEQ LBVS LEAU STB10
LBEQ CLR CLRA LEAX STO
BGE BGE CLRB LEAY STS
LBGE CLR LSL3 LSLA STU
BGT BGT CMP3 CMPA LSLS STX
LBGT CMPB LSL STY
BHI BHI CMPO LSR6 LSRA SUB3 SUBA
LBHI CMPS LSRB SUBB
BHS BHS CMPU LSR SUBD
LBHS CMPX7 MUL4 SWig SWI
BIT BITA CMPY NEG3 NEGA SWI2
BITB COM COMA NEGB SWI3
BLE BLE COMB NEG SYNC
LBLE COM NOP TFR.R1,Rl2
BLO BLO CWAI TST5 TSTA
LBLO DAA TSTB
TST

Notes:

1. Shading identifies additions or modifications to the 6800 instruction set. The unshaded instruc-
tions are also 6800 instructions with the same operation codes except as noted below.

2. R1 and R2 may be any pair of 8-bit or 16-bit registers. The 8-bit registers are A. B. CC, and DP.
The 16-bit registers are D. X. Y. U, S. and PC.

3. The Half-Carry flag H is undefined after these instructions are executed.

4. This MUL affects the Zero flag, whereas 6801 M UL does not.

5. This instruction does not affect the Carry flag. On the 6800/6801/6802 it clears the C flag.

6. These do not affect the Overflow flag (V). On the 6800/6801 /6802 they may.

7. This instruction correctly sets all flags. On the 6800/6802 it does not.

8. On the 6809, the Entire flag (E) is checked during RTI to determine how much to unstack - the
entire register complement or just the Condition Code Register and Return Address.

9. SWI sets the F and I flags; SWI2 and SW13 have no effect on F and I.

10. These instructions are implemented on the 6800 with slightly different mnemonics.

11. This instruction is implemented on the 6800 as PSH.

12. This instruction is implemented on 6800 as PUL.


3-40 6809 Assembly Language Programming

We will briefly describe and compare the 6809 and 6800 microprocessors with
regard to their registers, flags, addressing modes, and instruction sets. The processors
are similar, and the manufacturers clearly will encourage migration from the 6800 to the
6809. This description will help you see what problems you would encounter in going
from one CPU to the other.

REGISTERS

The 6800 register set is a subset of the 6809 register set. In addition to the 6800
registers - Condition Code, Accumulators A and B, Index Register X, and the Hard­
ware Stack Pointer - the 6809 has another index register (Y), another stack pointer
(User Stack Pointer or U register), and a direct page register. Also, the 6809 allows
references to the Double Accumulator D, which consists of Accumulator A and
Accumulator B, whereas the 6800 does not.

FLAGS

The 6800 and 6809 microprocessors have identical Sign, Zero, Overflow, Carry,
Half (or Auxiliary) Carry, and Interrupt Mask flags. The 6809 also has a Fast Inter­
rupt Mask flag (F) and an Entire flag (E) which are not implemented on the 6800,
since the 6800 has no Fast Interrupt Request input and always saves all of its registers in
response to an interrupt. Bit positions 6 and 7 in the 6800's condition code register
always contain ones.

ADDRESSING MODES

The 6809 microprocessor has many more addressing modes than does the 6800.
The only indexed addressing mode that is implemented on the 6800 is the non­
indirect mode with an 8-bit unsigned offset from Index Register X. All other indexed
and indirect addressing modes are unique to the 6809. You should note that 6809
indexed instructions all require an extra (or post) byte that determines the addressing
mode. Thus an indexed instruction that required two bytes of code on a 6800
microprocessor will generally require three bytes on a 6809 microprocessor. However,
indexed addressing on the 6800 is most often used with an offset that is either zero or
less than 16; instructions with such small offsets can be implemented on the 6809
microprocessor using the special forms for zero offset or 5-bit signed offset, thus making
them again two bytes in length. You should also note that indexed offsets are signed in
the 6809 microprocessor (allowing them to be either positive or negative), whereas they
are unsigned in the 6800 microprocessor.
The direct addressing mode on the 6809 microprocessor differs from the direct
mode on the 6800 because the 6809 has a Direct Page register which provides the high­
order byte of the address. The 6800 microprocessor always sets the high-order byte of
the address to zero. Thus 6800 and 6809 direct addressing are the same only when the
6809's Direct Page register contains zero. Compatibility is simplified by the fact that
hardware Reset clears the 6809 Direct Page register, so that it contains zero unless the
program explicitly changes it. Obviously, the 6809 direct mode is more powerful and
more general.
6809 Machine Structure and Assembly Language 3-41

INSTRUCTIONS

The 6800 instruction set is a subset of the 6809 instruction set. Many 6800 and
6809 instructions are identical (see Table 3-6). Some new 6809 instructions (see Table
3-7) are obvious additions to the 6800 set, required to handle the new 6809 registers.
Still other 6809 instructions are generalizations of 6800 instructions (see Table 3-8) or
entirely new (see Table 3-9).
Table 3-10 describes the implementation of 6800 instructions that no longer
exist on the 6809 microprocessor. Note that the 6809 assembler automatically trans­
lates these 6800 instructions i�to their 6809 equivalents. All these one-byte 6800
instructions require at least two bytes (and sometimes as many as four bytes) on the
6809. However, most of them are rarely used in 6800 programs. The only common 6800
instructions in Table 3-10 are PSH and PUL, which have been greatly generalized on the
6809 to handle its larger set of registers, and DEX and INX, which have become far less
important on the 6809 with the addition of autoincrementing and autodecrementing.

6800/6809 DIFFERENCES

You should note the following minor differences between the 6800 and 6809
instruction sets:

1. The 6809 regards Accumulators A and Bas a Double Accumulator D, with A


as the high-order half. It therefore stacks and unstacks the accumulators
with B stacked first and removed last; this is the opposite order from that
implemented on the 6800 microprocessor.
2. The 6809's hardware stack pointer contains the address of the last memory
location occupied by the stack, not the address of the next empty location as
in the 6800. Thus 6809 instructions that use the hardware stack pointer
always decrement it before storing data and increment it after loading data.
6800 instructions that use the stack pointer always decrement it after storing
data and increment it before loading data. Thus the hardware stack pointer on
the 6809 should be initialized to a value one larger than that used in a com­
parable 6800 program.
3. The 6800 instructions TSX <Transfer Stack Pointer to Index Register) and
TXS (Transfer Index Register to Stack Pointer) took account of the fact
that the 6800's stack pointer contained the address one beyond the end of the
stack. This accounting involved an addition of 1 during TSX and a subtrac­
tion of 1 during TXS, thus moving to or from the last occupied address. The
6809 microprocessor does not require this awkward adjustment and
therefore does not implement it in instructions.
4. The 6809 TST instruction does not affect the Carry flag, whereas the 6800
TST instruction clears that flag.
5. The 6809 right shifts (ASR, LSR, ROR) do not affect the Overflow flag,
whereas the 6800 right shifts do.
6. The 6809 Half-Carry flag is undefined after subtraction, comparison, and
related instructions (NEG), whereas the 6800 Half-Carry flag is cleared after
such instructions.
3-42 6809 Assembly Language Programming

Table 3-6. Identical 6800/6809 Instructions

6800 Mnemonic 6809 Mnemonic Notes

ADCA/ADCB ADCA/ADCB
ADDA/ADDB ADDA/ADDB
ANDA/ANDB ANDA/ANDB
ASL ASL (also LSL) 1
ASR ASR 1
BCC BCC (also BHS)
BCS BCS (also BLO)
BEG BEG
BGE BGE
BGT BGT
BHI BHI
BIT BIT
BLE BLE
BLS BLS
BLT BLT
BMI BMI
BNE BNE
BPL BPL
BRA BRA
BSR BSR
BVC BVC
BVS BVS
CLR CLR 1
CMPA/CMPB CMPA/CMPB
COM COM 1
CPX CMPX 3
DAA DAA
DEC DEC 1
EOR EOR
INC INC 1
JMP JMP 1
JSR JSR
LOAA/LDAB LOA/LOB
LOS LOS 2
LOX LOX 2
LSR LSR 1, 3
NEG NEG 1
NOP NOP 2
ORAA/ORAB ORA/ORB
PSH PSHS 2. 4
PUL PULS 2, 4
ROL ROL 1
ROR ROR 1. 3
RTI RTI
RTS RTS
SBC SBC
STAA/STAB STA/STAB
STS STS 2
STX STX 2
SUBA/SUBB SUBA/SUBB
SWI SWI
TST TST 1. 3

Note the minor differences in some of the mnemonics - namely, an extra A in LOAA, LDAB, ORAA.
ORAB. STAA. and STAB on the 6800, an extra S in PSHS and PULS on the 6809. and a slightly
d ifferent version of Compare Index Register X (CM PX on 6809, CPX on 6800).

Notes:
1. Direct addressing is available with this instruction on the 6809 only.
2. 6809 instruction has a different object code.
3. 6809 version has slightly different effects on flags.
4. 6809 Stack Pointer manipulation differs from that of the 6800. See the text for further information.
6809 Machine Structure and Assembly Language 3-43

7. The 6809 sets all flags properly after executing CMPX and similar instruc­
tions, whereas the 6800 sets only the Z flag properly after executing its CPX
instruction.

Clearly these differences will not affect most programs, unless they perform many
stack manipulations. There are slight differences in operations involving the Condition
Code register, since the 6800 always has ones in the two most significant bits of that
register, whereas the 6809 uses those bits for the Entire flag and the Fast Interrupt Mask
bit.

Table 3-7. 6809 Instruction Set Extensions to Handle Additional Registers

6809 Operation Comparable 6800 Operation

CMPY CPX
LDU LDS
LDY LDX
PSHU PSH
PULU PUL
STU STS
STY STX

Table 3-8. 6809 Generalizations of 6800 Instructions

6809 Operation Comparable 6800 Operations

ADDD ADDA. ADDB


ANDCC CLC. Cll. CLV
CMPD CMPA. CMPB
CMPS CPX
CMPU CPX
CWAI WAI
EXG TAB. TAP. TBA. TPA. TSX. TXS
LBCC (also LBHS, BCC
LBCS (also LBLO) BCS
LBEQ BEQ
LBGE BGE
LBGT BGT
LBHI BHI
LBLE BLE
LBLS BLS
LBLT BLT
LBMI BMI
LBNE BNE
LBPL BPL
LBRA BRA
LBSR BSR
LBVC BVC
LBVS BVS
LDD LDAA. LDAB
ORCC SEC. SEI. SEV
STD STAA. STAB
SUBD SUBA. SUBS
SWI2 SWI
SWI3 SWI
TFR TAB. TAP. TBA. TPA. TSX. TXS
3-44 6809 Assembly Language Programming

Table 3-9. New 6809 Instructions (Without 6800 Equivalents)

Instruction Mnemonic

ABX (Also implemented on 6801 microprocessor)


BRN
LBRN
LEA
SEX
SYNC (but similar to 6800 WAI)

Table 3-10. 6809 Implementations of Missing 6800 Instructions

6800 Instruction 6809 Equivalent

ABA PSHS B; ADDA ,S+


CBA PSHS B; CMPA .S+
CLC ANDCC #% 11111110
CLI ANDCC "#% 11101111
CLV ANDCC "#%11111101
DES LEAS -1,S
DEX LEAX -1.X
INS LEAS 1,S
INX LEAX 1.X
PSHA PSHS A'
PSHB PSHS B'
PULA PULS A'
PULB PULS B'
SBA PSHS B; SUBA ,S+
SEC ORCC #%00000001
SEI ORCC "#%00010000
SEV ORCC #%00000010
TAB TFR A,B; TSTA
TAP TFR A.CC
TBA TFR B,A; TSTA
TPA TFR CC.A
TSX TFR S,X
TXS TFR X.S
WAI CWAI "#$FF or CWAI "#$EF to enable
regular interrupt (replaces CLI. WAll

• 6809 Stack Pointer manipulation differs from that of the 6800. See the text for further information.

6801/6809 COMPATIBILITY

The 6801 microprocessor is a slightly improved version of the 6800


microprocessor that is manufactured by some of the same companies. The 6801
instruction set is almost the same as the 6800's except that the 6801 has a multiplication
instruction and a ABX instruction (as on the 6809), as well as 16-bit shifts for the dou­
ble accumulator that are not implemented on either the 6800 or the 6809. The 6801, like
the 6809, does set the flags properly after CMPX (CPX). The only added difference is
that the 6801 multiply instruction (MUL) does not affect the Zero flag, whereas the
6809 MUL instruction does.
6809 Machine Structure and Assembly Language 3-45

6502/6809 COMPATIBILITY

The 6809 microprocessor is also similar to the 6502 and related


microprocessors, which are produced by a different group of manufacturers. For more
details on 6502 compatibility, see the discussions in Chapters 9 and lO of An Introduction
to Microcomputers: Volume 2 and in Chapter 3 of 6502 Assembly Language Programming.-'

MOTOROLA 6809 ASSEMBLER CONVENTIONS

The standard 6809 assembler is available from 6809 manufacturers and on many
major time-sharing networks; it is also included in most development systems. Cross­
assembler versions are available for most large computers and many minicomputers.

ASSEMBLER FIELD DELIMITERS

The assembly language instructions have the standard field structure (see
Table 2-1). The required delimiters are:

1. A space after a label. All labels must start in column 1 and all statements that
are not labeled must start with at least one space.
2. A space after the operation code. The accumulator, double accumulator, or
index register/stack pointer designation can be added to the operation code
without a space; for instance, ADDA for"Add to Accumulator A," STD for
"Store Double Accumulator," and PSHU for "Push Registers onto User
Stack."
3. A comma between operands in the address field - that is, between an offset
value or register and a base register (X, Y, U, S, or PC). For example, ADDA
$35,X means that an indexed instruction is to be generated with an offset of
3516 from the value in Index Register X. A zero offset can be omitted unless
the base register is the program counter.

4. A comma in front of the symbols for autoincrementing or autodecrement­


ing. For example, LOA ,X+ tells the assembler to generate an indexed LOA
instruction which autoincrements Index Register X by 1. Similarly, ADDB
, -- U tells the assembler to generate an indexed ADDB instruction which
autodecrements Stack Pointer U by 2. This comma is similar to the one be­
tween operands (item 3 above), although no offset is allowed with autoincre­
menting or autodecrementing.
5. Square brackets - I I - around addresses to be used indirectly.
6. A space before a comment that appears on the same line as an instruction,
and an asterisk before an entire line of comments.

Typical 6809 assembly language instructions are:

START LOA [lOOO,Xl GET LENGTH


LOX TEMPR
WAI
3-46 6809 Assembly Language Programming

LABELS

Most versions of the assembler allow only six characters in labels and truncate
longer labels. The first character must be a letter or the special character period (.).
The assembler reserves certain names to refer to CPU registers; these names are A,
B, CC, D, DP, PC, PCR (program counter relative), S, U, X, andY. The use of opera­
tion mnemonics as labels is often not allowed and is not good programming practice
anyway, because of the obvious confusion.

ASSEMBLER DIRECTIVES

The assembler has the following explicit pseudo-operations:

END End of Source Program


EQU Equate or Define Symbolic Name
FCB Form Constant Byte or Enter Byte-Length Data
FCC Form Constant Character String or Enter Character Data
FOB Form Double Byte Constant or Enter Word-Length Data
ORG Set (Location Counter to) Origin
RMB Reserve Memory Bytes or Allocate Storage
SETDP Set Direct Page Pseudo-Register

FCB, FCC, and FOB

FCB, FCC, and FDB are the data directives used to place constant data in pro­
gram memory -data such as tables, messages, and numerical factors- that is necess­
ary for the execution of the program but does not consist of instructions. FCB is used
for byte-length (8-bit) data, FCC for 7-bit ASCII characters (MSB of each byte is
zero), and FDB for word-length 06-bit) data or addresses. Note that FOB stores
word-length data in the standard 6800-6809 format with the high-order bits in the first
byte and the low-order bits in the following byte.

Examples:
ADDR FOB $31�5

places the numbers 3116 and 6516 in the next two bytes of program memory and assigns
the name ADDR to the address of the first byte� thus (ADDR) = 3116 and (ADDR +
1) =6516•
TCONV FCB 3/.

places the number 32 (2016) in the next byte of program memory and assigns the name
TCONV to the address of that byte.
ERROR FCC /ERROR/

places the 7-bit ASCII character representations of E, R, R, 0, and R (hexadecimal 45,


52, 52, 4F, and 52) in the next five bytes of program memory and assigns the name
ERROR to the address of the first byte.
Any single character (not just /) may be used to surround the ASCII text. An
alternative is to specify the number of characters in the operand field. For example:

E�ROR FCC �,ERROR


6809 Machine Structure and Assembly Language 3-47

We will always use the first form shown (with the I character) for consistency.
OPERS FDB FAOD, FSUB, FMUL, FDIV

places the addresses F ADD, FSUB, FMUL, and FDJV in the next eight bytes of
memory and assigns the name OPERS to the address of the first byte. All addresses (and
16-bit data items) are stored with their high-order bits first.

RMB

RMB is the Reserve directive used to assign locations in memory for specific pur­
poses; it allocates a specified number of bytes.

EQU

EQU is the Equate or Define directive used to define names.

ORG

ORG is the standard Origin directive. 6809 assembly language programs usually
have several origins, which are used for the following purposes:

1. To specify the Reset, interrupt service, and software interrupt addresses.


These addresses must be placed in the highest memory addresses in the
system (FFF216 through FFFF16).
2. To specify the starting addresses of the actual Reset, interrupt service, and
software interrupt routines. The routines themselves may be placed anywhere
in memory.
3. To specify the starting address of the main program.
4. To specify the starting address of subroutines.
5. To define areas of memory for data storage.
6. To define areas of memory for the Hardware and User Stacks.
7. To specify addresses used for 1/0 ports and special functions.

Examples:
RESET EQU S3ROO
ORG RESET

ORG SFFFE
FOB RESET

Note: $means 'hexadecimal'.

This sequence places the Reset (or startup) instruction sequence in memory beginning
at address 380016, and places that address in the memory locations (addresses FFFE16
and FFFF16) from which the 6809 CPU retrieves the Reset address.
MAIN EQU SCOOG
ORG MAIN

This sequence specifies that the instructions following it are to be placed in memory
beginning at address C00011,.
3-48 6809 Assembly Language Programming

END

END simply marks the end of the assembly language program.

SETDP

SETDP specifies which page of memory is to be treated as the direct page for
subsequent assembly. After a SETDP directive, the assembler will generate instruc­
tions using the direct addressing mode whenever an address is located on the specified
page. If the programmer does not specify a direct page with a SETDP directive, the direct
page is assumed to be page 0 (the high-order byte of every address is zero) for 6800
compatibility. Note that SETDP does not generate the object code required to load the
Direct Page register; the programmer must place the required instructions (such as
LOA =#:DPAGE; TFR A,DP) in the source program.

labels with Assembler Directives

The rules and recommendations for labels with 6809 pseudo-operations are as
follows:

I. Simple equates, such as MAIN EQU $COOO, require labels since their purpose
is to define the meaning of those labels.
2. FCB, FCC, FDB, and RMB pseudo-operations usually have labels.
3. ORG, END, SETDP, and other housekeeping pseudo-operations should not
have labels, since the meanings of such labels are unclear.

ADDRESSES

The Motorola 6809 Assembler allows entries in the address field in any of the
following forms:

1. Decimal (the default case)

Example:
1247

A & symbol in front of the number is optional.


2. Hexadecimal (must start with $ or end with H)

Example:
SCEOO or r:JCP.OOI-1

Note that you must place a zero in front of hexadecimal numbers that begin
with a letter (A through F), so that the assembler can distinguish them from
names, if you are using the format with a terminating H. We will use the"$"
symbol to maintain compatibility with the 6800 assembler.
3. Octal (must start with @ or end with the letter 0 or Q)

Example:
1<11:< 4 7 or 12470

We will use the"@" format to maintain compatibility with the 6800 assem­
bler.
6809 Machine Structure and Assembly Language 3-49

4. Binary (must start with % or end with B)

Example: %00101 or OO!OlB

We will use the"%" symbol to maintain compatibility with the 6800 assem­
bler.
5. ASCII (single character preceded by an apostrophe)

Example: 'fl

6. As an offset from the current value of the location counter (*).

Example: *+7

7. Relative to the current value of the location counter (OEST, PCR)

Example: LOll TABLE, PCH

The assembler will generate an indexed LOA instruction using the mode
based on a constant offset from the program counter. The value of the offset
will be the relative distance between TABLE and the current value of the
location counter. Note the difference between LOA TABLE,PCR and LOA
TABLE,PC: the latter generates an indexed LOA instruction with TABLE as
the value of the offset to be added to the program counter. The assembler au­
tomatically calculates the relative distance to the destination when the pro­
grammer uses the PCR notation.

Distinguishing Addressing Modes

The various 6809 addressing modes are distinguished as follows:

1. Direct and Extended are the default modes. The assembler chooses direct
addressing if the address is on the page specified as the direct page. Remem­
ber that the direct page is page 0 unless a SETOP directive specifies otherwise.
You can force the asssembler to use direct addressing by preceding the
address with the "< " character and to use extended addressing by preceding
the address with the ">" character.
2. The symbol =*1: precedes the data for immediate mode.
3. OFFSET,R specifies indexed non-indirect modes with offsets. R must be
one of the registers PC, S, U, X, or Y. You can force an 8-bit offset mode by
preceding the operand with the "<" character and a 16-bit offset mode by
preceding the operand with the ">"character. The assembler will automat­
ically choose the zero offset, 5-bit offset, or 8-bit offset mode if the mode is
available and the offset is the correct size.
4. The form DEST,PCR specifies the indexed mode that adds a constant
offset to the program counter, and furthermore directs the assembler to
calculate the offset as the relative distance to the address labeled OEST.

5. Square brackets enclose addresses to be used indirectly.


6. The symbol + or + + after the register name (S, U, X, or Y) specifies
autoincrementing, and - or -- before the register name (S, U, X, or Y)
specifies autodecrementing.
3-50 6809 Assembly Language Programming

Assembler Arithmetic and Logical Expressions

The assembler also allows expressions in the address field. These expressions
consist of numbers and names separated by the arithmetic operators +, - , *

(multiplication), or I <integer division), or the following special two-character opera-


tors:
!h exponentiation !< shift left
!. logical AND !> shift right
!+ logical (inclusive) OR !L rotate left
!X -
logical Exclusive OR !R -
rotate right

The precedence of the various operators is as follows:

1. Expressions within parentheses are evaluated first.


2. Multiplication, division, and the two-character operators have precedence
over addition and subtraction.
3. Operators with the same precedence are evaluated from left to right.

All intermediate results are truncated to 16-bit integers and all fractional
results are dropped.
We recommend that you avoid expressions within address fields whenever
possible, since there are no standards for calculating such addresses. If you must com­
pute an address, comment any unclear expressions and be sure that the evaluation of
the expressions never produces a result which is too large for its ultimate use.

OTHER ASSEMBLER FEATURES

Most 6809 assemblers have additional features, including both macro and condi­
tional assembly capabilities. You should consult your particular assembler's manual for
a description of how these features are implemented. We will not use any of these
features or refer to them again, although they can be quite convenient in many applica­
tions.

REFERENCES

Terry Ritter and Joel Boney, the co-architects of the Motorola 6809, have de­
scribed its architecture and instruction set in a series of three very interesting articles
entitled "A Microprocessor for the Revolution: The 6809" in BYTE magazine. These
articles describe the philosophy that resulted in the 6809 microprocessor and answer
many questions about approaches to problems, design decisions, and tradeoffs. The
specific articles in the series are:

T. Ritter and J. Boney, "A Microprocessor for the Revolution: The 6809. Part 1:
Design Philosophy," BYTE, January 1979, pp. 14-42.
T. Ritter and J. Boney, "A Microprocessor for the Revolution: The 6809. Part 2:
Instruction Set Dead Ends, Old Trails and Apologies,": BYTE, February 1979, pp.
32-42.
T. Ritter and J. Boney, "A Microprocessor for the Revolution: The 6809. Part 3:
Final Thoughts," BYTE, March 1979, pp. 46-52.
6809 Machine Structure and Assembly Language 3-51

1. A. Osborne and J. Kane, An Introduction to Microcomputers: Volume 2-Some


Real Microprocessors. Berkeley: Osborne/McGraw-Hill, 1979.
2. A. Osborne, An Introduction to Microcomputers, Volume 1 -Basic Concepts,
2nd ed. Berkeley: Osborne/McGraw-Hill, 1980.
3. L. Leventhal, 6502 Assembly Language Programming. Berkeley: Osborne/
McGraw-Hill, 1979.
II
Introductory Problems

The only way to learn assembly language programming is through experience.


The next six chapters of this book contain examples of simple programs that perform
actual microprocessor tasks. You should read each example carefully and try to
execute the program on a 6809-based microcomputer. Finally, you should work the
problems at the end of each chapter and run the resulting programs on your
microcomputer to ensure that you understand the material.

GENERAL FORMAT OF EXAMPLES

Each program example contains the following parts:

A title that describes the problem


A statement of purpose that describes the specific tasks the program performs
and the memory locations it uses

A sample problem with data and results

A flowchart if the program logic is complex


The source program or assembly language listing

The obj ect program or hexadecimal machine language listing

Explanatory notes that discuss the instructions and methods used in the pro­
gram

You should use the examples as guides for solving the problems at the end of each
chapter. Be sure to run your solutions on a 6809-based microcomputer to ensure that
they work correctly.
Program Listing Format

We reproduce Program 4-1 below to illustrate the format for program listings
which we will use in this book. This is a common format for assembler output; it
shows the object code as well as the source code.

Memory Object
Address Code Source Program
__..._.._ �
0000 911 40 LDA $40 GET DATA
0002 97 41 STA $41 TRANSFER TO NEW LOCATION
0004 3F SWI

The 4-digit number starting in the leftmost column of each line is the hexadecimal
address of the first byte of object code generated from the line of source code. For
example, in the second line 0002 is the address of the object code byte for STA (base
page direct addressing form). The digits following the address are the hexadecimal
object code for the instruction. Thus, in the second line, 97 41 is the object code for ST A
$41, and the byte 97 is in location 0002. The byte 41 is in location 0003; we infer this
from the fact that it follows the byte in address 0002. The letters, numbers, and words
to the right of the object code are the assembly language fields which we described in
Chapter 2. These fields comprise the source program.
If you wish to assemble these examples on your microcomputer, key in the
source statements only; do not enter the addresses or object codes, since the assembler
program will generate them. You will also need to enter some assembler directives -
for example, to tell the assembler where to start program addresses. We may not show
all the necessary directives; the ones you use will be determined by your assembler and
the requirements of your microcomputer's operating system.
If you wish to execute the program examples without assembling source code,
you can key the object code into the specified addresses. Before you do this, however,
make sure that you will not be trying to load areas of memory reserved for the monitor
or operating system. To avoid such problems, you may need to change addresses before
you load the programs. As we will discuss in the seventh guideline below, you may also
need to change the instruction at the end of the program.

Guidelines for Examples

We have used the following guidelines in constructing the examples:

Standard 6809 assembler notation as summarized in Chapter 3

Use of the clearest possible forms for expressing data and addresses. We use
hexadecimal numbers for memory addresses, instruction codes, and binary­
coded decimal (BCD) data; decimal for numeric constants; binary for logical
masks; and ASCII (American Standard Code for Information Interchange) for
characters
Emphasis on frequently used instructions and common programming tech­
niques

Drawing of problems from actual microprocessor applications in com­


munications, instrumentation, computers and peripherals, business equip­
ment, industrial and process control, and military systems

Extensive commenting for instructional purposes, often more than we would


typically include in actual programs
Emphasis on simple, clear structure, while still making programs as efficient
as possible within this guideline. The notes often describe more efficient pro­
cedures
Use of a standard set of memory addresses. Each program starts in memory
location 000016, uses memory addresses starting at 0040111 for temporary data
storage, and ends with the SWJ (Software Interrupt) instruction. Jf your
microcomputer has no monitor and no interrupts, you may prefer to end pro­
grams with an endless loop instruction such as

HERE BRA HERE

Some 6809-based microcomputers require a JMP or JSR instruction with a


specific destination address to return control to the monitor. You should con­
sult the User's Manual for your microcomputer to determine the required
memory addresses and terminating instruction for your particular system.
Use of base page direct memory addressing. This makes the object code pro­
gram even shorter and therefore easier to key into memory for testing

Trying the Examples

To test an example program on your microcomputer system, first place the


object program in memory. Your assem bier program may do this automatically, or it
may create an object code file which a separate loader program must then place in
memory. Many of the example programs are so short that you can bypass the assembler
and simply key the object code into memory using your monitor facility or front panel.
Be sure to make any changes your system requires before entering the code; as we men­
tioned earlier, you may have to change addresses in the program or the terminating
instruction.
Once the program is in memory, put the test data in the appropriate locations.
Then run the program. After the program terminates, examine the result locations.
To test different sets of data, simply change the appropriate data locations before run­
ning the program again.

GUIDELINES FOR SOLVING PROBLEMS

Use the following guidelines in solving the problems at the end of each chapter.

1. Comment each program so that others can understand it. The comments
may be brief and ungrammatical; they should explain the purpose of an
instruction or a section of the program. Comments should not describe the
operation of instructions; that description is available in manuals. You do not
have to comment each statement or explain the obvious. You may follow the
format of the examples but provide less detail.
2. Emphasize clarity, simplicity, and good structure in programs. While pro­
grams should be efficient, do not worry about saving a single byte of program
memory or a few microseconds.
3. Make programs reasonably general. Do not confuse parameters (such as the
number of elements in an array) with fixed constants (such as 1T or ASCII C).
4. Load initial values for parameters from the memory area assigned for tern-
porary storage. Remember that microprocessor applications programs will
often execute from ROM or from protected RAM, so you will not be able to
vary parameters that are assigned values in the program. The more
parameters you can vary, the more likely the program is to be useful in a wide
range of tasks.
5. Use assembler notation as shown in the examples and defined in Chapter 3.
6. Use hexadecimal notation for addresses. Use the clearest possible form for
data.
7. If your microcomputer allows it, start all programs in memory address
0000 and use memory addresses starting with 004016 for data and tempor­
ary storage. Otherwise, establish equivalent addresses for your microcom­
puter and use them consistently. Again, consult your user's manual.
8. Use meaningful names for labels and variables -for example, SUM or
CHECK rather than X, Y, or Z.
9. Execute each program on your microcomputer. This is ultimately the only
way to verify that the program functions correctly. We have provided sample
data with each problem, but be sure that the program works for all special
cases.

FURTHER PROGRAMMING TIPS

We will now summarize some useful information that will help you in writing your
first programs.

Accumulator Operations

Almost all processing instructions (for example, Add, Subtract, AND, OR) use
the contents of an accumulator as one operand and place the result back in the same
accumulator. In most cases, you will load the initial data into an accumulator with LOA
or LOB. You will then store the result (from the same accumulator) with STA or STB.

The Direct Page (Base Page)

You can place data and addresses that you plan to use frequently on the direct
(base) page -that is, the page that the processor can access using the Direct Page
register. You can then utilize the short direct addressing mode, using one-byte
addresses, to reach that data. We assume in our examples that the direct page is page
zero, although you can change it easily enough. Remember, however, that the processor
initializes the Direct Page register to zero on machine reset, and the assembler assumes
the direct page to be page zero unless a SETOP pseudo-operation changes this assump­
tion explicitly.
6809 direct page addressing is a powerful programming tool. Instruction forms
with this addressing mode have shorter object codes and execute faster than those using
other memory addressing modes, and you can place the direct page anywhere in
memory (along 256-byte boundaries). However, there are disadvantages to using the
direct page. Direct page addressing is a type of absolute addressing; thus programs
which use it are limited since the addresses are fixed in the object code. Furthermore,
changing the direct page register in a program introduces a new source of potential
errors. The more complex the program or system, the more likely it is that program
execution might unexpectedly branch or return to a sequence that assumes the wrong
direct page. The 6809 designers intended the direct page to be a tool for program
optimization and operating system organization, and discourage its casual use in applica­
tions programs. (See the References section of Chapter 3 for further information.)

Memory Operations

Some instructions- shifts, clear, increment (add 1), decrement (subtract 1),
and ones or twos complement - can act directly on data in memory. Such instructions
allow you to bypass the user registers, but each executes more slowly than the equiva­
lent instruction that acts on a register. A memory operation is slower because the CPU
must load the data into a temporary register, perform the operation, and then store the
result back into memory. Therefore a sequence of operations on one memory location
will execute more slowly than the sequence which operates on the same data in a
register, even though the latter sequence must be two instructions (a load register and a
store back to memory) longer. Of course, for a single operation the one instruction that
operates directly on memory executes faster than the three instructions (load, operate,
store) required to obtain the same result through a register operation. Thus, operating
directly on memory is slower than register operation unless the register load and
store overhead eliminates the time savings resulting from register use.
4
Beginning Programs

This chapter contains some very elementary programs. They will introduce
some fundamental features of the 6809. In addition, these programs demonstrate some
primitive tasks that are common to assembly language programs for many different
applications.

PROGRAM EXAMPLES

4-1. 8-BIT DATA TRANSFER

Purpose: Move the contents of memory location 0040 to memory location 0041.

Sample Problem:
(0040) 6A

Result: (0041 l 6A

Program 4-1 :
0000 96 40 LDA $40 GET DATA
0002 97 41 STA $41 TRANSFER TO NF.\,r T.OCIITION
0004 3f SWI

LOA (Load Accumulator A) and ST A (Store Accumulator A) both need an


address to determine the memory location that the processor will use in loading or stor­
ing the data. In the example, we have used addresses on the direct page (or base page).
Remember that we are assuming the Direct Page register contains zero, so all addresses
4-.L 6809 Assembly Language Programming

with zeros in their eight most significant bits are on the direct page. Therefore, we can
use the direct (or base page) forms of LOA and STA in which the instructions need only
specify the eight least significant bits of the memory address in the byte following the
operation code. We can omit the leading zeros just as we do in everyday conversation
(e.g., we say "sixty cents" rather than "zero dollars and sixty cents"). However,
remember that the addresses are really 004016 and 004116•
Before you execute the example program, you will have to load the data into
memory location 004016. After you execute the program, you can see the result in
memory location 004116 (or in Accumulator A -why?).
We use SWI (Software Interrupt) to end all examples and return control to the
monitor. You may have to replace this instruction with whatever your microcomputer
requires.

4-2. 8-BIT ADDITION

Purpose: Add the contents of memory locations 0040 and 0041, and place the result in
memory location 0042.

Sample Problem:
(0040) 38
(0041) 28

Result: (0042) 63

Program 4-2:
0000 96 40 LOA 540 GET FIRST OPERAND
0002 98 41 .'IDDA $41 ADD SECOND OPERAND
0004 97 42 STA $42 STORE RESULT
0006 3F SWI

This program uses the direct (base page) forms of LOA, AODA, and STA, since
we have placed all the addresses on the direct page. We will use direct page addressing
throughout this book, in order to make the example programs shorter and thus easier to
key into memory by hand.
AOOA affects the Carry flag, but LOA and STA do not. Only arithmetic and shift
instructions affect the Carry; logical and transfer instructions do not.
LOA and AOOA do not affect the contents of memory, but they do affect the
contents of Accumulator A. On the other hand, ST A changes the contents of the
addressed memory location, but does not affect the contents of Accumulator A.
Before you execute this example program, you will have to load the two operands
into memory locations 004016 and 004116• After you execute the program, you can see
the result in memory location 004216. In a real application, some previous section of the
program would store the data in memory and a subsequent section would use the result.

4-3. SHIFT LEFT 1 BIT

Purpose: Shift the contents of memory location 0040 left one bit and place the result in
memory location 0041. Clear bit position 0.

Sample Problem:
(0040) 6F=0110 11112

Result: (0041) DE=1101 11102


Beginning Programs 4-3

Program 4-3:
0000 06 40 LOB $40 GET DATA
0002 58 ASLB SHIFT LEFT
0003 07 41 STB $41 STORE RESULT
0005 3F SWI

Unlike the two previous programs, this one uses Accumulator B. There is no com­
pelling reason for these preferences; we could use Accumulator A in this program, and
we could use Accumulator B in either of the previous programs. Accumulators A and B
are virtually interchangeable; most instructions can use either one. We will note a few
differences in later chapters.
ASLB shifts Accumulator B left one bit and clears the least significant bit position
(bit 0). The previous contents of bit position 7 go into the Carry flag. The result (includ­
ing the Carry flag) is twice the original data (why?).
We could also shift the contents of memory location 0040 left one bit with the
instruction ASL $40 and then move the result to memory location 0041. However, this
method would change the contents of memory location 0040 as well as the contents of
memory location 0041. How would you change the program to operate on a memory
location without changing the contents of location 0040?
Compare the bit patterns for instructions that use Accumulator A with those that
use Accumulator B. How do the bit patterns differ? 1 How does the processor know
whether to use Accumulator A or Accumulator B? Remember that two groups of
instructions use an accumulator: single-operand instructions such as shifts, clear, incre­
ment, and decrement; and double-operand instructions such as ADD, AND, and SUB.

4-4. MASK OFF MOST SIGNIFICANT FOUR BITS

Purpose: Place the least significant four bits of memory location 0040 in the least signifi­
cant four bits of memory location 0041. Clear the most significant four bits of
memory location 0041.

Sample Problem:
(0040) 30=0011 11012

Result (004 1) OD =0000 1 1 012

Program 4-4:
0000 96 40 LDA $40 GET DATA
0002 84 OF ANDA #%000011ll MASK OUT FOUR MSB'S
0004 97 41 STA $41 STORE RESULT
0006 3F SWI

The symbol* identifies an immediate operand, and % means binary constant in


standard 6809 assembler notation.
ANOA*%00001111 logically ANDs the contents of Accumulator A with the bi­
nary number 00001111 (OF 16), not the contents of memory location OOOF. Immediate
addressing (indicated by* in the operand field) means that the instruction contains the
actual data, not its address.
We have written the mask (00001111) in binary to make its purpose clearer to the
reader. Binary masks are easier to understand than hexadecimal ones since the
microprocessor performs logical operations bit-by-bit rather than on digits or bytes.
The result, of course, does not depend on the programming notation. You should use
hexadecimal notation for long masks whenever the binary versions become cumber­
some. The comments should then explain the purpose of the masking operation.
4-4 6809 Assembly Language Programming

A logical AND instruction may be used to clear bits that are not meaningful.
For example, the four least significant bits of the data could be an input from a ten-posi­
tion switch or an output to a numeric display. Remember that logically ANDing a bit
with '0' always produces a zero result, while logically ANDing a bit with '1' does not
change its value.

4-5. CLEAR A MEMORY LOCATION

Purpose: Clear memory location 0040; that is, reset all the bits in location 0040 to zeros.

Program 4-5:
0000 OF 40 CLR $4 0 CLEAR MEMORY LOCATION 00�0
0002 3F SWI

The CLR instruction can act directly on a memory location, without the need for a
user register. Of course, the processor does not really clear the memory location
directly; instead, it generates a zero internally (using a register that the programmer can­
not access) and writes it into the specified memory location.
CLR always affects the status flags in the same way: it resets the Carry, Sign
(Negative), and Overflow flags, and sets the Zero flag.
The 6809 instruction set treats zero as a special number; no other value can be
loaded into a memory location as easily.

4-6. BYTE DISASSEMBLY

Purpose: Divide the contents of memory location 0040 into two 4-bit sections (some­
times called "nibbles" or "nybbles") and place the sections in the low-order
four bits of memory locations 0041 and 0042. Place the four most significant
bits of 0040 in 0041 and the four least significant bits of 0040 in 0042. Clear
the four most significant bits of both 0041 and 0042.

Sample Problem:
(0040) 3F

Result: (0041) 03
(0042) OF

Program 4-6:
:100 f) ')(; �() L f)/\ $40 GET DATA
() () r, 7 �l4 ()F 1\NDA �%0000llll .MASK OFF MSB' S
()()(}� <)") �? ')T/\ $�2 STORE LSB'S
fliJOG ')(, '10 Lf)/\ S40 RELOAD 0/\TA
nona �.� LSRA SHIFT MSB'S TO LEAST
!JODCJ 4-1 LSRA SIGNIFICANT POSITIONS
'100/\ A� LSR/\ AND CLEAR OTHER
OOOLl 44 LSRA POSITIONS
none 97 �� ST/\ S4l STORE MSB'S
norn: lr swr

Each execution of LSR shifts an accumulator or memory location right one posi­
tion, so four LSRs are required to shift four positions. LSR always clears the most sig­
nificant bit of the result (a so-called "logical shift"), so four LSRAs clear the four most
significant bits of Accumulator A.
Rewrite the program so that it saves a copy of the data in Accumulator 8 rather
than loading it twice. Use the instruction TFR A,8. This instruction moves the contents
of A to 8 without changing A. Which version do you prefer, and why?
Beginning Programs 4-5

The monitor program in your microcomputer must contain a routine similar to


this example if it prints or displays the contents of memory locations in hexadecimal.
The output device must receive the two hexadecimal digits separately in order to print
or display them separately.

4-7. FIND LARGER OF TWO NUMBERS

Purpose: Place the larger of the contents of memory locations 0040 and 0041 in memory
location 0042. Assume that memory locations 0040 and 0041 contain
unsigned binary numbers.

Sample Problems:
a. (0040) 3F
(0041) 2B
Result: (0042) = 3F

b. (0040) 75
(0041) AS
Result: (0042) AS

Program 4-7:
0000 <)lj �I) LD/\ S40 GET FIRST OPERAND
0002 ')] II 1 CMPA S-11 IS SECOND OPERAND LARGER?
000-1 74 02 BllS STRES
oooc; % -11 LDA $!) 1 YES,GET SECOND OPERAND
OOOR 97 4?. STRES ST/\ 547 STORE LARGER OPERAND
()00/\ JF SWI

The Compare Instruction and Status Flags

CMPA $41 subtracts the contents of memory location 0041 from the contents of
Accumulator A, but does not save the result anywhere. All the CMPA instruction does
is set the flags for branching; it leaves the value in Accumulator A unchanged, so that
value can be used for later comparisons or other operations.
CMPA affects the flags as follows:

l. The Carry flag (C) is set to 1 if the unsigned subtraction requires a borrow and
to 0 if it does not.
2. The Zero flag (Z) is set to 1 if the result of the subtraction is zero and to 0 if it
is not.

3. The Sign flag (N) takes the value of the most significant bit of the result of the
subtraction.

4. The Overflow flag (V) is set to 1 if the subtraction causes twos complement
overflow and to 0 if it does not.

The following cases are particularly important smce they are often used for
branching:

1. Z = 1 if the operands are equal� Z = 0 if the operands are not equal. Thus you
can use BEQ or BNE after a CMP instruction to check for equality.
2. C = 1 if the contents of the memory location are larger (in the unsigned
sense) than the contents of the accumulator; C = 0 if the contents of the
memory location are smaller than or equal to the contents of the accumulator.
Remember that CMPA calculates (A) - (M), where M is the selected
memory location. A borrow is necessary if (M) is larger.
4-6 6809 Assembly Language Programming

Thus you can use BLO, BHI, BLS, or BHS after a CMP instruction to compare
the magnitude of unsigned numbers. There are four branches so that you can put the
equality case on either side; that is, the options are:

a. (A) > (M) BHI, branch if (A) is higher (greater than (M)).
b. (A) L (M) BHS (BCC), branch if (A) is higher or same (greater than or equal
to (M)).
c. (A) � (M) BLS, branch if (A) is lower or same (less than or equal to (M)).
d. (A) < (M) BLO (BCS), branch if (A) is lower (less than (M)).

Calculating Relative Offsets


All 6809 conditional branch instructions use relative addressing; in this mode,
the destination is specified by how far it is from the current instruction. In the short
form, the second byte is an 8-bit twos complement number with a range of -128 (1000
00002) to + 127 (0 Ill 11112). The processor adds this number to the program counter
to calculate the destination; the result is

NEW PC = OLD PC + OFFSET + 2

where OLD PC is the original value of the program counter and the extra 2 comes from
the two bytes occupied by the branch instruction itself. Rearranging, we can calculate
the offset from the equation

OFFSET = NEW PC - OLD PC - 2

In our latest object program, for example, we have

OLD PC= 0004

NEW PC (destination) = 0008

So
OFFSET = 0008 - 0004 - 2 = 02

You can always get the same result by counting bytes. Start counting at 0 at the byte
immediately following the last byte of the branch instruction.
Calculating offsets is clearly a rather unpleasant task, unless you are very good at
binary or hexadecimal arithmetic or own a calculator (such as the Texas Instruments
Programmer) that performs arithmetic in different number systems. The calculations
are particularly troublesome if the branch is backwards - that is, the destination
address is smaller than the original program counter value plus two. Then you must deal
with negative binary or hexadecimal numbers: FF16 is -1, FE16 is -2, and so on.
Counting bytes is very tedious, especially for long offsets.
The way to avoid calculating offsets is to let the assembler do it. You can, for
example, simply specify how far you want the branch to go by using an expression
containing the symbol*, which refers the assembler to the current value of the location
counter. Thus
oHS *+-4

will produce a branch to the instruction four bytes further along. The assembler will take
care of the extra 2 automatically (that is, it will make the actual offset 2 instead of 4).
The problem with this approach is that 6809 instructions vary in length and thus it is
often difficult to determine the required numerical value. Furthermore, a much better
method of specifying offsets is available.
Beginning Programs 4-7

The better method is to assign a name (referred to as a "label") to the destina­


tion address. You can choose whatever name you want (see Chapter 2), but we will try
to choose names that have some mnemonic value. The assembler will determine the
actual address to which the label refers and will calculate offsets for any branches that
use the label. The use of labels not only makes the programmer's job easier, but it also
makes programs easier to read and understand.

Conditional Branches

Conditional branches work as follows:

1. If the condition is true, the processor branches. That is, it places the destina­
tion address in the program counter and starts executing instructions at that
point.
2. If the condition is false, the processor continues its normal sequence as if
the branch instruction did nothing at all except advance the program counter.

In our latest source program, the choices are:


1. If (A) 2 (0041). NEW PC= OLD PC+ OFFSET+ 2= 0004 + 02 + 2
= 0008 (We have named this location
with the label STRES.)

2. If (A) < (0041), NEW PC =OLD PC + 2 = 0004 +2


= 0006 (The location immediately
following the branch
instruction.)

Executing a 2-byte instruction advances the program counter by 2 regardless


of whether a branch occurs.
BHS causes a branch if (A) � (M). In terms of the flags, the branch condition is
C = 0, meaning (A) � (M).

4-8. 16-BIT ADDITION

Purpose: Add the 16-bit number in memory locations 0040 and 0041 to the 16-bit num­
ber in memory locations 0042 and 0043. The most significant bytes are in
memory locations 0040 and 0042. Store the result in memory locations 0044
and 0045, with the most significant byte in 0044.

Sample Problem:

(0040) 67
(0041) 2A

(0042) 14
(0043) FS

Result: 672A + 14F8 = 7C22

(0044) 7C
(0045) = 22

Program 4-8:

0000 DC 40 LDD S40 GET FIRST lG-BIT NUMBER


0002 [)) 112 ADDD $42 ADD SECOND lG-BIT NUMBER
0004 DD 44 STD $44 STORE lG-BIT RESULT
OOO'i 3F SWI
4-8 6809 Assembly Language Programming

The Double Accumulator D consists of Accumulator A, which comprises the


high-order byte, and Accumulator B, used as the low-order byte. Be careful - D is
not a separate register; it is physically the same as A and B.
The 16-bit operations LDD, ADDD, and STD all operate on two bytes of data.
For example, LDD $40 loads the contents of memory location 0040 into Accumulator A
and the contents of memory location 0041 into Accumulator B. ADDD $42 adds the
contents of memory location 0043 to Accumulator B and then adds the Carry from that
operation and the contents of memory location 0042 to Accumulator A. STD $44 stores
the contents of Accumulator A in memory location 0044 and the contents of Accumula­
tor B in memory location 0045.
The 6809 microprocessor actually performs most 16-bit operations eight bits (one
byte) at a time. The advantages of the 16-bit instructions are that they direct the pro­
cessor through two 8-bit operations instead of one, thus reducing the amount of time
spent fetching instructions as well as the amount of program memory that is required.
Remember that 16-bit data (and 16-bit addresses) always occupy two bytes of
memory, the one that is actually addressed and the next higher one. For example,
LDD $40 uses memory location 0041 as well as 0040.
The 6809 convention for storing 16-bit data (and 16-bit addresses) is to store the
eight most significant bits first (at the lower address). This convention seems natural,
but is the opposite of that used in most other microprocessors and minicomputers.

4-9. TABLE OF SQUARES

Purpose: Calculate the square of the contents of memory location 0041 from a table and
place the square in memory location 0042. Assume that memory location 0041
contains a number between 0 and 7 inclusive; that is, 0 < (0041) < 7. The
table occupies memory locations 0050 through 0057.

Entry
Hexadecimal
Memory Address
Hexadecimal Decimal

0050 00 0 (02)
0051 01 1 (1 2)
0052 04 4 (22)
0053 09 9 (32)
0054 10 16 (42)
0055 19 25 (52)
0056 24 36 (62)
0057 31 49 (72)

Sample Problems:
a. (0041) 03

Result: (0042) 09

b. (0041) 06

Result: (0042) 24

Remember that the answer is a hexadecimal number.


Beginning Programs 4-9

Program 4-9:
0000 D"i 4l LDB $41 G ET DATA
0002 8E OO'iO LOX #SSO GET BASE ADDRESS
000 �) AG <JS LOA B,X GET SQUARE OF DATA
0007 97 47 STA $47 STORE SQUARE
000') JF S\"I

00')0 ORG $SO TABLE 01." SQUARES


00 ')0 00 �;OTAB FCB 0,1,4,9; !G,75,3'i,49
0051 ()]
oor,:;> 04
DOS) 09
OOS4 lfl
!lOSS 19
OOSG ?4
i) 0 s 7 11

The assembler directive FCB places the table of squares in memory locations 0050
through 0057. This block of data is essential for the proper execution of the program,
even though it does not consist of instructions. The object program may thus include
fixed data as well as executable instructions.
LOX =#=$50 loads Index Register X from the two bytes of memory immediately
following the operation code (addresses 0003 and 0004 in the object program). The pro­
cessor loads the contents of the first byte into the eight most significant bits of Index
Register X, and the contents of the second byte into the eight least significant bits of
Index Register X. Always remember that Index Registers X andY, Stack Pointers S and
U, and the Double Accumulator D are all 16 bits long.

Indexed Addressing

The instruction LOA B,X loads Accumulator A from the address calculated by
adding the contents of Index Register X (the "base address" of the table) and the con­
tents of Accumulator B (the index of the element that we want). For example, if
memory location 0041 contains 03, then
(X) = 0050 (base address of the table of squares)
(B) = 03 (datal

The calculated or "effective" address is


EA = (X) + (B) = 0053

Address 0053 contains the square of 3. The result of this procedure (called a ''table
lookup") depends only on the organization of the table; it does not depend on the table
data value or on the function that the table represents.
As we discussed in Chapter 3, all indexed instructions require an extra object code
byte, called the "post byte," which selects from among the indexed addressing modes.
Our example uses the non-indirect mode with an offset in Accumulator B from the
indexable register R (referred to as accumulator indexed addressing). The binary form
is:
1 R R 0 0 1 0 1

We have chosen Index Register X, so RR = 00. See Table 3-4 and Appendix B for a
complete description of the indexed addressing modes and the assignment of bits in the
post bytes.
Indexing takes extra clock cycles whenever the processor must calculate the effec­
tive address. Adding Accumulator B to Index Register X takes one cycle beyond the
base amount required by any indexed instruction (four cycles for LOA). Appendix B
tells how many extra bytes of memory and extra clock cycles each of the indexed modes
requires.
4-10 6809 Assembly Language Programming

Operations on Registers X, Y, S, and U

The 6809 has a few special instructions that operate on the index registers and
stack pointers rather than on the accumulators. These are:
CMP(X/Y/S/U) - Compare Memory with Index Register or Stack
Pointer

LD(X/Y/S/U) Load Memory into Index Register or Stack


Pointer

LEA (X/Y/S/U) Load Effective Address into Index Register or


Stack Pointer

ST(X/Y/S/U) Store Index Register or Stack Pointer in


Memory

The index registers and stack pointers are primarily intended to hold memory addresses,
so there are no logical or arithmetic instructions for those registers. As we will see,
however, you can occasionally use LEA to perform some arithmetic.

Use of the ORIGIN Directive

The assembler directive ORG simply determines where the loader program will
place the next section of code when it is finally entered into the microcomputer's
memory for execution. An ORG does not actually result in the generation of any object
code.

Arithmetic with Tables

The use of lookup tables is a simple but powerful approach to solving complex
arithmetic problems on microprocessors. The lookup table contains all the possible
answers to a problem, much as a table of sines or cosines contains all the possible
values of a particular function. This approach reduces an arithmetic problem to a prob­
lem of obtaining the correct answer from the table. To do that, we need two things: the
base (starting) address of the table and the position (called the "index") of the answer.
The address of the answer is the sum of the base address and the index.
The base address of a table is a fixed number. The index, however, is not, and we
need some way to determine it. In simple cases (such as our Table of Squares example),
we can organize the table so that the data itself is the index. In the example, the zeroth
entry in the table is zero squared, the first entry is one squared, and so on. In more com­
plex cases, where the input values are irregularly spaced or there are several data items
involved (for example, roots of a quadratic equation or number of permutations), we
must actually perform some computations (perhaps even involving another table) to
determine an index from the data.
The use of ta bles represents tradeoffs among programming time, execution
time, and memory usage. A table lookup executes faster than any but the simplest
calculations. For example, even the Table of Squares program executes faster than an
equivalent simple squaring program using the 6809 multiplication instruction MUL.
Tables can be faster and simpler to program than actual calculations since lookup pro­
cedures do not depend on the complexity of the function involved. Furthermore, since a
table lookup is fast-executing, it is unlikely to slow down a program intolerably, as a
complex calculation might, and thus is less likely than a calculation to require
reprogramming to save execution time. On the other hand, tables can occupy a large
Beginning Programs 4-11

amount of memory if there are many possible input values. We can often reduce the
required amount of memory by limiting the accuracy of the results, scaling the input
data, or organizing the table cleverly.
Common uses of tables include the computation of transcendental and trig­
onometric functions, the linearization of inputs from thermocouples and other non­
linear devices, and code conversions.

4-10. 16-BIT ONES COMPLEMENT

Purpose: Place the ones complement of the 16-bit number in memory locations 0040
and 0041 in memory locations 0042 and 0043. The most significant bytes are
in locations 0040 and 0042.

Sample Problem:
(0040) 67 } 01 10 0111 1110 00102
(0041) E2
Result: (0042) 98 l1001 1000 0001 11012
(0043) 1D f
The ones complement of a number is its logical inverse; that is, each 0 bit in the
number is replaced by a I and each 1 bit by a 0. The sum of a number and its ones com­
plement is therefore always a number in which all the bit positions contain Is.

Program 4-1 0:

0000 DC 40 LDD $40 GET 1�-BIT NUMBER


0002 43 COMA ONES COMPLEMENT MSH'S
0003 53 COMB ONES COMPLEMENT LSB'S
0004 DD 42 STD $42 STORE 16-BIT ONES CO�PLfME�T
0006 3F SWI

Despite the 6809's 16-bit instructions, you must use the 8-bit instructions to per­
form many arithmetic and logical operations. The 6809 instruction set does include
some common 16-bit operations, such as loading, adding, comparing, subtracting, and
storing, but other operations must be performed eight bits at a time.
Manage the accumulators with care; they can hold only one result at a time. If you
need an accumulator's contents, be sure to save them before reloading the accumulator.

PROBLEMS

4-1. 16-BIT DATA TRANSFER

Purpose: Move the contents of memory location 0040 to memory location 0042 and the
contents of memory location 0041 to memory location 0043.

Sample Problem:

(0040) 3E
(0041) 87
Result: (0042) 3E
(0043) 87
4-12 6!109 Assembly Language Programming

4-2. 8-BIT SUBTRACTION

Purpose: Subtract the contents of memory location 0041 from the contents of memory
location 0040. Place the result in memory location 0042.

Sample Problem:

(0040) 77
(0041) 39

Result: (0042) 3E

4-3. SHIFT LEFT TWO BI"TS

Purpose: Shift the contents of memory location 0040 left two bits and place the result in
memory location 0041. Clear the two least significant bit positions.

Sample Problem:

(0040) 50=0101 11012

Result: (0041) = 74=0111 01002

4-4. MASK OFF LEAST SIGNIFICANT FOUR BITS

Purpose: Place the four most significant bits of memory location 0040 in memory loca­
tion 0041. Clear the four least significant bits of memory location 0041.

Sample Problem:

(0040) C4 =1100 01002

Result: (0041I CO=1100 00002

4-5. SET A MEMORY LOCATION TO All ONES

Purpose: Set all the bits of memory location 0040 to ones (FF16).

4-6. BYTE ASSEMBLY

Purpose: Combine the four least significant bits of memory locations 0040 and 0041
into a byte and store the result in memory location 0042. Place the four least
significant bits of memory location 0040 in the four most significant bit posi­
tions of memory location 0042; place the four least significant bits of memory
location 0041 in the four least significant bit positions of memory location
0042.

Sample Problem:

(0040) 6A =0110 10102


(0041 ) 83 = 1011 0011 2

Result: (0042) A3 =1010 00112


Beginning Programs 4-13

4-7. FIND SMALLER OF TWO NUMBERS

Purpose: Place the smaller of the contents of memory locations 0040 and 0041 in
memory location 0042. Assume that memory locations 0040 and 0041 con­
tain unsigned binary numbers.

Sample Problems:

a. (0040) 3F
(0041) 2B

Result: (0042) 2B

� �040) 75
(0041) AS

Result: (0042) 75

4-8. 24-BIT ADDITION

Purpose: Add the 24-bit number in memory locations 0040, 0041, and 0042 to the 24-
bit number in memory locations 0043, 0044, and 0045. The most significant
bytes are in memory locations 0040 and 0043, the least significant bytes in
memory locations 0042 and 0045. Store the result in memory locations 0046,
0047, and 0048 with the most significant byte in memory location 0046 and
the least significant byte in 0048.

Sample Problem:

}
(0040) 35
(0041) 67 35672A
(0042) 2A

}
(0043) 51
(0044) A4 51A4F8
(0045) F8

}
Result: (0046) 87
(0047) OC 870C22
(0048) 22

4-9. SUM OF SQUARES

Purpose: Calculate the squares of the contents of memory locations 0040 and 0041 and
add them together. Place the result in memory location 0042. Assume that
memory locations 0040 and 0041 both contain numbers between 0 and 7
inclusive; that is, 0 � (0040) � 7 and 0 s (0041) s 7. Use the table of squares
from the example entitled Table of Squares.
Sample Problem:
(0040) 03
(0041) 06

Result: (0042) 20

that is, 32 + 62 = 9 + 36 10 = 45 10 = 2D1s


4-14 6809 Assembly Language Programming

4-10. 16-BIT TWOS COMPLEMENT

Purpose: Place the twos complement of the 16-bit number in memory locations 0040
and 0041 (most significant bits in 0040) in memory locations 0042 and 0043
(most significant bits in 0042). The twos complement of a number is the num­
ber that, when added to the original number, produces a result of zero; the
twos complement is also equal to the ones complement plus one, since the
sum of a number and its ones complement is all 1 bits.

Sample Problems:

a. (0040) 00 } 0000 0000 0101 10002


(0041) 58

Result: (0042) FF }
1111 1111 1010 10002
(0043) AB

b. (0040) 72
} 0111 0010 0000 00002
(0041) 00

Result: (0042) BE} 1000 1110 0000 00002


{0043) 00

Since the sum of the original number and its twos complement is zero, we can
calculate the twos complement of x as 0 - x. Which approach (calculating the ones
complement and adding one, or subtracting from zero) results in a shorter and faster
program? Remember to use the SUBD instruction.

REFERENCES

1. L. A. Leventhal, "Microprogramming," Kilobaud. April 1977, pp. 120-23.


5
Simple Program Loops

The program loop is the basic structure that forces the CPU to repeat a
sequence of instructions. Loops have four sections:

1. The initialization section, which establishes the starting values of counters,


pointers, indexes, and other variables.

2. The processing section, where the actual data manipulation occurs. This is
the section that does the work.

3. The loop control section, which updates counters and pointers for the next
iteration.
4. The concluding section, which analyzes and stores the results.

The computer performs Sections I and 4 only once, while it may perform Sections
2 and 3 many times. Therefore, the execution time of the loop depends mainly on the
execution time of Sections 2 and 3. Those sections should execute as quickly as possible,
while the execution times of Sections 1 and 4 have little effect on overall program speed.
Figures 5-l and 5-2 contain two alternative flowcharts for a typical program
loop. Following the flowchart in Figure 5-l results in the computer always executing
the processing section at least once. On the other hand, the computer may not execute
the processing section in Figure 5-2 at all. The order of operations in Figure 5-l is
more natural, but the order in Figure 5-2 is often more efficient and eliminates the prob­
lem of the computer going through the processing sequence once even where there is no
data for it to handle.
The computer can use the loop structure to process large sets of data (usually
called "blocks" or "arrays"). The simplest way to use one sequence of instructions
to handle a block of data is to have the program add 1 to its address register (usually
5-2 6809 Assembly Language Programming

Initialization
Section

Processing
Section

Loop Control
Section

Concluding
Section

The computer always executes the processing section at least once.

Figure 5-1. Flowchart of a Program Loop

an index register or stack pointer) after each iteration. Then the address register will
contain the address of the next element in the block when the computer repeats the
sequence of instructions. The computer can then handle blocks of any length with a
single program.
Indexed addressing is the key to processing blocks of data with the 6809
microprocessor, since that mode allows you to vary the actual address of the data (the
"effective address") by changing the contents of an address register. In immediate and
extended addressing modes, the instruction completely determines the effective
address; that address is therefore fixed if program memory is read-only. The direct page
mode shares this fixed address limitation even though a register determines part of the
effective address.
The 6809's autoincrementing mode is particularly convenient for processing
arrays, since it automatically updates the address register for the next iteration. No
Simple Program Loops 5-3

Initialization
Section

Loop Control
Section

Yes

Processing Concluding
Section Section

The computer need not execute the processing section at all if it finds that there is nothing to be done.

Figure 5-2. An Alternative for a Program Loop

additional instruction is necessary. You can even have an automatic increment by 2 if


the array contains 16-bit data or addresses.
Although our examples show the processing of arrays with autoincrementing
(adding l or 2 after each iteration), the procedure is equally valid with autodecrement­
ing (subtracting l or 2 before each iteration). Most programmers find moving back­
wards through an array somewhat awkward and difficult to follow, but it is more effi­
cient in many situations. Clearly, the computer does not know backwards from forward.
The programmer, however, must remember that the 6809 increments an address
register after using it but decrements an address register before using it. This
difference affects initialization as follows:

1. When moving forward through an array (autoincrementing), start the address


register at the lowest address occupied by the array.

2. When moving backwards through an array (autodecrementing), start the


address register one step (1 or 2) beyond the highest address occupied by the
array.
You must also remember the difference between autoincrementing and
autodecrementing if you use a CMP instruction (CMPX, CMPY, CMPU, or CMPS) to
determine if an index register or stack pointer has reached a particular value.
5-4 6809 Assembly Language Programming

PROGRAM EXAMPLES

5-1. SUM OF DATA

Purpose: Calculate the sum of a series of numbers. The length of the series is in
memory location 0041 and the series begins in memory location 0042. Store
the sum in memory location 0040. Assume that the sum is an 8-bit number so
that you can ignore carries.

Sample Problem:

(0041) 03

(0042) 28
(0043) 55
(0044) 26

Result: (0040) A3
2816 + 5516 + 2616

There are three entries in the sum, since (004 1 ) =03

Flowchart:

SUM= 0
POINTER = 0042
COUNT = (004 1 )

SUM=
SUM+ (POINTER)

POINTER=
POINTER+ 1
COUNT=
COUNT- 1

(0040) =SUM
Simple Program Loops 5-5

(POINTER) refers to the contents of the memory location addressed by


POINTER. Remember that on the 6809 and similar microprocessors, POINTER is a 16-
bit address, while (POINTER) is an 8-bit byte of data.
This flowchart has the same form as that in Figure 5-1; that is, the processing sec­
tion will execute at least once. What does this form assume about the data, specifically
the length of the series (called COUNT above)?

Program 5-1a:

0000 4F CLRA SUM = ZERO


0001 06 41 LOB $41 COUNT = LENGTH OF ARRAY
0003 8E 0042 LOX #$42 POINT TO START OF ARRAY
0001) AB 80 SUMD ADDA ,X + ADD NUMBER TO SUM
0008 'iA DECB
0009 26 FB BNE SUMD
0008 97 40 STA $40
OOOD 3F SWI

The initialization section of the program consists of the first three instructions,
which set the sum, counter, and data pointers to their starting values. LOX loads the
two bytes of memory into Index Register X: 00 and 42 from memory addresses 0004 and
0005 respectively.
The processing section of the program consists of the single instruction
ADDA ,X+ which adds the contents of the memory location addressed by Index
Register X to the contents of Accumulator A. This instruction does the real work of the
program. The effective address (that is, the address from which the CPU gets the data)
is given by the contents of Index Register X.
In the autoincrementing mode, the processor adds 1 to the contents of Index
Register X after using it to fetch the data. For example, in the first iteration, Index
Register X initially contains 0042. The execution of the instruction ADDA ,X+ results
in the contents of memory location 0042 being added to Accumulator A, and Index
Register X being incremented by 1 to 0043.
The loop control section of the program consists of the single instruction DECB,
since the instruction ADDA ,X+ updates the pointer automatically. DECB decrements
the counter that keeps track of how many iterations the computer has left to perform.
The instruction BNE causes a branch if the Zero flag is 0 (that is, if the result of
decrementing B was not zero). The offset is a twos complement number, determined by
the distance between the destination and the end of the instruction. In this case, the dis­
tance is from memory location OOOB (the address following the end of the BN E instruc­
tion) to memory location 0006 (the destination). So the offset is:

0006 } { 0006
-0008 = +FFF5
FFFB
-

The 8-bit offset mode (BNE rather than LBNE) requires only the two least significant
digits of the difference.
If the Zero flag is 1 (that is, if the result of decrementing B was zero), the processor
continues its normal sequence. Thus the result of executing BNE is:

{ SUMO if the result of decrementing B is not zero


(PC)=
(PC) + 2 if the result of decrementing B is zero
5-6 6809 Assembly Language Programming

The extra 2, as usual, comes from the two bytes occupied by the BNE instruction itself.
Most programmers make computer loops count down rather than up so that
they can use the setting of the Zero flag as an exit condition. Remember that the Zero
flag is 1 if the most recent result was zero and 0 if that result was not zero. Rewrite the
program so that it loads Accumulator B with zero initially and increments it after each
iteration. Which approach is more efficient?
The order in which the processor executes instructions is often very important.
DECB must come immediately before BNE SUMO� otherwise, the intervening instruc­
tion (s) would probably change the Zero flag. The order of operations within instructions
may also be important. In the current program, we must initialize Index Register X to
0042, the lowest address in the array, since the processor increments Index Register X
after using its contents in the instruction ADOA ,X+. What initial value would be
necessary if the processor incremented Index Register X before using its contents?

Using Register Y

We could easily use Index Register Y, User Stack Pointer U, or Hardware


Stack PointerS inst�ad of Index Register X. The only difference is that LOS and LOY
require two-byte operation codes, so a program using one of those registers would
occupy one additional byte of memory and would take one extra clock cycle to execute.
For example, the following program uses Index Register Y.

Program 5-1 b:

0000 4F CLR!\ SUM =


ZERO
()()()] DG IJl LDB $1)1 COUNT = LENGTH OF ARRAY
0003 l 08 E 0042 LDY #$42 POINT TO START OF ARRAY
0007 Al:l AO SUMO ADDA , Y+ J\[)0 NUMBER TO SUM
0009 SA DECB
OOOA 26 FB l:lNE SUMO
oooc 97 40 STA $40
0001:: 31" SWJ

In most applications, the slight differences in execution time and memory usage
between the two programs do not matter. However, you might as well use Index
Register X rather than Index Register Y when both are available, since programs that
use Index Register X will be a little shorter and faster. UserStack Pointer U can also be
utilized as an address register, but most programs leave Hardware Stack Pointer S
permanently assigned for use with subroutines and interrupts.
You should verify the hexadecimal value of the relative offset in the last program
example. Of course, the final test of any calculation of an offset is whether the program
runs correctly. If you must perform hexadecimal calculations frequently, you should use
a calculator such as the Texas Instruments Programmer.

5-2. 16-BIT SUM OF DATA

Purpose: Calculate the sum of a series of 8-bit numbers. The length of the series is in
memory location 0042 and the series itself begins in memory location 0043.
Store the sum in memory locations 0040 and 0041 (eight most significant bits
in 0040).
Simple Program Loops 5-7

Sample Problem:

(0042) 03

(0043) CB
(0044) FA
(0045) 96

Result: (0040)
(0041)

Flowchart:

SUMU = 0
SUML = 0
POINTER = 0043
COUNT = (0042)

SUML=
SUML+(POINTER)
SUMU=
SUMU+CARRY

POINTER=
POINTER+ 1
COUNT=
COUNT- 1

(0040) = SUMU

(0041) = SUML

SUMU and SUML are, respectively, the high-order and low-order bytes ofthe 16-
bit sum, SUM.

Program 5-2:

0000 4F CLRA MSB'S OF SUM = ZERO


0001 SF CLRB LSB'S OF SUM = ZERO
0002 8E 0043 LOX #$43 POINT TO START OF ARRAY
0005 EB 80 SU.N!D ADDB ,X+ SUM SUM + DAT.l\
0007 89 00 ADCA #0 AND ADD IN CARRY
0009 OA 42 DEC $42
0008 2'i F8 BNE SUMO
OOOD DO 40 STD $40 SAVE SUM
OOOF 3F SWI
5-8 6809 Assembly Language Programming

This program has the same structure as the previous example. The only difference
is that this program must handle the high-order byte of the sum as well as the low-order
byte. The initialization section clears the full 16-bit sum and the processing section now
consists of two instructions: ADDB ,X+ adds the 8-bit data to the low-order byte of the
sum and ADCA #0 adds the carry to the high-order byte.
The only new aspect is that the 16-bit sum occupies both accumulators. Thus we
use a memory location on the direct (base) page to hold the counter. Such memory
locations are often used as if they were additional registers, since the processor can
access them with faster and shorter instructions than those it uses to access other
locations.
The instruction ADCA #0 adds the carry and 0 to Accumulator A:

(A) = (A) + 0 + Carry


= (A) + Carry

The result is to leave A unchanged if the Carry flag is 0 and to increment A by I if the
Carry flag is l.
The 6809 does not have a complete set of 16-bit instructions. For example, there
is no Clear Double Accumulator instruction. We can use either the two instructions
CLRA, CLRB (requiring two bytes of memory and four clock cycles) or the immediate
instruction LDD #0 (requiring three bytes of memory and three clock cycles).
However, when a 16-bit instruction is available (for instance, STD $40), it uses less
time and memory than the two equivalent 8-bit instructions (in this case, STA $40, STB
$41).
A single instruction such as DEC $42 can decrement the contents of a memory
location by 1 without changing any registers. Such instructions do affect the flags,
however. Note that a memory location is not nearly as useful as an accumulator; there
are no instructions that perform general arithmetic or logical operations on data in a
memory location. For example, SUBA :#=3 subtracts 3 from Accumulator A; try to per­
form the same operation on the data in memory location 0042.

Long Conditional Branches

Short relative branches are limited to distances that can be specified in an 8-bit
signed offset. These limitations are 7F16 = 12710 forward and 8016 = 12810 backwards
from the end of the branch instruction. Since short branches are two-byte instructions,
the distance from the start of the instruction must be in the range

-12610s distances +12910

For longer distances, you must use the long form of the branches. A long condi­
tional branch uses the same mnemonic as its short equivalent, with an additional
"L" in front: for instance, LBCC instead of BCC. It requires a two-byte operation code
followed by a two-byte relative offset. However, the unconditional branch LBRA has a
one-byte operation code, although it still requires a two-byte offset. The long relative
branches provide access to any memory location in the normal 64K range. In actual
practice, most program branches are quite short and you will rarely need the long
forms.
Simple Program Loops 5-9

5-3. NUMBER OF NEGATIVE ELEMENTS

Purpose: Determine the number of negative elements (most significant bit contains 1)
in a block. The length of the block is in memory location 0041, and the block
itself starts in memory location 0042. Place the number of negative elements
in memory location 0040.

Sample Problem:
(0041) 06

(0042) 68
(0043) F2
(0044) 87
(0045) 30
(0046) 59
(0047) 2A

Result (0040) 02, since 0043 and 0044 contain


numbers with an MSB of 1

Flowchart:

NNEG = 0
POINTER = 0042
COUNT= (0041)

NNEG= NNEG + 1

POINTER =

POINTER+ 1
COUNT=
COUNT- 1

(0040) = NNEG
5-10 6809 Assembly Language Programming

Like the previous flowchart, this one takes the form shown in Figure 5-1; thus it
assumes that the input value of COUNT will always be 1 or greater.

Program 5-3:

0000 8E 0042 LOX �$42 POINT TO FIRST NU."'!BER


0003 SF CLRB NUMBER OF NEGATIVES = ZERO
0004 A6 30 CHKNEG LOA , X+ IS NEXT ELEMENT NEGATIVF.;?
0006 2A 01 BPL CHCNT
0008 sc INCB YES, ADD 1 TO # OF NEGATIVES
0009 OA 41 CHCNT DEC $41
OOOB 26 F7 l:lNE CHKNEG
OOOD 07 !JO STB StlO SI\VE NUMBER OF NEGATIVES
OOOF 3F SWI

LDA affects the Sign (N) and Zero (Z) flags. We can therefore immediately
determine if a number that has been loaded into an accumulator is negative or zero.
We could use the Test instruction (TST) to set the Sign flag without using
Accumulator A. Accumulator A would then be available to hold a counter. Rewrite the
example program to use TST; this instruction is often useful for determining if bit 7 of a
memory location is set or if the memory location contains zero.

BPL, Branch if Plus, causes a branch if the Sign flag is 0. The offset for BPL is
the distance from the end of the instruction to the destination. Here the distance is a
single byte; the result is that the processor skips the INCB instruction if the Sign flag
is 0.
The Sign flag simply reflects the value of bit 7 of the most recent result. If you
are using signed numbers, bit 7 is, in fact, the sign (0 for positive, l for negative); the
mnemonics for Branch if Sign = l (BMI) and Branch if Sign = 0 (BPL) assume that
you are using signed numbers. However, you can equally well use bit 7 for other pur­
poses, such as the status of peripherals or other one-bit data. You can still test bit 7 with
BMI or BPL; the mnemonics may no longer make sense, but the operations work. The
computer performs its operations without considering whether the user thinks they are
sensible or meaningful. The interpretation of the results is the programmer's problem,
not the computer's.
Negative signed numbers all have a most significant bit of 1 and thus are
actually larger, in the unsigned sense, than positive numbers.

5-4. MAXIMUM VALUE

Purpose: Find the largest element in a block of unsigned binary numbers. The length of
the block is in memory location 0041 and the block itself begins in memory
location 0042. Store the maximum (largest unsigned element) in memory
location 0040.

Sample Problem:
(0041) 05 Number of elements

(0042) 67
(0043) 79
(0044) 15
(0045) E3
(0046) 72

Result: (0040) E3, since this is the largest of


the five unsigned numbers
Simple Program Loops 5-11

Flowchart:

COUNT = (0041)
POINTER = 0042
MAX= 0

MAX= (POINTER)

POINTER=
POINTER+ 1
COUNT=
COUNT- 1

(0040) =MAX

Program 5-4:

0000 06 41 LDB $� l COUNT =


NUMBER OF ELEM ENTS
0007 4F CLRA MAX =
0 (MINIMUM POSSIBLE)
0003 8F: 0042 LOX #S42 POINT TO FIRST ENTRY
OOO'i Al so MAXM CMPA ,X+ 1S CURRENT ENTRY GREATER
* THAN MAX?
0008 74 02 BHS NOCHG
OOOA A6 IF LOA -l,X YES, REPLACE .MAX WITH
* CURRENT ENTRY
oooc 5A NOCIIG DECB
OOOD 26 F7 BNE MAXM
OOOF 97 40 STA S40 SAVE MAXIMUM
DOll w swr

The first three instructions of this program form the initialization section.
This program takes advantage of the fact that zero is the smallest unsigned binary
number. If you make zero the initial estimate of the maximum, the program will set the
maximum to a larger value unless all the elements in the array are zeros.
5-12 6809 Assembly Language Programming

The instruction LOA -I ,X uses the indexed addressing mode with a constant
offset. The offset of -1 is necessary because the autoincrementing in CMPA ,X+ has
added 1 to Index Register X. The object code uses the special 5-bit offset form (signified
by a 0 in bit 7 of the post byte). In this form, the offset is a twos complement number in
the five least significant bits; bit 4 is thus the sign of the offset, and the processor auto­
matically extends (copies) that bit into the more significant positions before performing
the addition. The processor thus extends 111112 to 1111 11112, an 8-bit number. This
form requires no additional bytes of memory (since the post byte contains the offset)
and only one additional clock cycle. The range of the offset is

-1 610 = 100002 ;:; Offset .::;, + 1 5 1 0 = 01111 2

The relative offsets in the branch instructions are:

1. BHS NOCHG
Destination address = oooc
- Address at end of instruction = OOOA
02

2. BNE MAXM
Destination address = 0006 =
0006
- Address at end of instruction = OOOF + FFF1
F7

The program works correctly if the array has two elements, but not if it has only one ele­
ment or none at all. Why? How could you eliminate this problem?
The instruction CMPA ,X+ affects the Carry flag as follows (ELEMENT is the
contents of the effective address and MAX is the contents of Accumulator A):

Carry = 0 if MAX 2 ELEMENT ("Higher or Same")


Carry = 1 if MAX < ELEMENT ("Lower")

If Carry = 0, the program branches to address NOCHG and does not replace the current
maximum. If Carry = l , the program replaces the maximum with the current element
using the instruction LOA -1 ,X.
The program does not work properly if the numbers are signed, because negative
numbers all appear to be larger than positive numbers. You must then use the Sign
(Negative) flag instead of the Carry in the comparison. However, you must also con­
sider the fact that twos complement overflow can affect the sign; that is, the magnitude
of a signed result could overflow into the sign bit. The 6809 has special branch instruc­
tions- BGT, BGE, BLE, and BLT- which perform the branches indicated by their
mnemonics after signed comparisons and handle twos complement overflow auto­
matically.

5-5. JUSTIFY A BINARY FRACTION

Purpose: Shift the contents of memory location 0040 until the most significant bit of the
number is 1. Store the result in memory location 0041 and the number of left
shifts required in memory location 0042. If the contents of memory location
0040 are 0, clear both 0041 and 0042.
The process is just like converting a number to a scientific notation; for example:

o.oo57 = 5.7 x 1 o-3


Simple Program Loops 5-13

Sample Problems:

a. (0040) 22

Result: (0041) 88
(0042) 02

b. (0040) 01

Result: (0041) 80
(0042) 07

c. (0040) CB

Result: (0041) CB
(0042) 00

d. (0040) 00

Result: (0041) 00
(0042) 00

Flowchart:

NSHFT = 0
NUMB = (0040)

Yes

Yes

Shift NUMB
left one bit (0041) = NUMB
NSHFT = {0042) = NSHFT
NSHFT + 1

Program 5-5a:

0000 SF CLRB NUMBER OF SHIFTS = ZERO

000 1 96 40 LOA 540 GET DATA


On BEQ DONE THROUGH IF DATA IS ZERO
0003 27
2B 04 CHKMS BMI DONE THROUGH IF MSB OF DATA IS
0005
0007 sc INCB ADD 1 TO NUMBER OF SHIFTS

0008 1\fl ASLA SHIFT DATA LEFT ONE BIT

0009 20 FA BRA CHKMS


OOOB DD 41 DONE STD 541 SAVE JUSTIFIED DATA AND
* NUMBER OF SHIFTS

OOOD 3F SWI
5-14 6809 Assembly Language Programming

The relative offsets are:

1. BEO DONE
Destination address = 0008
- Address at end of instruction = 0005

06

2. BMI DONE
Destination address = 0008
- Address at end of instruction = 0007

04

3. BRA CHKMS
Destination address = 0005 = 0005
Address at end of instruction = 0008 = +FFF5

FA

ASL (Arithmetic Shift Left) shifts the contents of the specified accumulator or
memory location left one bit and clears the least significant bit. The most significant bit
ends up in the Carry flag and the old Carry value is lost. ASLA is equivalent to adding
Accumulator A to itself; the result is, of course, twice the original number (try it!).
BMI DONE causes a branch to address DONE if the Sign flag is 1. This condition
may mean that the result was a negative number, or it may just mean that the most sig­
nificant bit of that result was 1. The computer only performs the operations; the pro­
grammer must provide the interpretation.
BRA is an unconditional branch; that is, it always adds the offset to the program
counter. The 6809 also has the unconditional jump instruction JMP, which can use
direct (base page), extended, or indexed addressing. BRA, like the conditional branch
instructions, always uses relative addressing.

Reorganizing the Program

We can often reorganize programs to eliminate unconditional branches. The


reorganization usually makes the initial conditions less obvious, but may save a little
memory and some execution time, particularly if the processor repeats a loop many
times. For example, we can reorganize the justification program as follows.

Program 5-5b:

0000 SF CLRB NUMBER OF SHIFTS =


0
0001 9fi 40 LOA $40 GET DATA
0003 27 Ofi BEQ DONE THROUGH IF DATA IS ZERO
0005 511 OECB NUMBER OF SHIFTS =
-1
OOO'i sc CHKM'3 INCB ADD 1 TO NUMBER OF SHIFTS
0007 48 ASLA SHIFT DATA LEFT ONE BIT
0008 24 FC BCC CHKMS CONTINUE UNTIL CARRY BECOMES l
OOOA 4') ROR!I THEN SHIFT DATA BACK ONCE
0008 DO 4l DONE: STD $41 SAVE JUSTIFIED DATA AND
* NUMBER OF SHIFTS
0000 3F SWI

This version initializes the number of shifts to - 1 and shifts the data until the
Carry becomes 1. Then it shifts the data back once since the last shift was not really
necessary. Show that this version is also correct. What are its advantages and disadvan­
tages as compared to the other version? You might wish to try some other organizations
to see how they compare in terms of execution time and memory usage.
Simple Program Loops 5-15

PROBLEMS

5-1. CHECKSUM OF DATA

Purpose: Calculate the checksum of a series of numbers. The length of the series is in
memory location 0041, and the series itself begins in memory location 0042.
Store the checksum in memory location 0040. The checksum is formed by
Exclusive-ORing all the numbers in the series together.
Such checksums are often used in paper tape and cassette systems to ensure that
the data has been read correctly. The calculated checksum is compared to the one stored
with the data - if the two checksums do not agree, the system will usually either indi­
cate an error to the operator or automatically read the data again.

Sample Problem:
(0041) 03

(0042) 28
(0043) 55
(0044) 26

Resuit: (0040) (0042) ED (0043) ED (0044)


28 ED 55 ED 26
0010 1000
0101 0101
0111 1101
0010 0110
0101 1011
58

5-2. SUM OF 16-BIT DATA

Purpose: Calculate the sum of an array of 16-bit numbers. The length of the array is in
memory location 0042 and the array itself begins in memory location 0043.
Store the sum in memory locations 0040 and 0041 with the eight most signifi­
cant bits in 0040. Each 16-bit number occupies two bytes of memory, with the
eight most significant bits first (in the lower address). Assume that the sum­
mation does not result in any carries (i.e., the sum is a 16-bit number).

Sample Problem:
(0042) 03 length of the Array

(0043)
(0044)
;�} 28F1. First Number in Array

(0045)
(0046)
��} 301A, Second Number in Array

(0047)
(0048)
:� f 4889, Third Number in Array

Result: (0040)
(0041)
::} A494 = 28F1 + 301A + 4889

Hint: Use the indexed addressing mode with autoincrementing by 2.


5-16 6809 Assembly Language Programming

5-3. NUMBER OF ZERO, POSITIVE, AND


NEGATIVE NUMBERS

Purpose: Determine the number of zero, positive (most significant bit = 0 but entire
number not zero), and negative (most significant bit = 1) elements in a
block. The length of the block is in memory location 0043, and the block itself
starts in memory location 0044. Place the number of negative elements in
memory location 0040, the number of zero elements in memory location
0041, and the number of positive elements in memory location 0042.

Sample Problem:

(0043) = 06

(0044) = 68
(0045) F2
(0046) 87
(0047) 00
(0048) 59
(0049) 2A

Result: 2 negative, 1 zero, and 3 positive, so

(0040) 02
(0041) 01
(0042) 03

5-4. FIND MINIMUM

Purpose: Find the smallest element in a block of data. The length of the block is in
memory location 0041, and the block itself begins in memory location 0042.
Store the minimum in memory location 0040. Assume that the numbers in
the block are 8-bit unsigned binary numbers.

Sample Problem:

(0041) 05

(0042) 67
(0043) 79
(0044) 15
(0045) E3
(0046) 72

Result: (0040) 15. since this is the smallest of the


five unsigned numbers

5-5. COUNT 1 BITS

Purpose: Determine how many bits in memory location 0040 are ones and place the
result in memory location 0041.

Sample Problem:

(0040) 38=0011 10112

Result: (0041) 05
6
Character-Coded Data

Microprocessors often handle data which represents printed characters rather


than numeric quantities. Not only do keyboards, teletypewriters, communications
devices, displays, and computer terminals expect or provide character-coded data, but
many instruments, test systems, and controllers also require data in this form. ASCII
(American Standard Code for Information Interchange) is the most commonly used
code; others include Baudot (telegraph) and EBCDIC (Extended Binary-Coded­
Decimal Interchange Code).
Throughout this book, we will assume all of our character coded data to be
seven-bit ASCII, as shown in Table 6-1; the character code occupies the low-order
seven bits of the byte, and the most significant bit of the byte holds a 0.

HANDLING DATA IN ASCII

Here are some principles to remember when handling ASCII data:

1. The codes for the numbers and letters form ordered subsequences. Since the
codes for the numbers 0 through 9 are 3016 through 3916, you can convert a
decimal digit to the equivalent ASCII character (and ASCII to decimal) by
means of a simple additive factor:3016 = ASCII 0. Since the codes for the
upper-case letters (4116 through 5A 16) are ordered alphabetically, you can
alphabetize strings by sorting them according to their numerical values.
2. The computer does not distinguish between printing and non-printing
characters. Only 110 devices make that distinction.
6-2 6809 Assembly Language Programming

Table 6-1. Hexadecimal ASCII Character Codes

:s:
0
5
0

NUL OLE
1

SP
2 3

0
4

(W
5

p
6 7

p NUL Null
Control Characters

DC1 Device control 1


1 SOH DCl ! 1 A Q a q SOH Start of heading DC2 Device control 2
,, STX Start of text Device control 3
2 STX DC2 2. B R b r DC3
3 ETX DC3 # 3 c s c s ETX End of text DC4 Device control 4
4 EOT DC4 $ 4 D T d t EOT End of transmission NAK Negative acknowledge
5 ENQ NAK
Cu
il) 5 E u e u ENQ Enqu1ry SYN Synchronous idle
6 ACK SYN & 6 F v f v ACK Acknowledge ETB End of transmission block
7 BEL ETB 7 G w g w BEL Bell. or alarm CAN Cancel
8 BS CAN ( 8 H X h X BS Backspace EM End of medium
9 EM 9 I y i y HT Horizontal tabulation SUB Substitute
HT )
A SUB . j z LF Line feed ESC Escape
LF j z
I VT Vertical tabulation FS File separator
B VT ESC + K [ k I
I FF Form feed GS Group separator
c FF FS < L \ I I
D - I CR Carriage return RS Record separator
CR GS =
M J m I
E so RS > N n
--·
so Shift out us Unit separator
F us I ? 0 DEL Sl Shift in SP Space
Sl - 0
DLE Data link escape DEL Delete

3. An ASCII 1/0 device handles data only in ASCII. F or example, if you want
an ASCII printer to print the digit 7, you must send it 3716 as the data� 071 6 is
the "bell" character. Similarly, if an operator presses the "9" key on an
ASCII keyboard, the input data will be 3916� 0916 is the "horizontal tab"
character.

4. Many ASCII devices do not use the entire character set. For example,
devices may ignore meaningless control characters and may not print lower­
case letters.

5. ASCII control characters often have widely varying interpretations. Each


ASCII device typically uses control characters in a special way to provide
features such as cursor control on a CRT, and to allow software control of
characteristics such as rate of data transmission, print width, and line length.

6. Some widely used ASCII characters are:

O A 16 line feed(LF)

OD16 carriage return (CR)


20 1 6 space
3F1o question mark(?)
7F16 rubout or delete character(DEL)

7. Each ASCII character occupies eight bits. This allows a large character set
but is wasteful when only a few characters are actually being used. If, for
example, the data consists entirely of decimal numbers, the ASCII format
(allowing one digit per byte) requires twice as much storage, communications
capacity, and processing time as does the BCD format(allowing two digits per
byte).
Character-Coded Data 6-3

PROGRAM EXAMPLES

6-1. LENGTH OF A STRING OF CHARACTERS

Purpose: Determine the length of a string of characters. The string starts in memory
location 0041; the end of the string is marked by an ASCII carriage return
character ('CR', OD Ill). Place the length of the string (excluding the carriage
return) into memory location 0040.

Sample Problems:
a. (0041) OD

Result: (0040) 00 since the beginning character is a carriage return

b. (0041) 52 'R '


(0042) 41 'A'
(0043) 54 ·r
(0044) 48 'H'
(0045) 45 'E'
(0046) 52 'R'
(0047) OD CR

Result: (0040) 06

Flowchart:

POINTER = 0041
LENGTH= 0

Yes

LENGTH=
LENGTH+ 1
POINTER=
(0040) = LENGTH
POINTER+ 1

Program 6-1a:
0000 5F CLRB STRING LENGTH = ZERO
0001 8E 0041 LDX #$41 POINT TO START OF STRING
0004 86 OD LDA li$0D GET ASCII CARRIAGE RETURN
*
(STRING TERMINATOR)
0006 A1 80 CHKCR CMPA ,X+ IS NEXT CHARACTER
*
A CARRIAGE RETURN?
0008 27 03 BEQ DONE YES, END OF STRING
OOOA 5C INCB NO, ADD 1 TO STRING LENGTH
0008 20 F9 BRA CHKCR
OOOD D7 40 DONE STB $40 SAVE STRING LENGTH
OOOF 3F SWI
6-4 6809 Assembly Language Programming

As far as the computer is concerned, the carriage return (CR) is just another
character (OD16). The fact that the carriage return causes the output device to per­
form a control function rather than print a symbol does not affect the computer.
The Compare instruction CMP performs a subtraction and sets the flags, but
does not change the contents of the accumulator. In Program 6-la, CMPA leaves the
carriage return character in Accumulator A for later use. In this program, the CMPA
instruction affects the Zero flag as follows:
Z = 1 if the character in the string is a carriage return
Z = 0 if it is not a carriage return
The instruction INCB adds 1 to the string length counter in Accumulator B.
CLRB initializes this counter to zero before the loop begins. You must remember to
initialize variables before using them in a loop; failure to do so is a common program­
mmg error.
This loop does not terminate by decrementing a counter to zero. In fact, the com­
puter will simply continue examining characters until it finds a carriage return.
Obviously, this creates problems if the string, because of an error or omission, does not
contain a carriage return. It is good programming practice to place a maximum count
in a loop like this, even though it does not appear to be necessary. What happens if you
use the example program on a string that does not contain a carriage return?

Rearranging the Program

By rearranging the logic and changing the initial conditions, you can decrease
the execution time of the program. If we rearrange the flowchart so that the program
increments the string length before it checks for the carriage return, only one branch
instruction is necessary instead of two.

Flowchart:

POINTER= 0041
LENGTH= -1

LENGTH=
LENGTH + 1

Yes

POINTER=
(0040) = LENGTH
POINTER+ 1
Character-Coded Data 6-5

Program 6-1 b:
0000 C6 FF LDB #$FF STRING LENGTH = -1
0002 BE 0041 LDX ll$41 POINT TO START OF STRING
0005 86 OD LDA li$0D GET ASCII CARRIAGE RETURN
* (STRING TERMINATOR)
0007 sc CHKCR INCB ADD 1 TO STRING LENGTH
0008 A1 80 CMPA ,X+ IS NEXT CHARACTER
* A CARRIAGE RETURN?
OOOA 26 FB BNE CHKCR NO, KEEP CHECKING
oooc D7 40 STB $40 YES, SAVE STRING LENGTH
OOOE 3F SWI

This program, like the previous one, has no provision for stopping if a maximum
string length is reached before a carriage return is found.

6-2. FIND FIRST NON-BLANK CHARACTER

Purpose: Search a string of ASCII characters for a non-blank character. The string starts
in memory location 0042. Place the address of the first non-blank character in
memory locations 0040 and 0041 (most significant bits in 0040).
A blank character is exactly the same as a space, and is referred to as' li 'or 'SP'; a
blank character in ASCII is 2016 .

Sample Problem:

a. (0042) 37 '7'

Result: (0040)
(0041)
��} since memory location 0042 contains a non-blank character

b. (0042) 20 SP
(0043) 20 SP
(0044) 20 SP
(0045) 46 T
(0046) 20 SP

Result: (0040)
(0041)
��} since the three previous memory locations all contain blanks

Flowchart:

POINTER = 0042

No

POINTER= (0040): (0041) =


POINTER+ 1 POINTER
6-6 6809 Assembly Language Programming

Program 6-2:
0000 8E 0042 LDX # $4 2 POINT TO START OF STRING
0003 86 20 LDA
#I GET ASCII SPACE FOR COMPARISON
0005 Al 80 CHBLK CMPA ,X+ IS CHARACTER AN ASCII SPACE?
0007 27 FC BEQ CHBLK YES, KEEP EXAMINING CHARS
0009 30 lF LEAX -1, X NO, MOVE POINTER BACK ONE
OOOB 9F 40 STX $40 SAVE ADDRESS OF FIRST
* NON-BLANK CHARACTER
OOOD 3F SWI

Note the use of an apostrophe (') or single quotation mark before an ASCII
character.
Looking for spaces in strings is a common task in microprocessor applications.
Programs often reduce storage requirements by removing spaces that only serve to
increase readability or fit data into particular formats. Storing and transmitting extra
space characters obviously wastes memory, communications capacity, and processor
time. However, operators find it easier to enter data and programs when the computer
accepts extra spaces; the entry is then said to be in free, rather than fixed, format. One
of the most popular uses of microcomputers is to convert data and commands between
the forms that are easy for people to handle and the forms that are most efficient for
computers and communications systems.
The LEA instruction has many uses in 6809 programming. This instruction
calculates an effective address using one of the indexed addressing modes (see
Chapter 22 for a complete description), but then simply places that address in an
index register or stack pointer rather than using it to transfer data. The effective
address is available for later use and need not be recalculated. This can save execution
time. Remember that instructions using most of the indexed addressing modes, particu­
larly the more complicated modes, require many additional clock cycles to execute.
Furthermore, the programmer can later use the effective address in any of the indexed
modes, thus providing additional levels of indirection and more flexibility.
LEA can perform many simple functions. For example, you can (as in Program
6-2) subtract 1 from Index Register X with the instruction
LEAX -l,X

In this case, the processor first calculates the effective address by adding -1 to the con­
tents of Index Register X. It then places that result back in Index Register X. A more
complex example is one that adds 8 to User Stack Pointer U and places the result in
Index Register Y; the required instruction is

U;AY 8 ,ll

The earlier 6800 microprocessor had no autoincrementing or autodecrementing.


Instead, the instruction DEX subtracted 1 from Index Register X and INX added 1 to it.
The 6809 assembler will accept DEX and INX (as well as DEY, INY, DES, and INS)
and will generate the appropriate LEA instructions. The use of these operation codes
saves typing and makes programs somewhat clearer (and more familiar to 6800 pro­
grammers), but we will stick with the actual 6809 operation codes.
The autoincrement in CMPA ,X+ provides us with a fast and simple way to step
to the next character. However, it is a bit of a nuisance once we have found the first non­
blank character, since it has then added l to the address that we want to save. We must
explicitly subtract the extra 1 with the instruction LEAX -1 ,X. This instruction would
not be necessary if we were working backwards instead of forward, since the 6809
autodecrements before using the address. As we noted earlier, however, you must start
the index register one beyond the end of the array when autodecrementing.
Character-Coded Data 6-7

6-3. REPLACE LEADING ZEROS WITH BLANKS

Purpose: Edit a string of numeric characters by replacing all leading zeros with blanks.
The string starts in memory location 0041; assume that it consists entirely of
ASCII-coded decimal digits. Memory location 0040 contains the length of the
string in bytes.

Sample Problems:

a. {0040) 02 Length of the string in bytes

{004 1 ) 36 ' 6'


10042) 39 '9'

The program leaves the string unchanged. since the leading digit is not zero

b {0040) 08 Length of the string in bytes

1004 1 ) 30 '0'
{0042) 30 ·o·
{0043) 38 '8'

Result: 1004 1 ) = 20 SP
(0042) = 20 SP

The program replaces the two leading zeros with ASCII spaces.

The printed result would be " 8 ... " instead of "008 .... "

Flowchart:

COUNT= (0040)
POINTER = 0041

POINTER=
POINTER+ 1
{POINTER- 1) =
SP I= 2016)
COUNT=
COUi-.JT- 1
6-8 6809 Assembly Language Programming

Program 6-3:

0000 8 6 30 LDA t. 0 GET ASCII ZERO FOR COMPARISON


0002 C 6 20 LDB #. GET ASCII SPACE FOR STORAGE
0004 8E 0041 LDX t$41 POINT TO START OF ARRAY
0007 A1 80 CHKZ CMPA ,X+ IS LEADING DIGIT ZERO?
0009 26 06 BNE DONE NO, DONE
OOOB E7 lF STB -1,X YES, REPLACE ZERO WITH SPACE
OOOD OA 40 DEC $40
OOOF 26 F6 BNE CHKZ
0011 3F DONE SWI

Editing strings of decimal digits to improve their appearance is a common task


in microprocessor programs. Typical procedures include the removal of leading zeros,
justification, the addition of signs ( + or -) and other delimiters or symbols for units
(such as$,¢%, or#), and rounding. The program should print numbers in the form
that the user wants and expects; results like "0006," "$27.34382," or "135000000"
are annoying and difficult to interpret.
This loop has two exits - one if the processor finds a non-zero digit and the other
if it works through the entire string. In an actual application, you would have to be care­
ful to leave one zero if all the digits in the string are zero. How would you modify the
program to do this?
We have assumed that the length of the string (the contents of location 0040) will
be greater than zero. What will happen if (0040) = 00 when the program starts execu­
tion?
The instruction STB -1, X places an ASCII space (2016) in a memory location that
previously contained ASCII zero. Here again we need the offset of -1 to make up for
the + 1 that was added to Index Register X by the instruction CMPA ,X+.
We have assumed that all the digits in the string are in the ASCII form� that is, the
digits used are 3016 through 3916 rather than the ordinary decimal 0 to 9. Converting a
digit from BCD to ASCII is simply a matter of adding 3016 (ASCII zero), while convert­
ing from ASCII to decimal involves subtracting the same number.
You can place a single ASCII character in a 6809 assembly language program
by preceding it with an apostrophe (').You can place a string of ASCII characters in
program memory by using the FCC (Form Constant Characters) directive on the 6809
assembler. There are two acceptable forms of this directive:

EMSG FCC S,ERROR

EMSG FCC /ERROR/

In the first form, the user must specify the number of characters, followed by a comma
and the character string. In the second form, the user may place any single character
delimiter (we will always use /) at both ends of the string.
Each ASCII digit requires eight bits of storage, as compared to four bits for a
BCD digit. Therefore, ASCII is a relatively expensive format in which to store or
transmit numerical data.

6-4. ADD EVEN PARITY TO ASCII CHARACTERS

Purpose: Add even parity to a string of 7-bit ASCII characters. The length of the string
is in memory location 0040 and the string itself begins in memory location
0041. Add even parity to each character by setting bit 7 if that makes the num­
ber of 1 bits in the byte even.
Character-Coded Data 6-9

Sample Problem:

(0040) 06 Length of string

l0041) 31 = 0011 0001


(0042) 32 = 0011 0010
(0043) 33 = 0011 0011
(0044) 34 = 0011 0100
(0045) 35 = 0011 0101
(0046) 36 = 0011 0110

Result: (0041) B1 = 1011 0001


(0042) B2 = 1011 0010
(0043) 33 = 0011 0011
(0044) B4 = 1011 0100
(0045) 35 = 0011 0101
(0046) 36 0011
= 0110

Flowchart:

POINTER = 0041
COUNT = (0040)

BIT COUNT= 0
OATA= (POINTER) Set MSB of
POINTER= (POINTER - 1) to 1
POINTER+ 1

COUNT=
COUNT -1

BIT COUNT=
BIT COUNT+ 1

Shift DATA left one


bit arithmetically
(LSB = 0)
6-10 6809 Assembly Language Programming

Program 6-4:

0000 8E 0041 LOX t$41 POINT TO START OF DATA BLOCK


0003 A6 80 GTBYTE LOA ,X+ GET A BYTE OF DATA
0005 SF CLRB BIT COUNT = ZERO INITIALLY
0006 48 CHBIT ASLA SHIFT A DATA BIT TO CARRY
0007 C 9 00 ADCB to IF BIT IS 1, INCREMENT
*
BIT COUNT
0009 40 TSTA KEEP COUNTING UNTIL
*
DATA BECOMES ZERO
OQOA 26 FA BNE CHBIT
oooc 54 LSRB DID DATA HAVE EVEN NUMBER
*
OF I 1 I BITS?
0000 24 06 BCC NEXTE
OOOF A6 1F LOA -1,X NO, SET EVEN PARITY BIT
*
IN DATA
0011 8A 80 ORA 1%10000000
0013 A7 1F STA -1,X
0015 OA 40 NEXTE DEC $40
0017 26 EA BNE GTBYTE
0019 3F SWI

Parity provides a simple means of checking for errors on noisy communications


lines. If the transmitter sends parity along with the actual data, the receiver can then
compare that parity with the parity of the data that it receives. If the two parities do not
agree, the receiver can request retransmission of the data. If there is a single bit in error,
the two parities will never agree, since the number of 'l' bits in the data will clearly
change from even to odd or odd to even. However, two wrong bits will just as obviously
result in the same parity as the original data. Thus we say that parity detects single but
not double bit errors. Of course, single bit errors are usually more common than are
double bit errors, so this is not a major drawback.
A more serious problem with parity is that it provides no way to correct errors.
An error in any bit position will produce the same change in parity, so the receiver can­
not determine which bit is wrong. More advanced coding techniques provide for error
correction as well as error detection. Parity, however, is easy to calculate and ade­
quate in situations in which retransmission of data is tolerable.
The procedure for calculating parity is to count the number of '1' bits in each
byte of data. If that number is odd, the program sets the most significant bit {MSB)
of the data byte to 1 to make the parity even. An advantage of ASCII is that it leaves bit
7 of each byte for parity; EBCDIC does not, since it is an 8-bit code.
ASL clears the least significant bit of the accumulator or memory location that it is
shifting. Therefore, the result of a series of ASL instructions will eventually be zero,
regardless of the original data (try it!). The bit counting procedure in the example pro­
gram does not use a counter for termination since it stops as soon as all the remaining
data bits are zero. This procedure is simple and reduces execution time in most cases.
The program sets the MSB of the data byte to '1' by logically ORing it with a pat­
tern that has a '1' in its most significant bit and zeros elsewhere. Logically ORing a bit
with '1' always produces a result of '1', while logically ORing a bit with '0' leaves the
bit unchanged.
Character-Coded Data 6-11

6-5. PATTERN MATCH

Purpose: Compare two strings of ASCII characters to see if they are the same. The
length of the strings is in memory location 0041; one string starts in memory
location 0042 and the other in memory location 0052. If the two strings
match, clear memory location 0040; otherwise, set memory location 0040 to
all ones (FF 11,).

Sample Problems:
a. (0041) 03 Number of characters in each string

(0042) 43 'C'
(0043) 41 'A'
(0044) 54 T

(0052) 43 ·c·
(0053) 41 'A'
(0054) 54 'T'

Result: (0040) 00, since the two strings are the same

b. (0041) 03 Number of characters in each string

(0042) 52 'A'
(0043) 41 'A'
(0044) 54 T

(0052) 43 ·c·
(0053) 41 'A'
(0054) 54 ·r

Result: (0040) FF. since the first characters in the


strings differ

Note: The matching process ends as soon as the CPU finds a difference - the rest of the
strings need not be examined.

Program 6-5:

0000 86 FF LDA #SFF MARK = F F HEX FOR INEQl}ALITY


0002 97 40 STA $40
0004 8E 0042 LDX 11$42 POINTER1 START OF STRING 1
=

0007 108E 0052 LDY #$52 POINTER2 START OF STRING 2


=

0008 D6 41 LDB $41 COUNT LENGTH OF STRINGS


=

OOOD A6 80 CHBYTE LDA ,X+ GET A CHAR ACTER FROM STRING 1


OOOF A1 AO CMPA ,Y + DOES IT MATCH WITH STRING 2?
DOll 26 05 BNE DONE NO, DONE
0013 SA DECB
0014 26 F7 BNE CHBYTE CHECK NEXT PAIR IF ANY LEFT
0016 OF 40 CLR $40 IF NONE ARE LEFT, MARK =
0
*
FOR EQUALITY
0018 3F DONE SWI

Matching strings of ASCII characters is an essential part of recognizing names


or commands, identifying variables or operation codes in assemblers and compilers,
accessing named files, and many other tasks.
Program 6-5 uses different index registers for the two strings, so they can be
located anywhere in memory. We could use a single index register if the two strings
were always located a constant distance apart. If that distance were DIST, the com­
parison procedure would be

CHBYTE LDA , X+
CMPA DIST-l,X
6-12 6809 Assembly Language Programming

Program 6-5 autoincrements both Index Register X and Index Register Y. Note
that LOY requires a 2-byte operation code, while LOX requires only a 1-byte code. In
fact, the operation code for LOY is the operation code for LOX preceded by the byte
1016. The prefix byte 1016 apparently tells the 6809 processor that this instruction falls in
a special group and the next byte will actually describe the operation to be performed.
We could replace CLR $40 with INC $40 or STB $40 (why?). Which of these
alternatives executes faster? Which do you think is clearer?

Flowchart:

POINTER1 = 0042
POINTER2 = 0052
COUNT = (0041)
MARK= FF1
6

POINTER1 =
POINTER1 + 1
POINTER2 =

POINTER2 + 1
COUNT=
COUNT - 1

MARK= 0

(0040) = MARK
Character-Coded Data 6-13

PROBLEMS

6-1. LENGTH OF A TELETYPEWRITER MESSAGE

Purpose: Determine the length of an ASCII message. All characters are 7-bit ASCII
with MSB = 0. The string of characters in which the message is em bedded
starts in memory location 0041. The message itself starts with an ASCII STX
character (02 16) and ends with ETX (03 16). Place the length of the message
(the number of characters between the STX and the ETX but including
neither) into memory location 0040.

Sample Problem:

(0041) 40
(0042) 02 STX
47 'G'
(0043)
(0044) 4F '0'
(0045) 03 ETX

Result: (0040) 02, since there are two characters between


the STX in location 0042 and ETX in
location 0045

6-2. FIND LAST NON-BLANK CHARACTER

Purpose: Search a string of ASCII characters for the last non-blank character. The string
starts in memory location 0042 and ends with a carriage return character
(ODit,). Place the address of the last non-blank character in memory locations
0040 and 0041 (most significant bits in 0040).

Sample Problems:

a. (0042) 37 '7 '


(0043) OD CR

Result: (0040) 00 } since the last (and only) non-blank


(0041) 42 character is in memory location 0042

b. (0042) 41 'A'
(0043) 20 SP
(0044) 48 'H'
(0045) 41 'A'
(0046) 54 ' T'
(0047) 20 SP
(0048) 20 SP
(0049) OD CR

Result: (0040) 00
(0041) 46
6-14 6809 Assembly Language Programming

6-3. TRUNCATE DECIMAL STRING TO INTEGER FORM

Purpose: Edit a string of ASCII characters by replacing all digits to the right of the
decimal point with ASCII blanks (2016). The string starts in memory location
0041 and is assumed to consist entirely of ASCII decimal digits and a possible
decimal point (2E16). The length of the string is in memory location 0040. If
no decimal point appears in the string, assume that the decimal point is
implicitly at the far right.

Sample Problems:

a. (0040) 04 Length of string

(0041) 37 '7'
(0042) 2E
. .

(0043) 38 '8'
(0044) 31 • 1.

Result: (0041) 37 '7'


(0042) 2E
, ,

(0043) = 20 SP
(0044) 20 SP

b. (0040) 03 Length of string

(0041) 36 '6'
(0042) 37 ' 7'
(0043) 31 .1.

Result: Unchanged, as number is assumed to be 671

6-4. CHECK EVEN PARITY IN ASCII CHARACTERS

Purpose: Check even parity in a string of ASCII characters. The length of the string is in
memory location 0041, and the string itself begins in memory location 0042. If
the parity of all the characters in the string is correct, clear memory location
0040; otherwise, place all ones (FF 16) into memory location 0040.

Sample Problems:

a. (0041) 03 Length of string

(0042) 81 = 1011 0001


(0043) 82 = 1011 0010
(0044) 33 = 0011 0011

Result: (0040) 00, since all the characters have even parity

b. (0041) 03 Length of string

(0042) 81 = 1011 0001


(0043) 86 = 1011 0110
(0044) 33 = 0011 0011

Result: (0040) FF. since the character in memory location


0043 does not have even parity
Character-Coded Data 6-15

6-5. STRING COMPARISON

Purpose: Compare two strings of ASCII characters to see which is larger (that is, which
follows the other in alphabetical ordering). The length of the strings is in
memory location 0041; one string starts in memory location 0042 and the
other in memory location 0052. If the string starting in memory location 0042
is greater than or equal to the other string, clear memory location 0040; other­
wise, set memory location 0040 to all ones (FF 10).

Sample Problems:

a. (00411 03 Length of each string

(00421 43 · c ·

(00431 41 'A'
(00441 54 ' T'

(00521 42 'B'
(00531 51 'A'
(00541 54 'T'

Result: (00401 00. since CAT is 'larger' than BAT

b. (00411 03 Length of each string

(00421 43 ·c ·

(00431 41 'A'
(00441 54 T

(00521 43 · c ·

(00531 41 ' A'


(00541 54 'T '

Result: (00401 00, since the two strings are equal

c. (00411 03 Length of each string

(00421 43 'C '


(00431 41 ' A'
(00441 54 'T '

(00521 43 · c ·

(00531 55 · u ·

(00541 54 ' T'

Result (00401 FF, since CUT is 'larger' than CAT


7
Code Conversion

Code conversion is a continual problem in microcomputer applications. Peri­


pherals provide data in ASCII, BCD, or various special codes. The microcomputer
must convert the data into some standard form for processing. Output devices may
require data in ASCII, BCD, seven-segment, or other codes. Therefore, the
microcomputer must convert the results to the proper form after it completes the pro­
cessing.
There are several ways to approach code conversion:

1. Some conversions can easily be handled by algorithms involving arithmetic


or logical functions. The pro gram may, however, have to handle special cases
separately.
2. More complex conversions can be handled with lookup tables. The lookup
table method requires little programmin g and is easy to apply. However, the
table may occupy a large amount of memory if the ran ge of input values is
large.
3. Hardware is readily available for some conversion tasks. Typical examples
are decoders for BCD to seven-se g ment conversion and Universal
Asynchronous Receiver/Transmitters (UARTs) for conversion between
parallel (ASCII) and serial (teletypewriter) formats.

In most applications, the program should do as much as possible of the code con­
version work. This approach reduces parts count and power dissipation, saves board
space, and increases reliability. Furthermore, most code conversions are easy to pro­
gram and require little execution time.
7-2 6809 Assembly Language Programming

PROGRAM EXAMPLES

7-1. HEXADECIMAL TO ASCII

Purpose: Convert the contents of memory location 0040 to an ASCII character.


Memory location 0040 contains a single hexadecimal digit (the four most sig­
nificant bits are zero). Store the ASCII character in memory location 0041.

Sample Problems:
a. (0040) oc

Result: (0041) 43 ·c·

b. (0040) 06

Result: (0041) 36 '6'

Program 7-1 :

0000 96 40 LDA $40 GET DATA


0002 81 09 CMPA J9 IS DATA 9 OR LESS?
0004 23 02 BLS ASCZ
0006 88 07 ADDA t'A-'9-1 NO, ADD OFFSET FOR LETTERS
0008 8B 30 ASCZ ADDA t'O CONVERT DATA TO ASCII
OOOA 97 41 STA $41 STORE ASCII DATA
oooc 3F SWI

The basic idea of this program is to add ASCII 0 (3016) to all the hexadecimal
digits. This addition converts the digits 0 through 9 to ASCII correctly. However, the
letters A through F do not follow immediately after the digit 9 in the ASCII code;
instead, there is a break between the ASCII code for 9 (3916) and the ASCII code for A
(4116), so the conversion must add a further constant to the nondecimal digits (A, B,
C, D, E, and F) to account for the break. The first ADD instruction does this by adding
'A -'9- l to Accumulator A. Can you explain why the extra factor for letter digits
has the value 'A- '9- 1?
We have used the ASCII forms for the addition factors in the source program; a
single quotation mark (apostrophe) before a character indicates the ASCII equivalent.
We have also left the offset for the letters as an arithmetic expression to make its mean­
ing as clear as possible. The extra assembly time is a small price to pay for the great
increase in clarity. A routine like this is necessary in many applications; for example,
monitor programs must convert hexadecimal digits to their ASCII equivalents in order
to display the contents of memory locations in hexadecimal on an ASCII printer or CRT
display.
The following program, described by Allisont, provides a less obvious conver­
sion method that requires no conditional branches.

0000 96 40 LDA $40 GET HEX DIGIT


0002 8B 90 ADDA t$90 DECIMAL ADD 90 BCD
0004 19 DAA
0005 89 40 ADCA t$40 DECIMAL ADD 40 BCD + CARRY
0007 19 DAA
0008 97 41 STA $41
OOOA 3F SWI

Try this program on some hexadecimal digits. Can you explain why it works?
Code Conversion 7-3

Flowchart:

DATA= (0040)

DATA=
DATA+ ASCII A
- ASCII9- 1

RESULT=
DATA+ ASCII 0

(004 1 ) = RESULT

7-2. DECIMAL TO SEVEN-SEGMENT

Purpose: Convert the contents of memory location 0041 to a seven-segment code in


memory location 0042. If memory location 0041 does not contain a single
decimal digit, clear memory location 0042.
Figure 7-1 illustrates the seven-segment display and our representation of it as a
binary code. The segments a·re usually assigned the letters a through g as shown in
Figure 7-l. We have organized the seven-segment code as shown: segment g is in bit
position 6, segment f in bit position 5, e in bit position 4, and so on. Bit position 7 is
always zero. The segment names are standard, but the assignment of segments to bit
positions is arbitrary; in actual applications, this assignment is a hardware function.
The table in Figure 7-l is a typical example of those used to convert decimal num­
bers to seven-segment code; it assumes positive logic, that is, l = on and 0 = off. Note
that the table uses 70 for 6 rather than the alternative 7C (top bar off) to avoid confu­
sion with lower-case b, and 6F for 9 rather than 67 (bottom bar off) for symmetry with
the 6.
7-4 6809 Assembly Language Programming

Sample Problems:
a. (0041) 03

Result: (0042) 4F

b. (0041) 28

Result: (0042) 00

Program 7-2:
0000 SF CLRB GET ERROR CODE
*
TO BLANK DISPLAY
0001 96 41 LOA $41 GET DATA
0003 81 09 CMPA J9 IS DATA A DECIMAL DIGIT?
0005 22 05 BHI DONE NO, KEEP ERROR CODE
0007 8E 0020 LOX ISSEG YES, GET SEVEN-SEGMENT
*
CODE FROM TABLE
OOOA E6 86 LOB A,X
oooc 07 42 DONE STB $4 2
OOOE 3F SWI
*

0020 ORG $20


*

0020 3F SSEG FCB $3F,$06,$5B,$4F,$66


0021 06
0022 5B
0023 4F
0024 66
0025 60 FCB $6D,$7D,$07,$7F,$6F
0026 70
0027 07
0028 7F
0029 6F

The program calculates the memory address of the seven-segment code by


adding an index - the digit to be converted - to the base address of the seven-seg­
ment code table. This procedure is known as a "table lookup." The addition does not
require any explicit instructions, since the processor performs it automatically as part of
the calculation of the effective address in the indexed addressing mode. We have used
the accumulator indexed mode in which the effective address is the sum of Accumulator
A and Index Register X.
The assembler directive FCB (Form Constant Byte) places constant byte-length
data in program memory. Such data may include tables, headings, error messages, prim­
ing messages, format characters, thresholds, and mathematical constants. The label
attached to an FCB pseudo-operation is assigned the value of the address in which the
assembler places the first byte of data.
The assembler assigns the data from the FCB directive to consecutive memory
addresses, with no changes other than numerical conversions. One FCB directive can fill
many bytes of memory; all the programmer must do is separate the entries with com­
mas.
We have left some memory space between the program and the table to allow for
later additions and to emphasize that they need not be located consecutively. In fact, we
could place the table anywhere in memory.
Tables are a simple, fast, and convenient approach to code conversion problems
that are more complex than our hexadecimal-to-ASCII example. The required lookup
tables simply contain all the possible results organized by input value; that is, the first
entry is the code for the number zero and so on.
Seven-segment displays provide recognizable forms of the decimal digits and a
few letters and other characters. They are relatively inexpensive and easy to handle
Code Conversion 7-5

with 8-bit microprocessors. However, many people find seven-segment coded digits
somewhat difficult to read, although their widespread use in calculators and watches
has made them more familiar.

Flowchart:

DATA= (004 1 )

Yes

RESULT =

RESULT= 0
(SSEG + DATA)

(0042) = RESULT

Note that the addition of base address (SSEG) and index (DATA) produces the
address that contains the answer.

Digit Code
a

b
0 3F

.I
1 06
2 56
3 4F ------
4 66

el_g_
5 60 c
6 70
7 07
8 7F d
9 6F

7 6 5 4 3 2 0 �-
.... - Bit Number

Figure 7-1. Seven-Segment Arrangement


7-6 6809 Assembly Language Programming

7-3. ASCII TO DECIMAL

Purpose: Convert the contents of memory location 0040 from an ASCII character to a
decimal digit and store the result in memory location 0041. If the contents of
memory location 0040 are not the ASCII representation of a decimal digit, set
the contents of memory location 0041 to FF16.

Sample Problems:

a. (0040) 37. 7'

Result: (0041) 07

b. (0040) 55 an invalid code. since it is not an


ASCII decimal digit

Result: (0041) = FF

Flowchart:

DATA = (0040)

Yes

Yes

RESULT=
RESULT= FF16
DATA- ASCII 0

(004 1) = RESULT
Code Conversion 7-7

Program 7-3:
0000 C6 FF LDB #$FF GET ERROR MARKER
0002 96 40 LDA $40 GET DATA
0004 80 30 SUBA 'I 0 IS DATA BELOW ASCII ZERO?
0006 25 06 BLO DONE YES, NOT A DIGIT
0008 81 09 CMPA #9 IS DATA ABOVE ASCII NINE?
OOOA 22 02 BHI DONE YES, NOT A DIGIT
oooc lF 89 TFR A,B SAVE VALID DECIMAL DIGIT
OOOE D7 41 DONE STB $41 SAVE DIGIT OR ERROR MARKER
0010 3 F SWI

This program handles ASCII characters just like ordinary numbers. Since ASCII
assigns an ordered sequence of codes to the decimal digits, we can identify an ASCII
character as a digit by determining if it falls within the proper range of numerical
values. We could use the ASCII ordering similarly to determine if a character is in a par­
ticular group of letters or symbols, such as A through F. This approach assumes
detailed knowledge of a particular code and would not necessarily be valid for other
codes.
Subtracting ASCII 0 (3016) from any ASCII decimal digit gives the decimal
value of that digit. An ASCII character is a decimal digit if its value lies between 3016
and 391 6 (including the endpoints); how would you determine if an ASCII character is a
valid hexadecimal digit? ASCII-to-decimal conversion is necessary in applications in
which decimal data is entered from an ASCII device such as a teletypewriter or terminal.
The program performs one comparison - to the lower limit - with an actual
subtraction (SUBA =lf'O), since the subtraction is necessary for the ASCII-to-decimal
conversion. It performs the other comparison with an implied subtraction (CMPA =lf9)
to avoid destroying the possible decimal digit in Accumulator A. Implied subtractions
(CMP) are far more common than actual subtractions (SUB) in programs, since the
numerical value of the result is seldom of interest.
The instruction TFR can transfer the contents of any 8- or 16-bit register to any
other 8- or 16-bit register. TFR copies the source register into the destination register;
the source register is not changed. The only restriction is that the source and destina­
tion registers must be the same length (both eight bits long or both 16 bits long). TFR
instructions always require one byte besides the operation code; the high-order four bits
of that byte specify the source register and the low-order four bits specify the destination
register. See the description of TFR in Chapter 22 for more details.
One special use of TFR is to load the direct page register, since there is no LD
instruction for that register. A typical sequence that loads the direct page register with
the constant value PGNO is:

LDA tPGNO DIRECT PAGE = PGNO


TFR A,DP

An alternative to TFR is EXG (Exchange Registers). This instruction swaps


the source and destination registers, thus preserving both values. For example, the
following sequence will load the direct page register with the constant PGNO and save
the old direct page register in memory location OLDPG.

LDA tPGNO DIRECT PAGE = PGNO


EXG A,DP
STA OLDPG SAVE OLD DIRECT PAGE NUMBER
7-8 6809 Assembly Language Programming

7-4. BCD TO BINARY

Purpose: Convert two BCD digits in memory locations 0040 and 0041 to a binary num­
ber in memory location 0042. The most significant BCD digit is in memory
location 0040.

Sample Problems:
a. (0040) 02
(0041) 09

Result: (0042) 10
16

b. (0040) 07
(0041) 01

Result: (0042) 47 16

Program 7-4:

0000 96 40 LOA $40 GET MOST SIGNIFICANT DIGIT


0002 C6 OA LOB 110 MULTIPLY BY 10
0004 30 MUL
0005 DB 41 ADDB $41 ADD LEAST SIGNIFICANT DIGIT
0007 07 42 STB $42 STORE BINARY EQUIVALENT
0009 3F SWI

The MUL instruction performs an unsigned 8-bit by 8-bit multiplication of the


contents of Accumulators A and B; the result occupies the double accumulator D,
with the high-order byte in A.
In this case, we know that the result is 9016 or less, so only the low-order eight bits
of the product (in Accumulator B) are relevant.
Converting BCD entries to binary saves storage and simplifies calculations.
BCD numbers require about 20% more memory space than do binary numbers; for
example, representing the numbers 0 to 999 requires three BCD digits - 12 bits - but
only 10 bits in binary since 210 = 1024:::::::1000.
Since MUL requires 11 clock cycles, it is sometimes faster to multiply by small
decimal numbers using repeated additions.2 The instruction ASLA multiplies the con­
tents of Accumulator A by 2, so multiplications by powers of 2 can be implemented as
arithmetic shifts.

7-5. BINARY NUMBER TO ASCII STRING

Purpose: Convert the 8-bit binary number in memory location 0041 to eight ASCII
characters (each either ASCII 0 or ASCII 1) in memory locations 0042
through 0049. (Place the most significant bit in location 0042.)

Sample Problem:
(0041) 02 = 1101 0010

Result: (0042) 31 "1'


(0043) 31 '1'
(0044) 30 ' 0'
(0045) 31 0,'
(0046) 30 ' 0'
(0047) 30 '0'
(0048) 31 '1"
(0049) 30 '0'
Code Conversion 7-9

Flowchart:

DATA: (0041)
POINTER : 0042

(POINTER): ASCII 0
Shift OATA right
one bit

(POINTER) : ASCII 1
( : (POINTER) + 1)

POINTER=
POINTER+ 1

Program 7-5:

0000 C6 30 LOB I I0 GET ASCII ZERO


* TO STORE IN STRING
0002 96 41 LD� $4 1 GET DATA
0004 8E 0042 LOX t$42 POINT TO START OF ASCII STRING
0007 E7 80 CONY STB 'X+ STORE ASCII ZERO IN STRING
0009 48 LSLA IS BIT ACTUALLY 1?
OOOA 24 02 BCC COUNT
oooc 6C 1F INC - 1,X YES, MAKE STRING ELEMENT
* INTO ASCII ONE
OOOE 8C 004A COUNT CMPX 1$4 A CHECK FOR END OF CONVERSION
00 1 1 26 F4 BNE CONY
0013 3F SWI

Since the decimal digits form a sequence in ASCII, ASCII 1 = ASCII 0 + 1.


The CMP(X/Y /U/8/D) instructions compare 16-bit quantities. The flags are
set according to the result of the entire 16-bit subtraction, even though the
microprocessor actually performs it eight bits at a time. CMPX takes two cycles longer
7-10 6809 Assembly Language Programming

than CMPA or CMPB, while CMPD, CMPY, CMPS, and CMPU all require two-byte
operation codes and take three cycles longer than CMPA or CMPB.
Single-operand instructions like INC, DEC, COM, or ASL can all use any of
the indexed addressing modes. Be careful of the fact that such instructions affect
memory locations (the effective address), not the specified index register or stack
pointer (except through autoincrementing or autodecrementing). For example, CLR
,X+ clears the byte of memory located at the address in Index Register X (and
autoincrementsX)� it does not clear Index Register X.
Assembly-time arithmetic often comes in handy for performing address com­
parisons. If, for example, we established that the ASCII binary string started in the loca­
tion named BINSTR, the required comparison instruction would be:

COUNT CMPX IBINSTR+8

This form is clearer and easier to change than is an explicit address. Furthermore, the
programmer does not have to perform any hexadecimal arithmetic.
Binary-to-ASCII conversion is necessary if numbers are to be printed in binary
on an ASCII device. Binary outputs are helpful in debugging and testing when each
bit has a separate meaning; typical examples are inputs from a set of panel switches or
outputs to a set of LEOs. If the programmer can only obtain the value in some other
number system (such as octal or hexadecimal), he or she must perform an error-prone
hand conversion to check the bits.

PROBLEMS

7-1. ASCII TO HEXADECIMAL

Purpose: Convert the contents of memory location 0040 to a hexadecimal digit and
store the result in memory location0041. Assume that memory location 0040
contains the ASCII representation of a hexadecimal digit (7 bits with MSB 0).

Sample Problems:

a. (0040) 43 ·c·

Result: (0041) oc

b. �o4rn 36 '6'

Result: (004 1) 06

7-2. SEVEN-SEGMENT TO DECIMAL

Purpose: Convert the contents of memory location 0040 from a seven-segment code to
a decimal number in memory location 0041. If memory location 0040 does not
contain a valid seven-segment code, set memory location 0041 to FF16• Use
the seven-segment table given in Figure 7-1 and try to match codes.
Code Conversion 7-11

Sample Problems:

a. (0040) 4F

Result: (0041) 03

b. (0040) 28

Result: (0041) FF

7-3. DECIMAL TO ASCII

Purpose: Convert the contents of memory location 0040 from a decimal digit to an
ASCII character and store the result in memory location 0041. If the number
in memory location 0040 is not a decimal digit, set the contents of memory
location 0041 to an ASCII space (2016).

Sample Problems:

a. Wo4m 07

Result: (0041) 37 '7'

b. (0040) 55

Result: (0041) 20 SP

7-4. BINARY TO BCD

Purpose: Convert the contents of memory location 0040 to two BCD digits in memory
locations 0041 and0042 (most significant digit in 0041). The number in
memory location 0040 is unsigned and less than 100.

Sample Problems:

a. {0040) 1D

Result: (0041) 02
(0042) 09

b. (0040) 47

Result: (0041) 07
(0042) 01

7-5. ASCII STRING TO BINARY NUMBER

Purpose: Convert the eight ASCII characters in memory locations 0042 through 0049 to
an 8-bit binary number in memory location 0041 (the most significant bit is in
0042). Clear memory location 0040 if all the ASCII characters are either
ASCII 1 or ASCII 0 and set it to FF16 otherwise.
7-12 6809 Assembly Language Programming

Sample Problems:

a. (0042) 31 '1'
(0043) 31 '1.
(0044) 30 ·o·
(0045) 31 '1'
(0046) 30 ·o·
(0047) 30 ·o·
(0048) 31 '1'
(0049) 30 ·o·

Result: (0041) D2 = 1101 0010


(0040) 00

b. Same as above except:


(0045) 37 '7'

Result: (0040) = FF

REFERENCES

1. D. R. Allison, "A Design Philosophy for Microcomputer Architectures," Com­


purer, February 1977, pp. 35-41. This is an excellent article which we highly recom­
mend.

2. Other BCD-to-binary conversion methods are discussed in J. A. Tabb and M. L.


Roginsky, "Microprocessor Algorithms Make BCD-Binary Conversions Super­
fast," EDN, January 5, 1977, pp. 46-50, and in J. B. Peatman, Microcomputer-Based
Design, (New York: McGraw-Hill, 1977), pp. 400-406.
8
Arithmetic Problems

Most arithmetic in microprocessor applications consists of multi-byte binary or


decimal manipulations. A decimal correction (decimal adjust) or some other means
for performing decimal arithmetic is frequently the only arithmetic instruction pro­
vided beyond binary addition and subtraction. The 6809 microprocessor represents a
significant advance over earlier devices in that, besides the operations mentioned, it
has instructions for 16-bit addition and subtraction, 8-bit unsigned multiplication,
and sign extension.
Multiple-precision binary arithmetic requires simple repetitions of the basic
single-byte instructions. The Carry flag transfers information between bytes. Add
with Carry and Subtract with Carry (Borrow) are the instructions that use the informa­
tion from the previous arithmetic operations. You must be careful to clear the Carry
before operating on the least significant bytes, since there is obviously never any carry
into them or borrow from them.
Decimal arithmetic is a common enough task for microprocessors that most
have special instructions for this purpose. These instructions may either perform
decimal operations directly or correct the results of binary operations to the proper
decimal forms. Decimal arithmetic is essential in such applications as point-of-sale ter­
minals, calculators, check processors, order entry systems, and banking terminals. It is
necessary in other applications as well (such as instrumentation, test equipment, pro­
cess control, and industrial control) to allow input and output of data in the form
familiar to human operators.
The 6809 microprocessor has a multiplication instruction MUL that can easily
be extended to handle data that is more than 8 bits in length. You can implement
division as a series of subtractions and shifts much as you ordinarily perform long
division by hand. Double-byte operations are essential since division reduces the bit
length of the result. Of course, multiplying or dividing by a power of 2 is simple since
such operations can be implemented with an appropriate number of left or right
arithmetic shifts.
8-2 6809 Assembly Language Programming

PROGRAM EXAMPLES

8-1. MULTIPLE-PRECISION BINARY ADDITION

Purpose: Add two multi-byte binary numbers. The length of the numbers (in bytes) is
in memory location 0040, the numbers themselves start (least significant bits
first) in memory locations 0041 and 0051 respectively, and the sum replaces
the number starting in memory location 0041.

Sample Problem:

(0040) 04 Number of bytes in each number

(0041) C3 )
(0042) A7 I 2F5BA 7C316 is first number
(0043) 58 (
(0044) 2F J
(0051) BB
(0052) 35
14DF35B816 is second number
(0053) OF
(0054) 14

Result: (0041) 78 )
(0042) DO I 443ADD7B16 is sum
(0043) 3A (
(0044) 44 '

Flowchart:

COUNT = (0040)
POINTER 1 = 0041
POINTER2 = 0051
CARRY= 0

(POINTER1) =
(POINTER 1) +
IPOINTER2l +
(CARRY) (This step also produces new carry)

POINTER1 =
POINTER1 + 1
POINTER2 =
POINTER2 + 1
COUNT=COUNT-1
Arithmetic Problems 8-3

Program 8-1 :

0000 D!i 40 LDB $40 COUNT=LENGTH OF NUMBER IN BYTES


0002 BE 0041 LDX *$41 POINT TO LSB'S OF FIRST NUMBER
0005 lOBE 0051 LDY �$51 POINT TO LSB'S OF SECOND NUMBER
0009 lC FE AN DCC #%11111110 CLEAR CARRY TO START
0008 A6 84 ADBYTE LDA ,X GET BYTE FROM FIRST NUMBER
0000 A9 AO ADCA ,Y+ ADD BYTE FROM SECOND NUMBER
OOOF A7 80 STA ,X+ STORE RESULT IN FIRST NUMBER
0011 SA DECB
0012 26 F7 BNE ADBYTE CONTINUE UNTIL ALL BYTES ADDED
0014 3F SWI

Clearing and Setting Flags

The instruction ANDCC logically ANDs the next byte of program memory with
the condition code register, clearing those flags that are ANDed with 'O's and leaving
unchanged those flags that are ANDed with '1 's. ANDCC=#=% 11111110 thus clears bit
0 of the condition code register (the Carry flag) and leaves the other bits unchanged.
The 6800 mnemonic for this operation is much clearer- CLC (CLEAR CARRY); of
course, the 6809 ANDCC is more general. The program must clear the carry since there
is never a carry into the least significant bytes.
The instruction ORCC is similar to ANDCC, except that it logically ORs the
next byte of program memory with the condition code register, setting those flags that
are ORed with '1 's and leaving unchanged those flags that are ORed with 'O's. ORCC
:#=%00000001 thus sets bit 0 of the condition code register (the Carry flag) and leaves the
other bits unchanged. As with ANDCC, the 6800 mnemonic is much clearer- SEC
(SET CARRY).

Add With Carry

The instruction ADC (ADD WITH CARRY) adds in the carry from the previous
byte. ADC is the only instruction in the loop that affects the Carry flag. Note, in particu­
lar, that instructions such as INC, DEC, and LEA perform counting and arithmetic
functions without affecting the Carry flag.

Positioning Data

This program uses two index registers so that the two numbers can be positioned
independently in memory. If we used a single index register, the numbers could be
located anywhere but would always have to be separated by a constant distance. We
could take advantage of the User Stack Pointer U to store the result in a third indepen­
dent set of memory locations. You might try modifying the program so that it stores the
sum starting in memory location 0061.

Decimal Accuracy in Binary Representation

This procedure can add binary numbers of any length. Ten bits correspond to
approximately three decimal digits since 210 = 1024�1000. So you can calculate the
number of bits required to give a certain accuracy in decimal digits from the formula:
Number of bits = ( 1 0 + 3) x Number of decimal digits

For example, twelve decimal digit accuracy requires:


12 x 10 + 3 = 40 bits
8-4 6809 Assembly Language Programming

One shortcoming of the 16-bit instruction ADDD is that it cannot be extended easily.
There is no 16-bit equivalent of the ADD WITH CARRY instruction.

8-2. DECIMAL ADDITION

Purpose: Add two multi-byte decimal (BCD) numbers. The length of the numbers (in
bytes) is in memory location 0040, the numbers themselves start (least sig­
nificant digits first) in memory locations 0041 and 0051 respectively, and the
sum replaces the number starting in memory location 0041.

Sample Problem:

(0040) = 04 Number of bytes in each number

=
l
(0041) 85
(0042) 19
36701985 is first number

J
(0043) 70
(0044) = 36

=

(0051) 59
(0052) 34
1 2663459 is second number

)
(0053) 66
(0054) = 12

l
Result: (0041) = 44
(0042) 54
49365444 is decimal sum


(0043) 36
(0044) = 49

that is. 36701985


+ 12663459

49365444

Flowchart:

COUNT = (0040)
POINTER1= 0041
POINTER2= 0051
Carry= 0

(This step also


produces new carry)

POINTER1=
POINTER1 + 1
POINTER2 =
POINTER2 + 1
COUNT =COUNT-1
Arithmetic Problems 8-5

Program 8-2:

0000 06 40 LOB $40 COUNT=LENGTH OF NUMBERS IN BYTES


0002 8E 0041 LOX 1$41 POINT TO LSB'S OF FIRST NUMBER
0005 lOSE 0051 LOY #$51 POINT TO LSB'S OF SECOND NUMBER
0009 lC FE ANDCC t%11111110 CLEAR CARRY TO START
0008 A6 84 ADDIGS LOA ,X GET TWO DIGITS OF FIRST NUMBER
0000 A9 AO ADCA ,Y+ ADD TWO DIGITS OF SECOND NUMBER
OOOF 19 DAA DECIMAL CORRECTION
0010 A7 80 STA ,X + STORE RESULT IN FIRST NUMBER
0012 5A DECB
0013 26 F6 BNE ADDIGS CONTINUE UNTIL ALL DIGITS ADDED
0015 3F SWI

The Decimal Adjust Instruction

The Decimal Adjust (DAA) instruction uses the Carry (C) and Half-Carry (H)
flags to recognize and change the following situations in which binary and BCD addition
differ:

1. The sum of two digits is between 10 and 15 inclusive. In this case, six must
be added to the sum to give the right result , e.g.,

0101 (5)
+ 1000 (8)
1101 (D)
+ 0110
0001 0011 (BCD 13, which is correct)

2. The sum of two digits is 16 or more. In this case, the result is a proper BCD
digit but six less than it should be, e.g.,

1000 (8)
+ 1001 (9)
0001 0001 (BCD 11)
+ 0110

0001 01 11 (BCD 1 7, which is correct)

An extra factor of 6 is necessary in both cases. However, the processor can recog­
nize Case 1 by determining that the sum is not a BCD digit, i.e., it is between 10 and 15
(or A and F hexadecimal). On the other hand, the processor must check the digit carry
(H for the lower digit, C for the upper digit) to recognize Case 2, since the result is a
valid BCD number. DAA is the only instruction that actually needs the H (Half-Carry)
flag. Note that DAA only operates on Accumulator A and only works correctly after an
ADDA or ADCA instruction.
You cannot use DAA after such instructions as:

1. ADDD or SUBD, since neither affects the H flag. Correcting the result of
ADDD to decimal would obviously require three digit carry flags.
2. ASL, ASR, NEG, SBC, or SUBA(B), since all of these leave the H flag in
an undefined state. In particular, you can only perform decimal subtraction
in a rather roundabout way (see Problem 2 at the end of the chapter). This
approach involves transforming a subtraction operation into an addition
8-6 6809 Assembly Language Programming

operation; if, for example, X and Y are each two digits from a string of
decimal numbers, then

X - Y = X + 99 - Y + BORROW

where BORROW is the borrow from the previous (less significant) digits.

Calculating 99- Y is simple, since any decimal number can be subtracted


from 99 without producing a borrow from either digit. You can then use DAA
to add X in decimal form. Note, however, that this operation produces a carry
if the result is positive but not if the result is negative. Thus the Carry has the
opposite meaning from its usual significance as a borrow in subtraction opera­
tions.

3. INC or DEC, since neither affects the Half-Carry or the Carry. You can,
however, perform a decimal increment of Accumulator A with the sequence:

ADDA #1 INCREMENT ACCUMULATOR


DAA RETAINING DECIMAL FORM

or a decimal decrement by adding 99 (hex or BCD):

ADDA #$99 DECREMENT ACCUMULATOR


DAA RETAINING DECIMAL FORM

The decimal increment produces a carry if the result is I 00, while the decimal
decrement produces a carry unless the result is 99. Thus you can recognize
either a carry or a borrow by examining the Carry flag.

4. LEA, since it produces a 16-bit result and does not affect either the Half­
Carry flag or the Carry flag.

Binary and BCD Accuracy

The decimal addition procedure works for decimal (BCD) numbers of any length.
Since each decimal digit requires four bits, twelve-digit accuracy requires

12 x 4 = 48 bits

as compared to 40 bits using binary addition. This is six bytes instead of five, a 20%
increase.
Arithmetic Problems 8-7

8-3. 8-BIT BY 16-BIT BINARY MULTIPLICATION

Purpose: Multiply the 8-bit unsigned number in memory location 0040 by the 16-bit
unsigned number in memory locations 0041 and 0042 ( MSB's in 0041). Place
the result in memory locations 0043, 0044, and 0045, with the MSB's in 0043
and the LSB's in 0045.

Sample Problems:
a. (0040) 03 multiplier
(0041) 00
(0042) 05 } 0005 is multiplicand

Result: (0043) 00
(0044) 00 OOOOOF is product
(0045) OF
or in decimal: 3 X 5 = 15.

b. (0040) 64 multiplier

(0041) 75
(0042) 30 } 7530 is multiplicand

Result: (0043) 20
(0044) C6 2DC6CO is product
(0045) co
or in decimal: 1 00 x 30,000 = 3,000.000.

Program 8-3:

0000 96 40 LDA $40 GET MULTIPLIER


0002 06 42 LOB $42 GET LSB'S OF MULTIPLICAND
0004 3D MUL MULTIPLY LSB'S
0005 DD 44 STD $44 SAVE PARTIAL PRODUCT
0007 96 40 LDA $40 GET MULTIPLIER
0009 06 41 LOB $41 GET MSB'S OF MULTIPLICAND
0008 3D MUL MULTIPLY MSB'S
oooc DB 44 ADDS $44 ADD LSB'S TO MSB'S
*
OF PREVIOUS PARTIAL PRODUCT
OOOE 89 00 ADCA 10 ADD CARRY TO MSB'S
0010 DO 43 STD $43 SAVE SUM OF PARTIAL PRODUCTS
0012 3F SWI

Extending the MUL instruction to handle longer operands works much like ordin­
ary long multiplication. You must be careful to align the partial products correctly before
adding them together. Each successive partial product is shifted 8 bits to the left from
the previous product. The ADCA =#:0 instruction provides a convenient way to handle
carries that may result from adding partial products.
Besides its obvious uses in calculators and point-of-sale terminals, multiplica­
tion is also a key part of almost all signal processing and control algorithms. The
speed at which a processor can perform multiplication determines its usefulness in
process control, adaptive control, signal detection, and signal analysis.

Multi-Dimensional Arrays

Another common use of multiplication is in locating elements in multi-dimen­


sional arrays. For example, if we have an array of sensor readings organized by remote
station number and sensor number, we generally refer to the reading from the 7th sen­
sor at station number 5 as R(5,7), where R is the name of the entire array. The usual
method of storing such an array is to start at address RBASE with R (0,0) and continue
8-8 6809 Assembly Language Programming

with R(0, 1), R(0,2), etc. If there are 3 stations (0, 1, and 2) and 4 sensors at each sta­
tion (0, l , 2, and 3), we keep the readings in the following memory locations:

Memory Location Reading

ABASE A(O,O)
ABASE+ 1 A(0,1)
ABASE+ 2 A(0,2)
ABASE+ 3 A(0,3)
ABASE+ 4 A(1,0)
ABASE+ 5 R(1,1)
RBASE+ 6 A(1.2)
RBASE+ 7 R(1.3)
RBASE+ 8 A(2.0)
RBASE+ 9 A(2.1)
RBASE+ 10 R(2,2)
RBASE+ 11 R(2.3)

In general, if we know the station number I and the sensor number J, the reading
R(I,J) is located at address

RBASE+ N X I + J

where N is the number of sensors at each station. Thus locating a particular reading in
order to update it, display it, or perform some mathematical operations on it requires a
multiplication. For example, the operator might want an instrument to print the current
reading of sensor =#:3 at station=#: 2. To find that reading, the processor must calculate the
address

RBASE + 4 x 2+ 3 = RBASE+ 11

Even more multiplications are necessary if the array has more dimensions. For
example, we might organize the sensors by station number, position in the X direction,
and position in theY direction (each station thus has sensors at regular positions on a
two-dimensional surface). Now we can describe a reading R (2,3, 1), which refers to the
reading of the sensor at station =#:2, X position =#:3, andY position :l:Fl . We can add even
more dimensions, such as vertical position, type of sensor, or time of reading. Each
added dimension means that the processor must perform more multiplications to locate
elements in the essentially one-dimensional memory.

Execution Time

This algorithm takes 54 clock cycles (or 27 microseconds if the clock is 2 MHz) to
multiply on a 6809 microprocessor. Higher speed would require additional hardware,
such as one of the multiplier chips described in the References at the end of this chapter.

8-4. BINARY DIVISION

Purpose: Divide the 16-bit unsigned number in memory locations 0040 and 0041 (most
significant bits in 0040) by the 8-bit unsigned number in memory location
0042. The numbers are normalized so that 1) the most signicant bits of both
the dividend and the divisor are zero and 2) the number in memory location
0042 is greater than the number in memory location 0040, i.e., the quotient is
an 8-bit number. Store the remainder in memory location 0043 and the quo­
tient in memory location 0044.
Arithmetic Problems 8-9

Sample Problems:

a. (0040) 00 } 004016 64 is dividend


(0041) 40
'=

(0042) 08 divisor

Result: (0043) 00 remainder


(0044) 08 quotient

that is, 64 -o- 8 = 8

b. (0040) 32 } 326D 16 = 12,909 is dividend


(0041) 6D
(0042) 47 711 o is divisor

Result: (0043) 3A 58 10 is remainder


(0044) 65 18110 is quotient

that is, 12,909 + 71 = 181 with a remainder of 58

Division Algorithm

You can perform division on the computer just as you would perform division
with pen and paper, i.e., using trial subtractions. Since the numbers are binary, the
only question is whether the bit in the quotient is 0 or I, i.e., whether the divisor can be
subtracted from what is left of the dividend. Each step in a binary division can be
reduced to the following operation:

If the divisor can be subtracted from the eight most significant bits of the dividend
without a borrow, the corresponding bit in the quotient is 1; otherwise, it is 0.

The only remaining problem is to line up the dividend and quotient properly.
You can do this by shifting the dividend and quotient logically left one bit before each
trial subtraction. The dividend and quotient can share a 16-bit register, since the pro­
cedure clears one bit of the dividend at the same time as it determines one bit of the
quotient.
The complete process for binary division is

STEP 1 - Initialization

QUOTIENT'= 0
COUNT= 8

STEP 2- Shift DIVIDEND and QUOTIENT to align them properly

DIVIDEND '= 2 x DIVIDEND


QUOTIENT = 2 X QUOTIENT

STEP 3- Perform trial SUBTRACTION. If no BORROW, add l to QUOTIENT

If 8 MSBs of DIVIDEND :2. DIVISOR then


MSBs of DIVIDEND '= MSBs of DIVIDEND - DIVISOR
QUOTIENT = QUOTIENT + 1

STEP 4- Decrement counter and check for zero

COUNT = COUNT - 1
If COUNT � 0, GO TO STEP 2
REMAINDER = 8 MSBs of DIVIDEND

In the case of sample problem b, where the dividend is 326D16 and the divisor is
4716, the process works as follows.
8-10 6809 Assembly Language Programming

Initialization: After fifth iteration:

DIVIDEND 326D DIVIDEND 33AO


DIVISOR 47 DIVISOR 47
QUOTIENT 00 QUOTIENT 16
COUNT 00 COUNT 03

After first iteration of STEPS 2-4. Note After sixth iteration:


that the dividend is shifted prior to the
DIVIDEND 2040
trial subtraction): DIVISOR 47
QUOTIENT 2D
DIVIDEND 1DDA
COUNT 02
DIVISOR 47
QUOTIENT 01
COUNT 07

After second iteration of STEPS 2-4: After seventh iteration:

DIVIDEND 3884 DIVIDEND 4080


DIVISOR 47 DIVISOR 47
QUOTIENT 02 QUOTIENT 5A
COUNT 06 COUNT 01

After third iteration: After eighth iteration:

DIVIDEND 3068 DIVIDEND 3AOO


DIVISOR 47 DIVISOR 47
QUOTIENT 05 QUOTIENT 85
COUNT 05 COUNT 00

After fourth iteration:

DIVIDEND 19DO
DIVISOR 47
QUOTIENT 08
COUNT 04

So the quotient is B5 and the remainder is 3A.


The MSBs of dividend and divisor are assumed to be zero to simplify calculations
(the shift prior to the trial subtraction would otherwise place the MSB of the dividend in
the Carry). Problems that are not in this form must be simplified by removing parts of
the quotient that would overflow 8 bits. For example:

1024 40016 10016


-- =--=100 16 +--
3 3 3

The last problem is now in the proper form. An extra division may be necessary.
Arithmetic Problems 8-11

Flowchart:

DIVIDEND=
(0040): {0041)
DIVISOR = {0042)
COUNT= 8
QUOTIENT= 0

DIVIDEND= 2 X

DIVIDEND
QUOTIENT = 2 X

QUOTIENT {Shift both left 1 bit)

8 MSBs of
DIVIDEND= 8 MSBs
of DIVIDEND­
DIVISOR
QUOTIENT=
QU TIENT + 1

COUNT=

COUNT-

(0043) =
8 MSB's of
DIVIDEND=
REMAINDER
(0044)=QUOTIENT

Program 8-4:

0000 86 08 LOA #8 COUNT=8


0002 97 43 STA $43
0004 DC 40 LDD $40 GET DIVIDEND
0006 58 DIVIDE ASLB SHIFT DIVIDEND, QUOTIENT
0007 49 ROLA
0008 91 42 CMPA $4 2 IS TRIAL SUBTRACTION SUCCESSFUL?
OOOA 25 03 BCS CHKCNT
oooc 90 42 SUBA $4 2 YES, SUBTRACT AND SET BIT IN
* QUOTIENT
OOOE sc !NCB
OOOF OA 43 CHKCNT DEC $4 3
0011 26 F3 BNE DIVIDE
0013 D D 43 STD $4 3 STORE REMAINDER, QUOTIENT
0015 3F SWI
8-12 6809 Assembly Language Programming

Many applications, such as calculators, terminals, communications error


checking, and control algorithms, involve division, but it is not nearly as common as
multiplication. This is why the 6809 instruction set includes a multiplication
instruction, but no division instruction. In particular, locating elements in multi­
dimensional arrays requires multiplication but not division.
The algorithm takes between 170 and 230 clock cycles to divide. That corresponds
to between 85 and 115 microseconds at a 6809 clock frequency of 2 MHz. The precise
time depends on how many times the trial subtraction succeeds, resulting in an actual
subtraction and the setting of bit 0 of the quotient. Other algorithms can reduce the
execution time somewhat, but 200 clock cycles will still be typical for a software division.
Higher speed requires additional hardware as described in the References at the end of
this chapter.
The instructions ASLBand ROLA together produce a 16-bit arithmetic left shift
of the Double Accumulator D. ASLBshifts bit 7 of Accumulator Binto the Carry, and
ROLA picks it up and places it in bit 0 of Accumulator A. The 6801 microprocessor has
instructions that shift the Double Accumulator left logically (LSLD) and right logically
(LSRD).
Accumulators A and B hold both the dividend and the quotient. The quotient
simply replaces the dividend in Accumulator Bas the dividend is shifted left logically.

8-5. SELF-CHECKING NUMBERS

Double Add Double Mod 10

Purpose: Calculate a checksum digit from a string of BCD digits. The length of the
string (number of bytes) is in memory location 0041, and the string of digits
(2 in each byte) starts in memory location 0042. Calculate the checksum digit
by the Double Add Double Mod 10 technique' and store it in memory loca­
tion 0040.
The Double Add Double Mod 10 technique works as follows:

1. Clear the checksum to start.


2. Multiply the leading digit by two and add the result to the checksum.
3. Add the next digit to the checksum.
4. Continue the alternating process until you have used all the digits.
5. The least significant digit of the checksum is the self-checking digit.

Self-Checking Numbers

Self-checking digits are commonly added to identification numbers on credit


cards, inventory tags, luggage, parcels, etc. when they are handled by computerized
systems. They may also be used in routing messages, identifying files, and other
applications. The purpose of the digits is to minimize entry errors such as transpos­
ing digits (69 instead of 96), shifting digits (7260 instead of 3726), missing digits by
one (65 instead of 64), etc. You can check the self-checking number automatically for
correctness upon entry and can eliminate many errors immediately.
The analysis of self-checking methods is quite complex. For example, a plain
Arithmetic Problems 8-13

checksum will not find transposition errors(4 + 9 9 + 4). The Double Add Double
=

(2 x 4 + 9
algorithm will find simple transposition errors 17 =f. 2 x 9 + 4), but will
=

miss some errors, such as transpositions across even numbers of digits (367 instead of
763). However, this method will find many common errors! The value of a method
depends on what errors it will detect and on the probability of particular errors in an
application.
For example, if the string of digits is:

549321

the result will be:


Checksum = 5 x 2 +4+ 9 x 2+3 +2 x 2+ 1 = 40
Self-checking digit = 0 Ueast significant digit of checksum)

Note that an erroneous entry like 543921 would produce a different self-checking digit
(4), but erroneous entries like 049321 or 945321 would not be detected.

Sample Problems:

a. (0041) 03 Number of bytes

(0042) 36
(0043) 68
(0044) 51

Result: Checksum= 3 X2+6+6 X 2 +8 +5 X 2+1 = 43


(0040) 03

b. (0041) 04 Number of bytes

(0042) 50
(0043) 29
(0044) 16
(0045) 83

Result: Checksum = 5 X 2+0 +2 X 2+9+1 X 2 +6+8 X 2 +3 = 50


(0040) 00

Program 8-5:
0000 BE 0042 LOX t$4 2 POINT TO START OF STRING
0003 OF 40 CLR $40 CHECKSUM=ZERO
0005 A6 84 CHKDG LOA ,X GET NEXT 2 DIGITS OF DATA
0007 44 LSRA SHIFT OFF LEAST SIGNIFICANT
* DIGIT
0008 44 LSRA
0009 4 4 LSRA
OOOA 44 LSRA
0008 1F 89 TFR A,B COPY MOST SIGNIFICANT DIGIT
0000 98 40 ADDA $4 0 ADD MSD TO CHECKSUM
OOOF 19 DAA RETAINING DECIMAL FORM
0010 97 40 STA $4 0
0012 1F 98 TFR 8,A AND ADD MSD TO CHECKSUM AGAIN
0014 98 40 ADDA $4 0
0016 19 DAA RETAINING DECIMAL FORM
0017 A8 80 ADDA ,X+ ADD IN LEAST SIGNIFICANT DIGIT
0019 19 DAA RETAINING DECIMAL FORM
001A 97 40 STA $40
001C OA 41 DEC $41 CO�TINUE UNTIL A L L DIGITS ADDED
OOlE 26 E5 BNE CHKDG
0020 84 OF ANDA U000011ll SAVE LSD OF CHECKSUM
0022 97 40 STA $40
0024 3F SWI
8-14 6809 Assembly Language Programming

Flowchart:

CHECKSUM= 0
COUNT = (00411
POINTER= 0042

MSD=(POINTER)-+16
LSD= (POINTER)
AND 000011 1 1 2
CHECKSUM=
CHECKSUM+
2 X M +

POINTER =

POINTER+ 1
COUNT=
COUNT- 1

(0040) =
CHECKSUM AND
000011112

Four logical right shifts move the most significant digit to the least significant bit
positions. There is no reason to mask out the most significant digit before adding the
least significant digit, since we do not care what happens to the most significant digit of
the checksum anyway.
A decimal adjust (DAA) must follow each addition to produce the proper
decimal result. A single DAA after a series of additions will not work (try it!).
Remember that DAA only operates on Accumulator A.
There is no problem with carries from the various decimal sums, since the
algorithm only uses the least significant digit of the checksum anyway.

Doubling and Halving Decimal Numbers

You can double a decimal number in Accumulator A by adding it to itself and


then performing a decimal correction. The following sequence uses memory location
0040 for temporary storage:

STA $40
AODA $40 DOUBLE NUMBER (ADD IT TO ITSELF)
OAA
SWI
Arithmetic Problems 8-15

You cannot use ASLA, because it leaves the Half-Carry flag undefined. Only
ADCA, ADCB, ADDA, and ADDB set the Half-Carry f1ag correctly.
You can divide a decimal number by 2 simply by shifting it right logically and
then subtracting 3 from any digit that has a value of 8 or larger (since 10 BCD is 1610).
The following program divides a decimal number in memory location 0040 by 2 and
places the result in memory location 0041.

LDA $40 GET DECIMAL NUMBER


LSRA DIVIDE BY 2 IN BINARY
TFR A,B MOVE QUOTIENT TO B FOR TESTING
ANDB #SOF MASK OFF MSD
CMPB #8 IS LSD 8 OR MORE?
BLO DONE
SUBA #3 YES, SUBTRACT 3 FROM LSD FOR DECIMAL
DONE STA $41 STORE RESULT
SWI

Try this program (and the method) on the decimal numbers 28, 30, and 37. Do
you understand why it works?

Binary Rounding

Rounding numbers is simple, regardless of whether they are binary or decimal.


You can round a binary number as follows:

If the most significant bit to be dropped is 1, add 1 to the remaining bits. Other­
wise, do not change the remaining bits.

This rule works because 1 is halfway between 0 and 10 in binary, much as 5 is halfway in
decimal (0.5 decimal = 0.1 binary).
So the following program will round a 16-bit_number in memory locations 0040
and 0041 (MSB's in 0040) to an 8-bit number in memory location 0040:
TST $41 IS MSB OF EXTRA BYTE 1?
BPL DONE
INC $40 YES, ROUND UP
DONE SWI

The TST instruction sets the flags according to the contents of the specified
accumulator or memory location (by subtracting zero from those contents), thus allow­
ing you to change the flags without using any registers or changing any values.
If the number is longer than 16 bits, the rounding must ripple through the other
bytes as needed. Of course, the only time the rounding affects the more significant bytes
is when it causes a carry. Since incrementing a memory location with INC does not affect
the Carry f1ag, we can only recognize a carry by checking to see if the result of INC is
zero. The following program increments a 16-bit number in memory locations 0040 and
0041 (MSB's in 0040).
INC $41 ADD l TO LSB'S
BNE DONE
INC $4 0 AND CARRY TO MSB'S IF NECESSARY
DONE SWI

An alternative for 16-bit numbers is to use an index register as in:

LOX $40 GET 16-BIT DATA


LEAX l,X INCREMENT IT BY 1
STX $40 STORE INCREMENTED DATA

This approach is more general, since the step size can have any value.
8-16 6809 Asscm bly Language Programming

Decimal Rounding

Decimal rounding is a bit more difficult, because the crossover point is now
BCD 50 and the rounding must produce a decimal result. The rule is:
If the most significant digit to be dropped is 5 or more, add 1 to the remaining
digits.

The following program will round a four-digit BCD number in memory locations
0040 and 0041 (MSD's in 0040) to a two-digit BCD number in memory location 0040.
LOA $41 IS BYTE TO BE DROPPED 50 OR MOR P?
CMPA #$50
BLO DONE
LOA $40 YES, ADD l TO MSD'S
ADDA #l KEEPING THEM IN DECIMAL FORM
DAA
STA $40
DONE SWI

Remember that you cannot use INC to add 1 because INC does not affect the
Half-Carry flag (which could have any value). As in the binary case, rounding longer
numbers requires that the carries ripple through the more significant digits as needed.

PROBLEMS

8-1. MULTIPLE-PRECISION BINARY SUBTRACTION

Purpose: Subtract one multi-byte binary number from another. The length of the num­
bers (in bytes) is in memory location 0040, the numbers themselves start
(least significant bits first) in memory locations 0041 and 0051 respectively,
and the difference replaces the number starting in memory location 0041.
Subtract the number starting in 0051 from the one starting in 0041.

Sample Problem:

(0040) 04 Number of bytes


(0041) C3
(0042) A7
58
l 2F5BA7C316 is minuend
(0043)
(0044) 2F f
(0051) 88
(0052)
(0053)
35
DF
l 1 4DF3 58816 is subtrahend

(0054) 14 f
OB
l
Result: (0041)


(0042) 72
1A 7C720B16 is difference
(0043) 7C
(0044) 1A

8-2. DECIMAL SUBTRACTION

Purpose: Subtract one multi-byte decimal (BCD) number from another. The length of
the numbers (in bytes) is in memory location 0040, the numbers themselves
Arithmetic Problems 8-17

start (least significant digits first) in memory locations 0041 and 0051 respec­
tively, and the difference replaces the number starting in memory location
004l. Subtract the number starting in 0051 from the one starting in 004l.

Sample Problem:

(0040) 04 Number of bytes

(0041) 85
(0042) 19 1 36701985 is minuend
(0043) 70
(0044) 36 �
(0051) 59
(0052) 34 1 12663459 is subtrahend
(0053) 66
(0054) 12 J
26
l
Result: (0041)
(0042) 85
24038526 is decimal difference
(0043) 03
(0044) 24 l
Hint: Remember that X - Y = X + 99 - Y + BORROW

where X andY are each two digits from the decimal strings and BORROW is the borrow
from the less significant digits. The right-hand side of this equation has an extra factor of
100, but that factor has no effect on a two-digit number. Note, however, that the opera­
tions on the right-hand side produce an overall carry if X - Y + BORROW is positive
but not if it is negative or zero.

8-3. 16-BIT BY 16-BIT BINARY MULTIPLICATION

Purpose: Multiply the 16-bit unsigned number in memory locations 0040 and 0041
(MSB's in 0040) by the 16-bit unsigned number in memory locations 0042 and
0043 (MSB's in 0042). Store the result in memory locations 0044 through
0047, with the most significant bits in memory location 0044.

Sample Problems:
00
}
a. (0040)
0003 is multiplier
(0041) 03
(0042) 00
(0043) 05 } 0005 is multiplicand

(0044) 00
1
Result:
(0045) 00
OOOOOOOF is product
(0046) 00
(0047) OF �
or in decimal: 3 x 5 = 15.

(0040) 27
}
b.
2 710 is multiplier
(0041) 10
75
}
(0042)
7530 is multiplicand
(0043) 30

1
Result: (0044) 11
(0045) E1
11E1A300 is product


(0046) A3
(0047) 00

or in decimal: 10,000 x 30,000 = 300.000.000.


8-18 6809 Assembly Language Programming

8-4. SIGNED BINARY DIVISION

Purpose: Divide the 1 6-bit signed number in memory locations 0040 and 0041 (most
significant bits in 0040) by the 8-bit signed number in memory location 0042.
The numbers are normalized so that the magnitude of memory location 0042 is
greater than the magnitude of memory location 0040. Store the quotient
(signed) in memory location 0044 and the remainder (always positive) in
memory location 0043.

Sample Problems:
a. (0040)
dividend is -6410
(0041)
�O }
(0042) 08 divisor

Result: (0043) 00 remainder


(0044) F8 quotient is -8

or in decimal: -64 + 8 = -8.

b. (0040) EDtf dividend is -4.7171 0


(0041) 93
(0042) 47 divisor is 71 1 0

Result: (0043) 28 remainder is +4010


(0044) BD quotient is -671 0
That is. -4.717 + 71 = -67 with a remainder of +40.

Hint: Determine the sign of the result, perform an unsigned division, and finally
adjust the quotient and remainder to the proper forms.

8-5. SELF-CHECKING NUMBERS ALIGNED 1, 3, 7 MOD 10

Purpose: Calculate a checksum digit from a string of BCD digits. The length of the string
of digits (number of bytes) is in memory location 0041, the string of digits (2
per byte) starts in memory location 0042. Calculate the checksum digit by the
Aligned 1 , 3, 7 Mod 1 0 method and store it in memory location 0040.
The Aligned 1, 3, 7 Mod 10 technique works as follows:

1. Clear the checksum to start.

2. Add the leading digit to the checksum.

3. Multiply the next digit by 3 and add the result to the checksum.
4. Multiply the next digit by 7 and add the result to the checksum.
5. Continue the process (Steps 2-4) until you have used all the digits.
6. The self-checking digit is the least significant digit of the checksum.

For example, if the string of digits is:

549321

the result will be:

Checksum == 5 + 3 x 4 +7 x 9 + 3 +3 x 2 + 7 x 1 = 96
Self-checking digit = 6
Arithmetic Problems 8-19

Sample Problems:

a. (0041) 03 Number of bytes

(0042) 36
(0043) 68
(0044) 51

Result Checksum = 3 + 3 x 6 + 7 x 6 + 8 + 3 x 5 + 7 x 1 = 93
(0040) 03

b. (0041) 04 Number of bytes

(0042) 50
(0043) 29
(0044) 16
(0045) 83
EL4 Result Checksum = 5 + 3 X 0 + 7 X 2 + 9 + 3 X 1 + 7 X 6 + 8 + 3 X 3 = 90
(0045) 00

Hint: Note that 7 = 2 x 3+1 and 3 = 2 x 1 + 1, so the formula M; = 2 x M;_1 + 1 can be used to calculate
the next multiplying factor.

REFERENCES

l. J. R. Herr. "Self-Checking Number Systems," Computer Design, June 1974, pp.


85-91.

2. Other methods for implementing multiplication, division, and other arithmetic.


tasks are discussed in:

Ali,Z. "Know the LSI Hardware Tradeoffs of Digital Signal Processors," Electronic
Design, June 21,1979,pp. 66-71.

Geist,D. J. "MOS Processor Picks up Speed with Bipolar Multipliers," Electronics,


July 7, 1977,pp. 113-115.

Kolodzinski,A. and D. Wainland. "Multiplying with a Microcomputer," Electronic


Design, January 18,1978,pp. 78-83.

Mor, S. "An 8 x 8 Multiplier and 8-Bit Microprocessor Perform 16 x 16-Bit


Multiplication," EDN, November 5, 1979,pp. 147-152.

Tao,T. F. et al. "Applications of Microprocessors in Control Problems," Proceed­


ings of the 1977 Joint Automatic Control Conference,San Francisco,Ca.,June 22-
24,1977.
Waser,S. "State-of-the-Art in High-Speed Arithmetic Integrated Circuits,'' Com­
puter Design, July 1978, pp. 67-75.

Waser, S. "Dedicated Multiplier ICs Speed up Processing in Fast Computer


Systems," Electronic Design, September 13,1978,pp. 98-103.

Waser,S. and A. Peterson. "Medium-Speed Multipliers Trim Cost, Shrink Band­


width in Speech Transmission," Electronic Design, February 1,1979,pp. 58-65.

Weissberger,A. J. and T. Toal. "Tough Mathematical Tasks are Child's Play for
Number Cruncher," Electronics, February 17,1977,pp. 102-107.
9
Tables and Lists

Tables and lists are two of the basic data structures used with all computers.
We have already seen tables used to perform code conversions and arithmetic. Tables
may also be used to identify or respond to commands and instructions, linearize data,
provide access to files or records, define the meaning of keys or switches, and choose
among alternate programs. Lists are usually less structured than tables. Lists may
record tasks that the processor must perform, messages or data that the processor
must record, or conditions that have changed or should be monitored. Tables are a
simple way of making decisions or solving problems, since no computations or logical
functions are necessary. The task, then, reduces to organizing the table so that the
proper entry is easy to find. Lists allow the execution of sequences of tasks, the prepara­
tion of sets of results, and the construction of interrelated data (or data bases). Problems
include how to add elements to a list and remove elements from it.

PROGRAM EXAMPLES

9-1. ADD ENTRY TO LIST


Purpose: Add the contents of memory location 0040 to a list if it is not already present
in the list. The length of the list is in memory location 0041 and the list itself
begins in memory location 0042.
9-2 6809 Assembly Language Programming

Sample Problems:
a. (0040) 68 Entry to be added

(0041) 04 Length of list

(0042) 37 First element in list


(0043) 61
(0044) 38
(0045) 10

Result: (0041) 05 New length

(0046) 68

The entry 68 is added to the list, since it is not already there. The length of the list is
increased by 1.

b. (0040) 68 Entry to be added


(0041) 04 Length of list

(0042) 37 First element in list


(0043) 68
(0044) 38
(0045) 10

Result: No change, since the entry (68) is already in the list (in memory location 0043)

Flowchart:

ENTRY = (0040)
COUNT (0041)
=

POINTER 0042=

POINTER=
POINTER+ 1
COUNT=
COUNT- 1

(POINTER) = ENTRY
(0041) = (0041)
+ 1
Tables and Lists 9-3

Program 9-1 :
0000 8E 0042 LDX f$42 POINT TO START OF LIST
0003 D6 41 LDB $41 COUNT = LENGTH OF LIST
0005 96 40 LDA $40 GET ENTRY
0007 A1 80 SRLST CMPA ,X+ IS ENTRY = ELEMENT IN LIST?
0009 27 07 BEQ DONE YES, DONE
0008 SA DECB ALL ENTRIES EXAMINED?
oooc 26 F9 BNE SRLST NO, KEEP LOOKING
OOOE A7 84 STA ,X YES, ADD ENTRY TO LIST
0010 oc 41 INC $41 ADD 1 TO LIST LENGTH
0012 3F DONE SWI

Clearly, this method of adding elements is very inefficient if the list is long. We
could improve the procedure by limiting the search to part of the list or by ordering the
list. We could limit the search by using the, entry to get a starting point in the list. This
method is called "hashing," and is much like selecting a starting page in a dictionary or
directory on the basis of the first letter in an entry.l We could order the list by numerical
value. The search could then end when the list values went beyond the entry (larger or
smaller, depending on the ordering technique used). A new entry would have to be
inserted properly, and all the other entries would have to be moved down in the list.
The program could be restructured to use two tables. One table could provide a
starting point in the other table; for example, the search point could be based on the
most or least significant 4-bit digit in the entry.
The program does not work if the length of the list could be zero (what happens?).
We could avoid this problem by checking the length initially. The initialization pro­
cedure would then be:
LDB $41 COUNT u:w;TH OF LIST
=

BEQ ADELM ADD ENTRY T0 LI�T IF LENGTH IS ZERO

ADELM STA 'X YES, ADD LNTRY TO LIST

Unlike some other processors, the 6809's Zero flag is affected by simple data transfer
instructions such as LD (load) and ST (store).
If each entry were more than one byte in length, a pattern-matching program
would be necessary. The program would have to proceed to the next entry if a match
failed; that is, skip over the last part of the current entry once a mismatch was found.

9-2. CHECK AN ORDERED LIST

Purpose: Check the contents of memory location 0041 to see if it is in an ordered list.
The length of the list is in memory location 0042; the list itself begins in
memory location 0043 and consists of unsigned binary numbers in increasing
order. If the contents of location 0041 are in the list, clear memory location
0040; otherwise, set memory location 0040 to FF16.

Sample Problems:

a. (0041) 68 Entry to be added

(0042) 04 Length of list

(0043) 37 First element in list


(0044) 55
(0045) 7D
(0046) A1

Result: (0040) FF. since 68 is not in the list


9-4 6809 Assembly Language Programming

b. (0041) 6B Entr y to be added

(0042) 04 Length of list

(0043) 37 First element in list


(0044) 55
(0045) 6B
(0046) A1

Result: (0040) 00. since 6B is in the list

Flowchart:

ENTRY = (0041)
POINTER= 0043
COUNT = (0042)
MARK= 0

POINTER=
POINTER+ 1
MARK= FF16
COUNT=
COUNT- 1

(0040) =MARK

The searching process is a bit different here since the elements are ordered. Once
we find an element larger than the entry, the search is over, since subsequent elements
will be even larger. You may want to try an example to convince yourself that the pro­
cedure works. Note that an element larger than the entry is indicated by a comparison
that produces a borrow (that is, Carry = 1).
As in the previous problem, a table or other method that could choose a good
starting point would speed up the search. One method would be to start in the middle
and determine which half of the list the entry was in, then divide the half into halves,
etc. This method is called a binary search, since it divides the remaining part of the list in
half each time.2.3
Tables and Lists 9-5

Program 9-2:
0000 OF 40 CLR $40 MARK ELEMENT AS IN LIST
0002 BE 0043 LDX *$43 POINT TO START OF LIST
0005 D6 42 LDB $42 COUNT = LENGTH OF LIST
0007 96 41 LDA $41 GET ENTRY
0009 AI 80 SRLST CMPA , X+ IS ENTRY EQUAL TO ELEMENT?
OOOB 27 07 BEQ DONE YES, DONE
OOOD 25 03 BCS NOTIN ENTRY NOT IN LIST IF ELEMENT

IS LARGER
OOOF 5A DECB ALL ELEMENTS EXAMINED?
0010 26 F7 BNE SRLST
0012 03 40 NOT IN COM $40 YES, MARK ELEMENT AS NOT IN
0014 3F DONE SWI LIST

This algorithm is a bit slower than the one in Program 9-1 because of the extra
conditional jump (BCS NOTIN). The average execution time for this simple search
technique increases linearly with the length of the list, while the average execution time
for a binary search increases logarithmically. For example, if the length of the list is
doubled, the simple technique takes twice as long on the average, while the binary
search method only requires one extra iteration.

9-3. REMOVE ELEMENT FROM QUEUE

Purpose: Memory locations 0042 and 0043 contain the address of the head of the queue
0042). Place the address of the first element (head) of a queue into
(MSBs in
memory locations 0040 and 0041 (MSBs in 0040) and update the queue to
remove the element. Each element in the queue is two bytes long and contains
the address of the next two-byte element in the queue. The last element in the
queue contains zero to indicate that there is no next element.

Queues are used to store data in the order in which it will be used, or tasks in
the order in which they will be executed. The queue is a first-in, first-out data struc­
ture; i.e., elements are removed from the queue in the same order in which they were
entered. Operating systems place tasks in queues so that they will be executed in the
proper order. 1/0 drivers transfer data to or from queues so that it will be transmitted or
handled in the proper order. Buffers may be queued so that the next available one can
easily be found and those that are released can easily be added to the available storage.
Queues may also be used to link requests for storage, timing, or 1/0 so that they can be
satisfied in the correct order.
In real applications, each element in the queue will typically contain a large
amount of information or storage space besides the address required to link the ele­
ment to the next one.

Sample Problems:
(0042)
a.

(0043)
��} Address of first element in queue

(0046)
(0047)
�g} Address of second element in queue

(0040) OOt End of queue


(004E) oof
Result: (0040)
(0041)
��} Address of element removed from queue

(0042)
(0043)
�g} Address of new first element in queue
9-6 6809 Assembly Language Programming

b. (0042) OOt Empty queue


(0043) 00 f
Result: (0040)
(0041)
gg} No element available from queue

Flowchart:

POINTER=
(0042): (0043)
(0040): (0041) =
POINTER

(0042)= (POINTER)
(0043) =
(POINTER + 1)

Program 9-3:
0000 9E 42 LOX $42 GET ADDRESS OF HEAD OF QUEUE
0002 9F 40 STX $40 REMOVE HEAD OF QUEUE
0004 27 04 BEQ DONE DONE IF QUEUE WAS EMPTY
0006 AE 64 LOX ,X GET ADDRESS FROM NEXT ELEMENT
0008 9F 42 STX $42 MOVE NEXT ELEMENT TO HEAD OF
*
QUEUE
OOOA 3F DONE SWI

The 16-bit instructions LDX, LDY, LDU, STX, STY, and STU are very useful
for moving addresses from one place to another. LOX, LOY, and LDU load the index
register or stack pointer with the contents of the effective address and the next sequen­
t!:!! address, thus allowing the loading of a 16-bit address with a single instruction. STX,
STY, and STU similarly store a 16-bit address in memory. The addresses that are loaded
or stored can later be used to fetch individual data items or addresses from a data struc­
ture.

Using Data Structures

The various indexed and indirect addressing modes allow us to use data struc­
tures in a very flexible way. If, for example, Index Register X contains the starting
address of a block of information, we can refer to elements in the block with constant
offsets. For example, the instruction
LOA S20,X

loads Accumulator A from the address that is 20 16 bytes from the start of the block. The
elements in the block may themselves be addresses; for example, the instruction

LOB [$14,X]
Tables and Lists 9-7

loads Accumulator B from the address that is stored 1416 and 1516 bytes from the start of
the block.
How would we use such data structures? For example, we might want a piece of
test equipment to execute a series of tests as specified by the operator. Using entries
from a control panel, we will make up a queue of blocks of information, one for each test
that the operator will eventually want to run. Each block of information contains:

1. The starting address of the next block (or 0 if there is no next block).
2. The starting address of the test program.
3. The address of the input device (e.g., keyboard, card reader, or communica­
tions line) from which data will be read during the test.
4. The address of the output device (e.g., printer, CRT terminal, or communica-
tions line) to which the results will be sent as the test is run.
5. The number of times the test will be repeated.
6. The starting address of the data area to be used for storing temporary data.
7. A flag that indicates whether failing a test should preclude continuing to the
next test.

Clearly the block could contain even more information if there were more options
for the operator to specify while setting up the test sequence. Note that some elements
in the block contain data, others contain addresses, while still others may be 1-bit flags.
Note what we mean by flexibility in this example. Some of the procedures that the
operator can easily implement are:

1. Run the same test with different sets of 1/0 devices. A trial run might use data
from a local keyboard and send the results to the CRT, while a production run
might use data from a remote communications line and produce a permanent
record on a printer.
2. Execute tests in any order, just by changing the order in the queue.
3. Place temporary data in an area where it can easily be displayed or retrieved by
a debugging program.
4. Make alternative decisions as to whether tests should be continued, errors
should be reported, or procedures should be repeated. Here again, trial or
debugging runs may use one option, while production runs use another.
5. Delete or insert tests merely by changing the links which connect a test to its
successor. The operator can thus correct errors or make changes without
reentering the entire list of tests.

For example, assume that the operator enters the sequence TEST 1, TEST 2,
TEST 4, and TEST 5, accidentally omitting TEST 3. The blocks are linked as follows:

Block 1 (for TEST 1) contains the starting address for block 2 (for TEST 2).
Block 2 (for TEST 2) contains the starting address for block 3 (for TEST 4).
Block 3 (for TEST 4) contains the starting address for block 4 (for TEST 5).
Block 4 (for TEST 5) contains a link address of zero to indicate that it is the last
block.

To insert TEST 3 between TEST 2 and TEST 4 merely involves the following
changes.
9-8 6809 Assembly Language Programming

Block 2 (for TEST 2) must now contain the starting address for block 5 (for TEST
3).
Block 5 (for TEST 3) must contain the starting address for block 3 (for TEST 4).

No other changes are necessary and no blocks have to be moved. Note how much
simpler it is to insert or delete using linked lists, rather than lists that are stored in con­
secutive memory locations. There is no problem of moving elements up or down so as to
remove or create empty spaces.
In our example, the blocks are organized as follows:

Byte Number Contents

0 MSBs of starting address of next block


1 LSBs of starting address of next block
2 MSBs of starting address of test program
3 LSBs of starting address of test program
4 MSBs of input device address
5 LSBs of input device address
6 MSBs of output device address
7 LSBs of output device address
8 Number of test repetitions
9 MSBs of starting address of data area
10 LSBs of starting address of data area
11 Flag for continuation

If Index Register X contains the starting address of the block, some typical pro­
cedures are:

1. Get a byte of data from the input device and place it in byte 6 of the data
area.
LDA [ 4, X] GET INPUT iJ/\TA
LDY 9,X GET ADDRESG OF DATA AREA
STA 6,Y PLACE INPUT OATA IN DATA AREA

We need indirect addressing here since the block contains the address of the
input device, not the actual input data.
2. Get a byte of data from byte 3 of the data area and send it to the output
device.
LOY 9,X GET ADDRE:3�.: l'F DATA AREA
LDA J,Y GET A BYTE OF DI\TA
STA [fi,X] 'SEND DATA TO PJTPUT DEVICE

The indirect addressing allows us to use the address of the output device from
the block. We could move that address to an index register or stack pointer if
we needed it repeatedly.
3. Decrement the number of test repetitions by 1.

DEC 8,X REDUCE NUM8!'!l OF HEPETITIONS BY 1

Queuing can handle lists that are not in sequential memory locations. Each ele­
ment in the queue must contain the address of the next element. Such lists allow the
programmer to handle data or tasks in the proper order, change variables or 1/0 devices,
or fill in definitions in a program. Queuing requires extra storage as compared to
sequential lists, but elements are far easier to add, delete, or insert.

Doubly linked Lists

Sometimes you may want to maintain links in both directions. Then each ele­
ment in the queue must contain the addresses of both the preceding and the following
Tables and Lists 9-9

elements.4,S Such doubly linked lists allow you to easily retrace your steps (e.g., repeat
the previous task if an error occurs in the current one) or access elements from either
end (e.g., allowing you to remove or change the last two elements without having to go
through the entire queue). The data structure may then be used in either a first-in,
first-out manner or in a last-in, first-out manner, depending on whether new ele­
ments are added to the head or to the tail. How would you change the example program
so that memory locations 0044 and 0045 contain the address of the last element (tail) of
the queue?

Empty Queue

If there are no elements in the queue, the program clears memory locations 0040
and 0041. A program that requests an element from the queue must check those
memory locations to see if its request has been satisfied (i.e., if there was anything in the
queue). Can you suggest other ways to indicate whether the queue is empty?

9-4. 8-BIT SORT

Purpose: Sort an array of unsigned 8-bit binary numbers into descending order. The
length of the array is in memory location 0041 and the array itself begins in
memory location 0042.

Sample Problem:

(0041} 06 Length of array

(0042} 2A First element of array


(0043) B5
(0044) 60
(0045} 3F
(0046) 01
(0047) 19

Result: (0042) 01 Largest element of array


(0043) B5
(0044) 60
(0045} 3F
(0046} 2A
(0047) 19 Smallest element of array

Simple Sorting Algorithm

A simple sorting technique works as follows:

Step 1. Set a flag INTER.


Step 2. Examine each consecutive pair of numbers in the array. If any are out
of order, exchange them and clear INTER.
Step 3. If INTER = 0 after the entire array has been examined, return to
Step 1.

INTER will be cleared if any consecutive pair of numbers is out of order.


Therefore, if INTER = 1 at the end of a pass through the entire array, the array is in
proper order.
This sorting method is referred to as a "bubble sort." It is an easy algorithm to
9-10 6809 Assembly Language Programming

implement. However, other sorting techniques should be considered when sorting


long lists where speed is important.6-8
The technique operates as follows in a simple case. Let us assume that we want to
sort an array into descending order; the array has four elements- 12, 03, 15, 08.

1st Iteration:

Step 1. INTER= 1
Step 2. Final order of the array is:
12
15
08
03
since the second pair (03, 15) is exchanged and so is the third pair (03,
08). INTER = 0.

2nd Iteration:

Step 1. INTER = 1
Step 2. Final order of the array is:
15
12
08
03
since the first pair (12, 15) is exchanged. INTER = 0.

3rd Iteration:

Step 1. INTER= 1
Step 2. The elements are already in order, so no exchanges are necessary and
INTER remains 1.

This approach always requires one extra iteration to ensure that the elements are
in the proper order. No exchanges are performed in the last iteration, so it does not
really accomplish anything. Tracing through the examples shows that many of the
comparisons are wasted and even repetitive . Thus the method could be improved
greatly, particularly if the number of elements is in the thousands or millions, as it
commonly is in large data processing applications. New sorting techniques are an
important area of current research. 9

Program 9-4:

0000 86 01 SORT LDA #l INTERCHANGE FLAG = 1


0002 97 40 STA $40
0004 96 41 LDA $41 ADJUST ARRAY LENGTH TO NUMBER OF
0006 4A DEC: A PAIRS
0007 8E 0042 LDX ll$42 POINT TO START OF ARRAY
OOOA E6 80 PASS LDB ,X+ IS PAIR OF ELEMENTS IN ORDER?
oooc E1 84 CMPB ,X
OOOE 24 oc BCC COUNT YES, TRY NEXT PAIR
0010 OF 40 CLR $40 NO,CLEAR INTERCHANGE FLAG
0012 34 02 PSHS A SAVE ARRAY COUNTER
0014 A6 84 LDA ,X INTERCHANGE ELEMENTS IF OUT OF
0016 E7 84 STB ,X ORDER
0018 A7 1F STA -1, X
001A 35 02 PULS A RESTORE ARRAY COUNTER
001C 4A COUNT DECA
Tables and Lists 9-11

OOlD 26 EB BNE PASS CHECK FOR COMPLETED PASS


OOlF OD 40 TST $40 WERE ALL ELEMENTS IN ORDER?
0021 27 DD BEQ SORT NO, GO THROUGH ARRAY AGAIN
0023 3F SWI

The case where two elements in the array are equal is very important. The pro­
gram should not perform an interchange in that case since that interchange would be
performed in every pass. The result would be that every pass would set the interchange
flag, thus producing an endless loop. The program compares the elements in the
specified order so that the Carry flag is cleared if the elements are already arranged cor­
rectly. Remember that comparing two equal values always clears the Carry flag since the
Carry is a borrow after subtractions or comparisons.
Since the 6809 has a complete set of unsigned conditional branches (BHI, BHS,
BLO, BLS), we could perform the comparison in either direction. The sequence
LDB l,X IS PAIR OF �:.E�E�TS IN ORDER?
CMPB , X+
BLS COUNT

is equivalent to the one in the example program. We must use BLS rather than BLO
(BCS) to force a branch if the elements are equal.
Before starting each sorting pass, we must be careful to reinitialize the index and
the interchange flag.
The program must reduce the counter by 1 initially since the number of consecu­
tive pairs is one less than the number of elements (the last element having no suc­
cessor).
This program does not work properly if there are fewer than two elements in the
array. How could you handle this degenerate case?

Flowchart:

INTER = 1
'
COUNT = (0041 )-1
POINTER = 0042

TEMP = (POINTER)
(POINTER)=
(POINTER) + 1)
(POINTER+ 1) =
TEMP
INTER = 0

POINTER=
POINTER+ 1
COUNT=
COUNT- 1
9-12 6809 Assembly Language Programming

Other Sorting Methods

There are many sorting algorithms that vary widely in efficiency. References 2, 7,
and 8 describe some of these.
We have chosen to use the Hardware Stack for temporary storage in this problem;
the advantage of this approach is that it does not tie up a specific memory address.
Chapter 10 discusses the 6809's Hardware Stuck in more detail. Of course, we could
easily substitute a fixed memory location, such as 003F. Note the use of the special
operation codes PSH for Store Registers in Stack and PUL for Load Registers from
Stack, as opposed to the standard ST and LD.

9-5. USING AN ORDERED JUMP TABLE

Purpose: Use the contents of memory location 0042 as an index to a jump table starting
in memory location 0043. Each entry in the jump table contains a 16-bit
address with the MSBs in the first byte. The program should transfer control
to the address with the appropriate index; that is, if the index is 6, the program
should jump to address entry =#=6 in the table. Assume that the table has fewer
than 128 entries.

Sample Problem:
(0042) 02 Index for jump table

(0043) 00 }z . .
eroth element 1n Jump table
(0044) 4c
}
=

(0045) 00 . . .
F1rst element 1n Jump table
(0046) 50
(0047)
OOlf Second element .1n Jump
.
table
(0048) 54
(0049) 00 t . . .
Th1rd element 1n Jump table
(004A) 58 f

Result: (PC) 0054 since that is entry '11'2 (starting from zero)
in the jump table. The next instruction to be
executed will be the one located at that address.

Flowchart:

INDEX=
(0042) X 2

JELEM =
BASE+ INDEX

(PC)=
(JELEM):
(JELEM + 1)

The last box in the flowchart results in a transfer of control to the address obtained
Tables and Lists 9-13

from the table. No ending block is necessary. Such transfers do not bother the processor
at all, but you may want to add special notes to your flowchart and program documenta­
tion so that the sequence does not appear to be a "dead-end street" to the reader.

Program 9-5:
0000 96 42 LDA $4 2 GP.:T INDEX
0002 48 ASLA DOUBLE INDEX FOR 2-BYTE ENTRIES
0003 8E 0043 LDX *$4 3 GET BASE ADDRESS OF JUMP TABLE
0006 6E 96 JMP [A,X] TRANSFER CONTROL TO JUMP TABLE
* ENTRY

When you run this program, be sure to place some executable code (such as an
SWI instruction) at each address to which control could be transferred. Otherwise the
processor will never get back to the monitor program.

Jump Tables

Jump tables are very useful in situations where the processor must select one of
several routines for execution. Such situations arise in decoding commands (entered,
for example, from a control keyboard), selecting test programs, choosing alternative
methods or units, or selecting an 1/0 configuration. For example, a 4-position switch
on the front of an instrument or test system may select among the remote, self-test, au­
tomatic, or manual modes of operation. The processor reads the switch and selects the
appropriate routine from a jump table as follows:
LDA SWITCH READ SWITCH PO;; IT ION
ASLA DOUBLE IND�X FOR 2-BYTE �NTRIES
LDX #MODES GET BASE A�DRESS OF JUMP TABLE
JMP [A,X]

The jump table is organized as follows:


Address Contents

MODES MSBs of starting address of REMOTE routine


MODES+ 1 LSBs of starting address of REMOTE routine

MODES+ 2 MSBs of starting address of SELF-TEST routine


MODES+ 3 LSBs of starting address of SELF-TEST routine

MODES+ 4 MSBs of starting address of AUTOMATIC routine


MODES+ 5 LSBs of starting address of AUTOMATIC routine

MODES+ 6 MSBs of starting address of MANUAL routine


MODES+ 7 LSBs of starting address of MANUAL routine

The jump table replaces a series of conditional jump operations. The program
that accesses the jump table could be used to access several different tables merely by
changing the starting address.
The data must be multiplied by 2 to give the correct index since each entry in the
jump table is a 16-bit address that occupies two bytes of memory. The instruction JMP
[A,X] uses an indirect mode in which the destination is the address stored at the
specified location rather than the location itself. The procedure is as follows:

l. Add the contents of Accumulator A and Index Register X.


2. Use that address to fetch the new value for the program counter.
JMP A,X would actually place the sum of Accumulator A and Index Register X in
the program counter. JMP is an unconditional jump that allows direct (including base­
page) or indexed addressing, as compared to BRA and LBRA which require relative
addressing.
9-14 6809 Assembly Language Programming

No terminating instruction such as SWI is necessary, since JMP A,X transfers


control to the address obtained from the jump table. References 10 and 11 contain addi­
tional examples of the use of jump tables.
The program assumes that the jump table contains fewer than 128 entries (why?).
How could you change the program to allow longer tables?

Jump and Branch Instructions

The terminology used in describing jump and branch instructions can be con­
fusing. A jump instruction using direct addressing loads the specified address into
the program counter; the result is more like the outcome of an LDX instruction using
immediate addressing than it is like one using direct addressing. A jump instruction
using one of the indirect modes works like other instructions (such as LOX or STX)
using the corresponding non-indirect mode. For example,

l. JMP $AOOO transfers control to address A00016. That is, (PC) = A00016•
On the other hand, LOX $AOOO loads Index Register X from addresses
A00016 and A0011t.· That is (X) (A00016): (A00116).
=

2. JMP ,Y transfers control to the address in Index Register Y. That is, (PC) =

(Y).
On the other hand, LOX , Y loads Index Register X starting at the address in
Index Register Y. That is, (X) ( (Y)): ( (Y) + 1).
=

However, the instruction JMP [, Y] transfers control to the address reached


indirectly through Index Register Y. That is, (PC) ( (Y)): ( (Y) + 1).
=

PROBLEMS

9-1. REMOVE ENTRY FROM LIST

Purpose: Remove the byte in memory location 0040 from a list if it is present. The
length of the list is in memory location 0041 and the list itself begins in
memory location 0042. Move the entries below the one removed up one posi­
tion and reduce the length of the list by 1.
Sample Problems:

a. (00401 68 Entry to be removed from list

(00411 04 Length of list

(00421 37 First element in list


(00431 61
(00441 28
(00451 1D

Result: No change. since the entry is not in the list

b. (00401 68 Entry to be removed from list

(00411 04 Length of list

(00421 37 First element in list


(00431 68
(0044i 28
(00451 10
Tables and Lists 9-15

Result: (0041) 03 Length of list reduced by 1

(0043) 28 Other elements in list moved up one position


(0044) 10

The entry is removed from the list and the elements below it are moved up one
position. The length of the list is reduced by 1.

9-2. ADD ENTRY TO ORDERED LIST

Purpose: Place the byte in memory location 0041 in an ordered list if it is not already
there. The length of the list is in memory location 0042; the list itself begins in
memory location 0043 and consists of unsigned binary numbers in increasing
order. Place the new entry in the correct position in the list, adjust the ele­
ments below it down, and increase the length of the list by 1.

Sample Problems:
a. (0041) 6B Entry to be added to list

(0042) 04 Length of list

(0043) 37 First element in list


(0044) 55
(0045) 70
(0046) A1

Result: (0042) 05 Length of list increased by 1

(0045) 6B Entry placed in list

(0046) =
70 Other elements in the list moved down one position
(0047) A1

b. (0041) 6B Entry to be added to list

(0042) 04 Length of list

(0043) 37 First element in list


(0044) 55
(0045) 6B
(0046) A1

Result: No change. since the entry is already in the list

9-3. ADD ELEMENT TO QUEUE

Purpose: Add the address in memory locations 0040 and 0041 (MSBs in 0040) to a
queue. The address of the first element of the queue is in memory locations
0042 and 0043 (MSBs in 0042). Each element in the queue contains either the
address of the next element in the queue or zero if there is no next element;
all addresses are 16 bits long with the most significant bits in the first byte of
the element. The new element goes at the end (tail) of the queue; its address
will be in the element that was at the end of the queue and it will contain zero
to indicate that it is now the end of the queue.

Sample Problem:

�� f
(0040)
New element to be added to queue
(0041)

�� }
(0042)
Pointer to head of queue
(0043)

(0046)
(0047) gg } Last element in queue
9-16 6809 Assembly Language Programming

Result: (0046) 00 l
Old last element points to new last element
(0047) 4D f

���!�: gg} New last element in queue

How would you add an element to the queue if memory locations 0044 and 0045
contain the address of the tail of the queue (or last element) ?

9-4. 16-BIT SORT

Purpose: Sort an array of unsigned 16-bit binary numbers into descending order. The
length of the array is in memory location 0040 and the array itself begins in
memory location 0041. Each 16-bit number is stored with the most significant
bits in the first byte.

Sample Problem:
(0040) 03 Length of list

(0041) 19 } 1901 First element in list


(0042) 01

(0043) 3F } 3F60 Second element


(0044) 60

(0045) 85 } 852A Third element


(0046) 2A

Result: (0041) 85 } Largest element


(0042) 2A

(0043) 3F
(0044) 60

(0045) 19 } Smallest element


(0046) 01

9-5. USING A JUMP TABLE WITH A KEY

Purpose: Use the contents of memory location 0042 as the key to a jump table starting
in memory location 0043. Each entry in the jump table contains an 8-bit key
value followed by a 16-bit address ( MSBs in first byte) to which the program
should transfer control if the key is equal to that key value.

Sample Problem:

(0042) 38 Key value for search

(0043) 32 Key value for first entry

�g}
(0044)
004C Jump address for first entry
(0045)

(0046) 35 Key value for second entry


(0047)
(0048) �g} 0050 Jump address for second entry

(0049) 38 Key value for third entry


(004A)
(0048) ��} 0054 Jump address for third entry

Result: (PC) 0054. since that address corresponds to key value 38

Note: Be sure to place some executable code ( such as an SWI instruction) at each
address to which the program could transfer control, so that the processor will get back
to the monitor correctly.
Tables and Lists 9-17

REFERENCES

1. J. Hemenway and E. Teja. "EON Software Tutorial: Hash Coding," EDN, Septem­
ber 20, 1979, pp. 108-10.
2. D. Knuth. The Art of Computer Programming, Volume Ill: Searching and Sorting,
Addison-Wesley, Reading, Mass., 1978.
3. D. Knuth. "Algorithms," Scientific American, April 1977, pp. 63-80.
4. K. J. Thurber and P. C. Patton. Data Structures and Computer Architecture, Lex­
ington Books, Lexington, Mass., 1977.
5. J. Hemenway and E. Teja. "Data Structures- Part 1," EDN, March 5, 1979, pp.
89-92. "Data Structures- Part 2," EDN, May 5, 1979, pp. 113-16.
6. See Reference 2.
7. B. W. Kernighan and P. J. Plauger. The Elements of Programming Style, McGraw­
Hill, New York, 1978.
8. K. A. Schember and J. R. Rumsey "Minimal Storage Sorting and Searching Tech­
niques for RAM Applications," Computer, June 1977, pp. 92-100.
9. "Sorting 30 Times Faster with DPS," Datamation, February 1978, pp. 200-03.
10. L. A. Leventhal. "Cut Your Processor's Computation Time," Electronic Design,
August 16, 1977, pp. 82-89.
11. J. B. Peatman. Microcomputer-Based Design, McGraw-Hill, New York, 1977,
Chapter 7.
Ill
Advanced Topics

The following chapters will discuss more advanced areas of assembly language
programming. Chapters 10 and 11 deal with subroutines, an important aspect of all
levels of programming. Chapter 10 defines and gives examples of subroutines, while
Chapter 11 discusses 6809 implementations of important parameter passing techniques.
The following three chapters cover input and output, a microprocessor's contact with
the outside world. In Chapter 12 we discuss time delays and different types of periph­
erals. Chapter 13 deals with the 6820 Peripheral Interface Adapter, a popular parallel
1/0 device for Motorola processors, and gives examples of basic program tasks for that
device. Chapter 14 illustrates basic routines for a serial interface device, the 6850
Asynchronous Communications Interface Adapter. Chapter 15 treats the important and
often confusing topic of interrupts.
10
Subroutines

None of the examples that we have shown so far is typically a program all by
itself. Most real programs perform a series of tasks, many of which may be the same
or may be common to several different programs. We need a way to formulate these
tasks once and make the formulations conveniently available both in different parts
of the current program and in other programs.

Subroutine Library

The standard method is to write subroutines that perform particular tasks. The
resulting sequences of instructions can be written once, tested once, and then used
repeatedly. They can form a subroutine library that provides documented solutions to
common problems.

Subroutine Instructions

Most microprocessors have special instructions for transferring control to


subroutines and restoring control to the main program. We often refer to the special
instruction that transfers control to a subroutine as Call, Jump-to-Subroutine, Jump and
Mark Place, or Jump and Link. The special instruction that restores control to the main
program is usually called Return.
On the 6809 microprocessor, the Jump-to-Subroutine (JSR) or Branch-to­
Subroutine (BSR or LBSR) instructions save the old value of the Program Counter in
the hardware stack before placing the starting address of the subroutine in the Pro­
gram Counter; the Return from Subroutine (RTS) instruction gets the old value from
10-2 6809 Assembly Language Programming

the Stack and puts it back in the Program Counter. The effect is to transfer program
control, first to the subroutine and then back to the main program. Clearly the
subroutine may itself transfer control to a subroutine, and so on.

Parameters

In order to be really useful, a subroutine must be generaL A routine that can per­
form only a specialized task, such as looking for a particular letter in an input string of
fixed length, will not be very useful. If, on the other hand, the subroutine can look for
any letter in strings of any length, it will be far more helpfuL We call the data or
addresses that the subroutine allows to vary .. parameters." An important part of writ­
ing subroutines is deciding which variables should be parameters.
One problem is transferring the parameters to the subroutine; this process is
called passing parameters. The simplest method is for the main program to place the
parameters into registers. Then the subroutine can simply assume that the
parameters are there. Of course, this technique is limited by the number of registers
available. The parameters may, however, be addresses as well as data. For example, a
sorting routine could begin with Index Register X containing the starting address of the
array. Such 6809 features as indirect addressing, indexed addressing using the Stack
Pointers, the ability to push and pop entire sets of registers with one instruction, the
availability of both the user and the Hardware Stack Pointer, and the LEA instruction
provide far more powerful and more general ways of passing parameters. The main
program can place the parameters in the Stack and the subroutine can easily access
them, utilize the Stack for temporary storage, and place the results back in the Stack.
The only problems are keeping track of the return address (and not changing it) and
cleaning the Stack of unwanted data. The two stack pointers and the LEA instruction are
particularly helpful in stack management, as we shall show in Chapter 11. In that chapter
we will also describe more general approaches to passing parameters.

Types of Subroutines

Sometimes a subroutine must have special characteristics. A subroutine is


relocatable if it can be placed anywhere in memory. You can use such a subroutine
easily, regardless of other programs or the arrangement of the memory. A relocating
loader is necessary to place the program in memory properly; the loader will start the
program after other programs and will add the starting address or relocation constant
to all addresses in the program. Position-independent code does not require a relocat­
ing loader - all addresses are expressed relative to the program counter's current
value. We will discuss the writing of strictly relocatable or position-independent code
later in this chapter.
A subroutine is reentrant if it can be interrupted and called by the interrupting
program and still give the correct results for both the interrupting and interrupted
programs. Reentrancy is important for standard subroutines in an interrupt-based
system. Otherwise the interrupt service routines cannot use the standard subroutines
without causing errors. Microprocessor subroutines are easy to make reentrant since the
Call instruction uses the Stack and that procedure is automatically reentrant. The only
remaining requirement is that the subroutine use the registers and Stack rather than
fixed memory locations for temporary storage. This is a bit awkward, but usually can be
done if necessary.
Subroutines 10-3

A subroutine is recursive if it calls itself. Such a subroutine clearly must also be


reentrant. However, recursive subroutines are uncommon in microprocessor applica­
tions.

Subroutine Documentation

Most programs consist of a main program and several subroutines. This is


advantageous because you can use proven routines and debug and test the other
subroutines separately. You must, however, be careful to use the subroutines pro­
perly and remember their exact effects on registers and memory locations.
Subroutine listings must provide enough information so that users need not
examine the subroutine's internal structure. Among the necessary specifications are:

A description of the purpose of the subroutine

A list of input and output parameters

Registers and memory locations used

A sample case, perhaps including a sample calling sequence.

The subroutine will be easy to use if you follow these guidelines.

Hardware Stack

The following examples all reserve an area of memory for the hardware stack.
We have arbitrarily started the hardware stack at address OOFF by initializing the
Stack Pointer to 010016• If your microcomputer establishes a Stack area, you may use it
instead and you will not need an initial LOS instruction. If you wish to establish your
own stack area, remember to save and restore the monitor's Stack Pointer (in two
specified RAM locations ) in order to produce a proper return at the end of your main
program.

PROGRAM EXAMPLES

10-1. CONVERTING HEXADECIMAL TO ASCII

Purpose: Convert the contents of Accumulator A from a hexadecimal digit to an ASCII


character. Assume that the original contents of Accumulator A are a valid
hexadecimal digit.

Sample Problems:

a. (A) oc

Result: (A) 43 'C'

b. (A) 06

Result: (A) 36 '6'


10-4 6809 Assembly Language Programming

Flowchart:

(A)=(A)+ASCII A­
ASCII 9- 1

(A) = (A) + ASCII 0

Program 1 0-1 :

The calling program starts the Stack at memory location OOFF, gets the data from
memory location 0040, calls the conversion subroutine, and stores the result in memory
location 0041.

0000 ORG $0000


0000 10CE 0100 LOS J$100 START STACK AT MEMORY LOCATION
* DOFF
0004 96 40 LOA $40 GET HEXADECIMAL DATA
0006 BD 0020 JSR AS DEC CONVERT DATA TO ASCII
0009 97 41 STA $41 STORE RESULT
OOOB 3F SWI

The subroutine converts the hexadecimal data to ASCII.

0020 ORG $0020


0020 81 09 AS DEC CMPA t9 IS DATA A DECIMAL DIGIT?
0022 23 02 BLS ASCZ
0024 BB 07 ADDA t'A-'9-1 NO, ADD EXTRA OFFSET FOR
* LETTERS
0026 88 30 ASCZ ADDA f'O CONVERT DATA TO ASCII BY
0028 39 RTS ADDING ZERO

Subroutine Documentation:
*
*SUBROUTINE ASDEC
*
* PURPOSE: ASDEC CONVERTS A HEXADECIM AL
* DIGIT IN ACCUMULATOR A TO AN
* ASCII DIGIT IN ACCUMULATOR A
*
*INITIAL CONDITIONS: HEXADECIMAL DIGIT IN A
*
*FINAL CONDITIONS: ASCII CHARACTER IN A
*
*REGISTERS AFFECTED: A, FLAGS
*
*SAMPLE CASE
* INITIAL CONDITIONS: 6 IN ACCUMULATOR A
* FINAL CONDITIONS: ASCII 6 (HEX 3")
* IN ACCUMULATOR A
Subroutines 10-5

The 6809 Stack grows downward (toward lower addresses); the Stack Pointer
always contains the address of the last occupied location, rather than the next empty
one as on some other microprocessors (including the 6800 and 6502) . This means you
must initialize the Stack Pointer to a value one higher than the largest address in the
Stack area (e.g., initializing the Stack Pointer to 010016 means that the largest address in
the Stack area will be OOFF16).

JSR Instruction

The Jump to Subroutine instruction places the starting address of the


subroutine (0020) in the Program Counter and saves the current value of the program
counter (the address immediately following the JSR instruction) in the hardware
stack. The procedure is:

STEP 1 Decrement Stack Pointer, save LSB's of current


Program Counter in Stack.
STEP 2 Decrement Stack Pointer, save MSB's of current
Program Counter in Stack.
STEP 3 Place starting address of subroutine in Program
Counter.

The 6809 always decrements the Stack Pointer before storing a byte of data, so the
procedure is the same as in the autodecrement addressing mode. Although the pro­
cessor stores the LSB's of the current program counter first, the address ends up in the
usual 6809 form (MSB's at the lower address) since the Stack is growing down (toward
lower addresses).
The overall effect of JSR is:

IISI-11 IPCL)
IISI-21 (PCH)

lSI lSI- 2
(PC) EA

where PCH and PCL are the most and least significant bytes of the Program Counter,
respectively, S is the Hardware Stack Pointer, and EA is the effective address for the
JSR instruction. Since the processor has fetched the entire JSR instruction, the program
counter contains the address of the following byte.
In our example, the effect of JSR ASDEC is:

IOOFFI
(OOFE)
09
00
} Return address
lSI OOFE
(PC) 0020

The only difference between JSR and JMP is that JSR ''remembers" where it
came from, thus providing for the resumption of the main program. The processor
keeps a record in the hardware stack, much as one might jot down a starting point on a
piece of paper. The advantages of using the stack are that it is ordered and expanda­
ble; subroutines can themselves call subroutines and so on without destroying any of
the return addresses or restoring them in the wrong order. The latest return address is
always at the top of the hardware stack, with the others under it in the order in which
they will be used.
10-6 6809 Assembly Language Programming

RTS Instruction

The Return from Subroutine (RTS) instruction retrieves the return address
from the Stack Ooading the top two bytes) and places that address back in the Pro­
gram Counter. The procedure is:

STEP I Load top byte from the stack into the MSB's of
the Program Counter, increment Stack Pointer.

STEP 2 Load top byte from the stack into the LSB's
of the Program Counter, increment Stack Pointer.

The 6809 microprocessor always increments the Stack Pointer after loading a byte
of data, so the procedure is the same as in the autoincrement addressing mode. RTS bal­
ances JSR, much as a right parenthesis balances a left parenthesis. The actions of RTS,
however, are automatic; it simply takes the top two bytes in the hardware stack and
places them in the Program Counter. The programmer must ensure that those top two
bytes contain a legitimate return address; the processor does not examine them.
The overall effect of RTS is:

(PCH) ((S))
(PCU ((S) + 1)

(S) (S) + 2

In our example, RTS has the following effects:

(PC) (OOFE) • (OOFF) = 0009


(S) 0100

Parameters and Subroutine Characteristics

This subroutine has a single parameter and produces a single result. An accumula­
tor is the obvious place to put both the parameter and the result.
The calling program consists of three steps: placing the data in the Accumulator,
calling the subroutine, and storing the result. The overall initialization program must
also load the Hardware Stack Pointer with the appropriate address.
This subroutine is reentrant since it uses no data memory; it is relocatable since
the address ASCZ is relative. The use of BSR (Branch-to-Subroutine) rather than JSR
would make the calling program relocatable as well.
The Jump-to-Subroutine instruction results in the execution of four or five
instructions, taking 12 or 14 clock cycles. A subroutine call may take a long time even
though it appears to be a single instruction in the program. Calling a subroutine always
involves some overhead as well, since both the Jump-to-Subroutine and the Return­
from-Subroutine instructions take time. In fact, a JSR takes 4 clock cycles longer than
the corresponding JMP (with the same addressing mode) because JSR must save the
current Program Counter in the RAM stack; RTS always takes 5 clock cycles.
If you use the stack for passing parameters, remember that Jump or Branch to
Subroutine always saves the return address at the top of the stack. You can refer to the
parameters using indexed addressing with offsets of 2 or more from the Hardware Stack
Pointer (the return address occupies the addresses with offsets 0 and I).
Subroutines 10-7

10-2. LENGTH OF A STRING OF CHARACTERS

Purpose: Determine the length of a siring of ASCII characters. The starting address of
the string is in Index Register X. The end of the string is marked by a carriage
return character ('CR', 0016). Place the length of the string (excluding the car­
riage return) in Accumulator B.

Sample Problems:

a. (X) 0043 Starting address of string


(0043) 52 ' R '
(0044) 41 A ' '

(0045) 54 ' T'


(0046) 48 'H'
(0047) 45 'E'
(0048) 52 ' R'
(0049) OD CR

Result: (B) 06

b. (XI 0043 Starting address of string


(0043) OD CR

Result: (B) 00

Flowchart:

POINTER = (X)
COUNT= 0

Yes

COUNT= End
COUNT+ 1
POINTER=
POINTER+ 1

Program 10-2:

The calling program starts the Stack at memory location OOFF, gets the starting
address of the string from memory locations 0040 and 0041, calls the string length
subroutine, and stores the result in memory location 0042.
0000 ORG $0000
0000 10CE 0100 LDS #$100 START STACK AT MEMORY L OCATION
*
OOFF
0004 9E 40 LDX $40 GET STARTING ADDRESS OF STRING
0006 BD 0020 JSR STLEN DETERMINE LENGTH OF STRING
0009 D7 42 STB $4 2 STORE STRING LENGTH
OOOB 3F SWI
10-8 6809 Assembly Language Programming

The subroutine determines the length of the string of ASCII characters and places
the length in Accumulator B.

0020 ORG $0020


0020 C6 FF STLEN LOB tSFF STRING LENGTH = -1
0022 86 OD LOA 1$00 GET ASCII CARRIAGE RETURN TO
* COMPARE
0024 5C CHKCR INCB ADO 1 TO STRING LENGTH
0025 A1 80 CMPA I X+ IS NEXT CHARACTER A CARRIAGE
* RETURN?
0027 26 FB BNE CHKCR NO, KEEP LOOKING
0029 39 RTS

Subroutine Documentation:
*SUBROUTINE STLEN
*
*PURPOSE: STLEN DETERMINES THE LENGTH
* OF A STRING (NUMBER OF CHARACTERS
* BEFORE � CARRIAGE RETURN)
*

*I NITIAL CONDITIONS: STARTING ADDRESS


* OF STRING IN INDEX REGISTER X
*
*FINAL CONDITIONS: NUMBER OF CHARACTERS IN B
*

*REGISTERS AFFECTED: A,B,X,FLAGS


*
*SAMPLE CASE
* INITIAL CONDITIONS: (X) = 0042
* (0042) = 40, (0043i = 41, (0044) 4E, (0045) OD
* FINAL CONDITIONS: {B) = 03

This subroutine has a single parameter which is an address; Index Register X is


the obvious place to put it. The result is returned in Accumulator B.
The calling program consists of three steps: placing the starting address of the
string in Index Register X, calling the subroutine, and storing the result in memory. The
overall initialization must also load the Hardware Stack Pointer with the appropriate
value.
The subroutine is reentrant, since it does not use any fixed memory addresses for
storage.
The subroutine changes Accumulator A as well as Accumulator B and Index
Register X. The programmer must be aware that calling this subroutine destroys the
contents of Accumulator A, even though it does not contain a parameter. The
subroutine documentation must specify which registers are affected in order to avoid
unforeseen side effects.
An alternative approach would be for the subroutine to save and restore the
original contents of Accumulator A_ The instruction PSHS A would save those con­
tents initially and the instruction PULS A would restore them before the return. This
approach takes extra time and memory, but makes the subroutine easier to use since it
does not produce as many incidental changes. We could save and restore the condition
code register as well by using the instructions PSHS A,CC and PULS A,CC.
If the terminating character were not always an ASCII carriage return, we
could make that character into another parameter. Then the calling program would
have to place the terminating character in Accumulator A before calling the
subroutine.
Subroutines 10-9

10-3. MAXIMUM VALUE

Purpose: Find the largest element in an array of unsigned binary numbers. The length
of the array (number of bytes) is in Accumulator Band the starting address of
the array is in Index Register X. The maximum value is returned in
Accumulator A.

Sample Problem:

(B) 05 Length of array (number of bytes)


(X) 0043 Starting address of array

(0043) 67
(0044) 79
(0045) 15
(0046) E3
(0047) 72

Result: (A) E3. since this is the largest of the five unsigned
numbers in the array

Flowchart:

COUNT= (B)
POINTER= (X)
MAX= 0

MAX= (POINTER)

POINTER=
POINTER+ 1
COUNT=
COUNT- 1

(Al =MAX
10-10 6809 Assembly Language Programming

Program 10-3:

The calling program starts the Stack at memory location OOFF, sets the starting
address of the array to 0043, gets the length of the array from memory location 0040,
calls the maximum subroutine, and stores the maximum value in memory location
0041.

0000 ORG $0000


0000 10CE 0100 LOS #$0100 START STACK AT MEMORY LOCATION

OOFF
0004 BE 0043 LOX ll$43 GET STARTING ADDRESS OF ARRAY
0007 06 40 LOB $40 GET LENGTH OF ARRAY
0009 BD 0020 JSR MAXM FIND MAXIMUM VALUE
oooc 97 41 STA $41 SAVE MAXIMUM VALUE IN MEMORY
OOOE 3F SWI

The subroutine determines the maximum value in the array.

0020 ORG $0020


0020 4F MAXM CLRA MAXIMUM = ZERO (MINIMUM POSSIBLE

VALUE)
0021 Al 80 CHKE CMPA I X+ IS CURRENT ENTRY GREATER THAN

MAXIMUM?
0023 24 02 BCC NOCHG
0025 A6 lF LDA -l,X YES, REPLACE MAXIMUM WITH

CURRENT ENTRY
0027 SA NOCHG DECB
0028 2 6 F7 BNE CHKE
002A 39 RTS

Subroutine Documentation:

*SUBROUTINE MAXM
*

*PURPOSE: MAXM DETERMINES THE MAXIMUM VALUE IN AN ARRAY OF


* UNSIGNED BINARY NUMBERS
*

*INITIAL CONDITIONS: STARTING ADDRESS OF ARRAY IN INDEX REGISTER


* X, LENGTH OF ARRAY (NUMBER OF BYTES) IN A�CUMULATOR B
*
*FINAL CONDITIONS: MAXIMUM VALUE IN ACCUMULATOR A
*
*REGISTERS AFFECTED: A,B,X,FLAGS
*

*SAMPLE CASE:
* I NIT I A L C O N D I T I ONS: 0043 IN IN D E X R E G I STE R X, 03 IN
* ACCUMULATOR B, (0041) = 35, (0044) = 4t;, (00<\5) = OD
* RESULT: (A) = 4G

This subroutine has two parameters - an address and a number. Accumulator B


is used to pass the number and Index Register X to pass the address. The result is a
single number that is returned in Accumulator A.
The calling program must place the starting address o f the array in Index Register
X and the length of the array in Accumulator B before transferring control to the
subroutine.
The subroutine is reentrant since it uses no fixed memory addresses and relocata­
ble since it uses only relative branches.
We could retain the original contents of the condition code register by using the
instructions PSHS CC and PULS CC.
This subroutine has some incidental effects: it changes the address in Index
Register X (the final value is one beyond the last address in the array because of the
autoincrementing) and it returns with zero in Accumulator B.
Subroutines 10-11

10-4. PATTERN MATCH

Purpose: Compare two strings of ASCII characters to see if they are the same. The
length of the strings is in Accumulator B. The starting address of one string is
in Index Register X and the starting address of the other string is in Index
Register Y. If the two strings match, clear Accumulator B; otherwise, set
Accumulator B to FF16•

Sample Problems:
a. (B) 03 Length of strings
(X) 0046 Starting address of string :¢1
(Y) 0050 Starting address of string #2
(0046) 43 ·c·
(0047) 41 'A'
(0048) 54 'T'

(0050) 43 ·c·
(0051) 41 'A'
(0052) 54 'T'

Result: (B) 00 since the strings are the same

b. (X) 0046 Starting address of #1


(Y) 0050 Starting address of string .ll:2
(0046) 52 'R'

(0047) 41 'A'
(0048) 54 'T'

(0050) 43 ·c·
(0051) 41 'A'
(0052) 54 'T'

Result: (8) FF since the first characters differ

Program 10-4:

The calling program starts the Stack at memory location OOFF, sets the two start­
ing addresses (Index Registers X and Y) to 0046 and 0050 respectively, gets the length
of the string from memory location 0041, calls the pattern match subroutine, and places
the result in memory location 0040.

0000 ORG $0000


0000 lOCE 0100 LOS t$0100 START STACK AT MEMORY LOCATION
*
OOFF
0004 BE 0046 LOX t$46 GET STARTING ADDRESS OF STRING 1
0007 lOBE 0050 LOY f$50 GET STARTING ADDRESS OF STRING 2
0008 06 41 LOB $41 GET LENGTH OF STRINGS
0000 BD 0020 JSR PMTCH COMPARE STRINGS
0010 07 40 STB $40 SAVE MATCH INDICATOR
0012 3F SWI

The subroutine determines if the two strings are the same.

0020 ORG $0020


0020 A6 BO PMTCH LOA ,X+ GET A CHARACTER FROM STRING 1
0022 Al AO CMPA ,Y+ IS THERE A MATCH WITH STRING 2?
0024 26 04 BNE NOMCH NO, DONE
0026 SA DECB ALL CHARACTERS CHECKED?
0027 26 F7 BNE PMTCH NO, CONTINUE
0029 39 RTS YES, RETURN WITH INDICATOR
*
ZERO
002A C6 FF NOMCH LOB ISFF NO MATCH, INDICATOR FF HEX =

RTS
10-12 6809 Assembly Language Programming

Flowchart:

POINTER1 = (X)
POINTER2 (Y) =

COUNT= (8)

No

POINTER1 =

POINTER1 + 1
POINTER2 =
POINTER2 + 1
COUNT=COUNT -1

MARK 0 MARK= FF16

Subroutine Documentation:

*SllfFl'1!JTINE PMTCH

*PURPOSE: PMTCH DETERMINES IF TWO STRINGS ARE IDENTICAL


*
*INITIAL CONDITIONS: STARTING ADDRESSES OF STRINGS IN INDEX
* REGISTF.RS X AND Y, LENGTH OF STRINGS (IN BYTES) TN
* ACCUMULATOR f\
*
*FINAL CONDITIONS: ZERO IN ACCUMULAT OR B IF STRINGS MATCH,
* FF IN ACCUMULATOR 8 OTHERWISE
*
*REGISTERS AFFECTED: A,B,X,Y,FLAGS
*
* SAMPLE CASF.:
* INITIAL CONDITIONS: (X) = 0046, (Y) = 0050, (B) = 02
* (OOtl')) = 3G, (0047) = 19
* (0050) = 3'), (0051) ·= 39
* RESULT: (fl) = 00 SINCE THE STRHTGS ARE IDENTICAL

This subroutine, like the preceding examples, changes all the flags. You should
generally assume that a subroutine call changes the flags unless it is specifically stated
otherwise. If the main program needs the old flag values (for later checking), it must
save them in the Stack (using PSHS CC) before calling the subroutine, and restore them
afterward (using PULS CC).
Subroutines 10-13

This subroutine has three parameters - two starting addresses and the length of
the strings. Two index registers (X and Y) are used for the starting addresses;
Accumulator B is used for both the length of the strings and for the result. The
subroutine changes Accumulator A incidentally.
The subroutine is reentrant, since it uses no fixed addresses.
Obviously, subroutines become far more complicated as soon as the number of
parameters exceeds the number of registers. Using the registers is convenient, but it
lacks generality; as soon as the number of parameters becomes large, you must use an
entirely different approach.
Note that the subroutine has two exit points (i.e., two RTS instructions). This cre­
ates no problems, since either RTS terminates the subroutine and transfers control back
to the main program.

10-5. MULTIPLE-PRECISION ADDITION

Purpose: Add two multi-byte binary numbers. The length of the numbers (in bytes) is
in Accumulator B, the starting addresses of the numbers are in Index
Registers X and Y, and the starting address of the result is in the User Stack
Pointer U. All the numbers begin with the least significant bits.

Sample Problem:

(B) 04 Length of numbers in bytes


(X) 0048 Starting address of first number

}
(Y) 004C Starting address of second number
(U) 0050 Starting address of result

(0048) C3
(0049) A7
2F5BA 7C316is first number

}
(004A) 5B
(0048) 2F

(004C) B8
(0040) 35

}
14DF35B816is second number
(004El DF
(004F) 14

Result: (0050) 78
(0051)
(0052)
�� 443ADD7B16is sum

(0053) 44

Program 1 0-5:

The calling program starts the Stack at memory location OOFF, sets the starting
addresses of the various numbers to 0048, 004C, and 0050, respectively, gets the length
of the numbers (in bytes) from memory location 0040, and calls the multiple-precision
addition subroutine.

0000 ORG $0000


0000 1 OCE 0100 LDS #$0100 START STACK AT MEMORY LOCATION

OOFF
0004 8E 0048 LDX #$48 GET STARTING ADDRESS OF FIRST

NUMBER
0007 1 08E 004C LDY #$4C GET STARTING ADDRESS OF SECOND

NUMBER
OOOB CE 0050 LDU #$50 GET STARTING ADDRESS OF SUM
OOOE D6 40 LDB $40 GET LENGTH OF NUMBERS (IN BYTES)
0010 B D 0020 JSR MPADD PERFORM MULTIPLE-PRECISION

ADDITION
0013 3F SWI
10-14 6809 Assembly Language Programming

Flowchart:

POINTER 1 = (X)
POINTER2 = (Y)
POINTER3 = (U)
COUNT= (8)
CARRY= 0

(POINTER3) =
(POINTER1) +
This step also produces a new carry.
(POINTER2) +

CARRY

POINTER1 =
POINTER1 + 1
POINTER2 =
POINTER2 + 1
POINTF:R3 =
POINTER3 + 1
COUNT = COUNT
- 1

The subroutine performs multiple-precision binary addition.

0020 ORG $0020


0020 1C FE MPADD ANDCC #%11111110 CLEAR CARRY TO START
0022 M 80 ADBYTE LDA ,X+ GET BYTE FROM FIRS� NUMBER
0024 A9 AO ADCA ,Y+ ADD BYTE FROM SECOND NUMBER
0026 A7 co STA 'U+ STORE RESULT
0028 SA DECB ALL BYTES ADDED?
0029 26 F7 BNE ADBYTE NO, ·CONTINUE
002B 39 RTS

Subroutine Documentation:
*SUBROUTINE MPADD
*
*PURPOSE: MPADD ADDS TWO MULTI-BYTE BINARY NUMBERS
*
*INITIAL CONDITIONS: STARTING ADDRESSES OF NUMBERS (LSB'S) IN
* IN D E X REGISTERS X AND Y, STARTING ADDRESS OF SUM IN USER
* STACK POINTER U, LENGTH OF NUMBERS (IN BYTES) IN ACCUMULATOR B
*
*REGISTERS AFFECTED: A,B ,X,Y,U,FLAGS
*
*SAMPLI': CASE:
* INITIAL CONDITIONS: (X) = 0048, (Y) 004C, (U) = 0050,
* (B) = 02, (0048) = C3, (0049) = A7, (004C) = 88, (OO�D) 35
* RESULT: (0050) = 78, (0051) = DD
*

This subroutine has four parameters - three addresses and the length of the
numbers. We use Index Register X, Index Register Y, User Stack Pointer U, and
Accumulator B to pass them; no results are returned. User Stack Pointer U is really just
Subroutines 10-15

an extra index register. It is, in fact, somewhat more useful than Index Register Y since
LOU and STU execute faster than LOY and STY. The reason for this difference is that
LOU and STU require 1-byte operation codes, while LOY and STY require 2-byte
operation codes. Note, however, that CMPU requires a 2-byte operation code, so U is
slightly inferior to X. A further advantage of U which we will discuss shortly is the
availability of the PSHU and PULU instructions, which can transfer an entire set of
registers to or from the User Stack.

POSITION-INDEPENDENT CODE

Position-independent routines can be placed anywhere in memory without


using a relocating loader and can be used with any combination of other programs.
The keys to writing position-independent code are:

1. Use relative branches (BSR, LBSR, BRA, LBRA), rather than JSR or JMP.
2. Refer to variables by means of the indexed addressing modes that use a
constant offset from the Program Counter. Remember that the assembler
will calculate a relative offset for you if you specify the address as OEST, PCR.
Thus the instruction
LDA RDATA, PCR

will load Accumulator A from the relative address ROATA. You can use the
indirect version to access data through addresses that are stored relatively.

3. Use the Hardware Stack for temporary storage. You can assign five Stack
locations for temporary storage by subtracting five from the Hardware Stack
Pointer with the instruction
LEAS -5,5

You can then refer to these locations with indexed offsets and finally discard
them with the instruction
LEAS 5,5

Note that such temporary storage locations are only allocated when the routine is
actually executed (referred to as dynamic allocation); they need not be permanently
assigned as fixed memory locations must be (referred to as static allocation). This use of
the Hardware Stack for temporary storage also promotes reentrancy, since Stack loca­
tions are saved automatically when routines are interrupted or suspended.
If necessary, you can always determine the current value of the Program Counter
by means of an instruction like
TFR PC, X

which saves its absolute value (the address of the byte following the TFR instruction) in
Index Register X. The program can thereby calculate its actual location in memory.
10-16 6809 Assembly Language Programming

NESTED SUBROUTINES

The BSR and JSR instructions allow the nesting of subroutines, since subse­
quent subroutine calls will place their return addresses on top of the previous return
addresses. No addresses are ever lost and an RTS instruction always returns control to
the instruction just after the most recent BSR or JSR.

Jump and Link

We can use other methods to call one level of subroutine. For example, the
instruction
EXG X, PC

loads the Program Counter with the previous contents of Index Register X and Index
Register X with the previous contents of the Program Counter. This is equivalent to
transferring control to the address in Index Register X, while saving the return address
in that index register. However, this approach does not allow nesting, since Index
Register X can only hold a single return address. Furthermore, it ties up Index Register
X and makes the program rather difficult to follow. If you use this approach, remember
that the instruction
EXG X,PC

at the end of the subroutine will transfer control back to the main program (as long as
you have not disturbed Index Register X) and will save the address immediately follow­
ing the EXG instruction in Index Register X. This approach is often referred to as
jump-and-link, since it uses Index Register X as the link back to the main program.

PROBLEMS

Note that you are to write both a calling program for the sample problem and a
properly documented subroutine.

10-1. CONVERT ASCII TO HEXADECIMAL

Purpose: Convert the contents of Accumulator A from the ASCII representation of a


hexadecimal digit to the actual digit. Place the result in Accumulator A.

Sample Problems:

a. (A) 43 · c·

Result: (A) oc

b. (A) 36 '6'

Result: (A) 06
Subroutines 10-17

10-2. LENGTH OF A TELETYPEWRITER MESSAGE

Purpose: Determine the length of an ASCII-coded teletypewriter message. The starting


address of the string of characters in which the message is embedded is in
Index Register X. The message itself starts with an ASCII STX character
(02 1 6) and ends with ASCII ETX (0316). Place the length of the message (the
number of characters between the STX and the ETX) in Accumulator B.

Sample Problem:

(X) 0044 Starting address of string


(0044) 49
(0045) 02 STX
(0046) 47 'G'
(0047) 4F '0'
(0048) 03 ETX

Result (B) 02 since there are 2 characters between the ASCII


STX and the ASCII ETX.

10-3. MINIMUM VALUE

Pupose: Find the smallest element in an array of 8-bit unsigned binary numbers. The
length of the array (number of bytes) is in Accumulator B and the starting
address of the array is in Index Register X. The minimum value is returned in
Accumulator A.

Sample Problem:

IB) 05 Length of array (number of bytes)


(X) 0043 Starting address of array

(0043) 67
(0044) 79
(0045) 15
(0046) E3
(0047) 73

Result: (A) 1 5 since this is the smallest of the five


unsigned numbers.

10-4. STRING COMPARISON

Purpose: Compare two strings of ASCII characters to see which is larger (i.e., which
follows the other in 'alphabetical' ordering). The length of the strings is in
Accumulator B. The starting address of string 1 is in Index Register X and the
starting address of string 2 is in Index Register Y. If string I is larger than or
equal to string 2, clear Accumulator B; otherwise, set Accumulator B to FF16.

Sample Problems:

a. (B) 03 Length of strings


(Xl 0046 Starting address of string '*f1
(Yl 004A Starting address of string '*f2

(0046) 43 'C'

(0047) 41 ' A'


(0048) 54 'T '

(004A) 42 ' B'

(004B) 41 'A'

(004C) 54 'T '

Result: (B) 00 since CAT is .. larger.. than BAT


10-18 6809 Assembly Language Programming

b. (B) 03 Length of strings


(X) 0046 Starting address of string =lf1
(Y) 004A Starting address of string =lf2

(0046) 44 ·c·
(0047) 41 'A '
(0048) 54 ·r

(004A) 44 'C'
(0048) 41 'A'
(004C) 54 ·r

Result: (B) 00 since the two strings are the same

c. (B) 03 Length of strings


(X) 0046 Starting address of string =lfl
(Y) 004A Starting address of string =lf2

(0046) 43 ·c·
(0047) 41 ' A'
(0048) 54 T

(004A) 43 'C'
(004B) 55 ·u·
(004Cl 54 T

Result: (B) FF since CUT is "larger" than CAT

10-5. DECIMAL SUBTRACTION

Purpose: Subtract one multi-digit decimal (BCD) number from another. The length of
the numbers (in bytes) is in Accumulator Band the starting addresses of the numbers
are in Index Registers X and Y. Subtract the number with the starting address in Index
Register Y from the one with the starting address in Index Register X. The starting
address of the result is in the user Stack Pointer U. All the numbers begin with the least
significant digits. The sign of the result is returned in Accumulator B- zero if the result
is positive, FF if it is negative.

Sample Problem:

(B) 04 Length o f numbers i n bytes


(Xl 0048 Starting address of minuend
(Y) = 004C Starting address of subtrahend
(U) 0050 Starting address of difference

(0048)

��}
(0049)
36701985 is minuend
(004A) 70
(004B) 36

(004C)
(0040)
(004El
(004Fl
;: }
66
12
12663459 is subtrahend

Result: (B)

(0050)
(0051)
00

26
85
} Positive result

24038526 is decimal difference


(0052) 03
(0053) 24
11
Parameter Passing Techniques

In Chapter 10 we defined and briefly discussed parameters and the problem of


transferring parameters to subroutines. The examples in Chapter 10 passed parameters
through the 6809 registers; however, in this chapter we will describe other, more
general methods for passing parameters. Since these parameter passing techniques
make use of the 6809 stacks and stack pointers, we will first discuss the important
stack manipulation instructions PSH and PUL.

THE PSH AND PUL INSTRUCTIONS

We have briefly mentioned the PSH and PUL instructions without fully explor­
ing them. These instructions allow the programmer to transfer sets of registers to and
from the User Stack or the Hardware Stack. Typical uses are to transfer parameters
to the Stack, transfer results from the Stack, and load or store a set of registers with
one instruction.
Each PSH or PUL instruction requires 2 bytes of program memory, one for the
operation code and one to specify the list of registers that will be transferred to or
from the Stack (either the User Stack or the Hardware Stack). The bits in the second
byte of data determine whether particular registers will (if the assigned bit is 1) or will
not (if the assigned bit is 0) be transferred to or from the Stack. Figure 11-1 shows how
the bits are assigned and the order in which registers are pushed (stored on the stack) or
pulled (loaded from the stack). Note that neither Stack Pointer can be stored in or
loaded from its own stack; saving a Stack Pointer in its own stack would be like saving
the key to a locked safe in the safe itself. The push order is, of course, the opposite of the
pull order.
11-2 6809 Assembly Language Programming

4 Pull Order

7 6 5 4 3 2 0 4 B it N umber

Push Order .-

Bit position 6 represents U for PULS and PSHS, S for PULU and PSHU.

Figure 11-1. Assignment of Bits and Orders for PSH and PUL Instructions

The Stack grows downward, so the first registers pushed will end up at the
highest addresses and the first registers pulled will come from the lowest addresses.
16-bit registers are pushed least significant byte first and pulled most significant
byte first, thus maintaining compatibility with the standard 6809 method for storing 16-
bit addresses or data. The 6809's Stack Pointers are decremented before each byte is
stored and incremented after each byte is loaded.
The result is that registers are pushed into either stack as follows:

Immediate data Result if bit is 1 Stack with entire


bit position register set pushed

7 SP-SP-2
STACK-PC
Last byte pushed cc ppqq - 12 "'
6 SP-SP-2
A final SP contents
STACK-U or S

5 SP-SP-2 B
STACK-Y
DP
4 SP-SP-2
XH
STACK-X
XL
3 SP-SP- 1
STACK-DP YH

2 SP-SP- 1 YL
STACK-S
UH or SH
SP-SP- 1
UL or SL
STACK-A
PCH
0 SP-SP- 1
STACK-CC First byte pushed PCL
ppqq =

initial SP contents

The description of PSH in Chapter 22 illustrates


the result of stacking just two registers.

SP represents either the Hardware Stack Pointer (PSHS) or the User Stack Pointer
(PSHU). Either PSH instruction can save any, all, any subset, or none of the user
registers except its own pointer. The assembly language programmer simply provides a
list of registers (in any order) in the operand field. The order in which registers are saved
is a function of the hardware, not of the order in which the programmer specifies them.
Parameter Passing Techniques 11-3

The PULS or PULU instruction pulls the registers from the stack in the following
order:

Immediate data Result if bit is 1 Stack with entire register


bit position set to be pulled

0 CC-STACK
SP- SP + 1
First byte pulled cc ppqq =

A-STACK
SP-- SP + 1 A initial SP contents

2 8-STACK 8
SP-SP + 1 DP
3 DP-STACK
XH
SP-SP + 1
XL
4 X-STACK
SP-SP + 2 YH

5 Y-STACK YL
SP-SP + 2 UH or SH
6 U or S-STACK
UL or SL
SP-SP + 2
PCH
7 PC-STACK
SP-SP + 2 Last byte pulled PCL

ppqq + 12 =

final SP contents

The description of PUL in Chapter 22 illustrates


the result of unstacking just three registers.

PSH and PUL are particularly convenient when the entire state of a task must be
saved or restored because the task has been suspended, preempted, or newly activated.

GENERAL PARAMETER PASSING TECHNIQUES1'2

The registers often provide a fast, convenient way of passing parameters to


subroutines and returning results. The limitations of this method are that it cannot be
expanded beyond the number of registers, it often results in unforeseen side effects, and
it lacks generality_ The tradeoff here is between fast execution time and a more general
approach. Such a tradeoff is common in computer applications at all levels; general
approaches are easy to learn, consistent, and can be automated through the use of
compilers and other systems programs. On the other hand, approaches that take
advantage of the specific features of a particular task require less time and memory.
The choice of one approach or the other depends on your application, but you should
take the general approach (saving programming time and simplifying documentation
and maintenance) unless time or memory constraints force you to do otherwise.

There are two general approaches to passing parameters:

1. Place the parameters (or arguments) immediately after the subroutine call.
2. Transfer the parameters and results on the Hardware Stack.

The first approach is convenient when the parameters are constants for a par­
ticular subroutine call, while the second approach is more general and is usually the
choice made in writing interpreters, compilers, operating systems, and other systems
programs.
11-4 6809 Assembly Language Programming

USING ARGUMENT LISTS


In the first approach, the programmer follows each subroutine call with an
appropriate list of parameters. The list itself must consist of constants if the program is
to execute from ROM, although the constants may be the addresses of variable data or
arrays. The programmer must implement this approach as follows:

1. Use the OAT A directives to store the parameters in program memory. For
the 6809 assembler, the directives are FCB for byte-length data, FOB for 16-
bit data or addresses, and FCC for character data.
2. Access the data by means of the return address that the JSR or BSR instruc­
tion stores at the top of the Hardware Stack. The return address will actually
be the starting address of the list of parameters. You can access the first ele­
ment of the list indirectly with an instruction like
LDA [ ,S]

or you can load the starting address into an Index Register (U, for example)
with an instruction like
LEAU [ ,S]

3. Adjust the return address so that it points to the next executable instruc­
tion. That is, add the length of the parameter list to the actual return address
so that the processor does not accidentally try to execute the subroutine
parameters. If the return address is in the User Stack Pointer U and the
parameters occupy 5 bytes of program memory, the sequence

LEAU 5,U MOVE RETURN ADDRESS PAST PARAMETERS


STU ,S SAVE ADJUSTED RETURN ADDRESS IN STACK
R'rS

will return control to the next executable instruction.

EXAMPLES

11-1a. LENGTH OF A STRING OF CHARACTERS


Purpose: Determine the length of a string of ASCII characters. The terminating
character and the starting address of the string follow the subroutine call. The
length of the string (excluding the terminating character) is returned in
Accumulator B. No other registers are affected.
Sam ple Problems:
a. The subroutine call is followed by:

FCB $00 TERMINATING CHARACTER


FDB $43 STARTING ADDRESS OF STRING

(0043) 52 'R '

(0044) 41 'A'
(0045) 54 T
(0046) 48 'H'
(0047) 45 'E'
(0048) 52 'R '

(0049) OD CR

Result: (B) 06
Parameter Passing Techniques 11-5

b. The subroutine call is followed by:

FCB $00 TERMINATING CHARACTER


FOB $43 STARTING ADDRESS OF STRING

(0043) OD CR

Result. (B) 00

Program 11-1 a:

The calling program starts the Stack at memory location OOFF, calls the string
length subroutine (specifying the terminator and starting address in the next three
bytes), and stores the result in memory location 0042.

0000 ORG $0000


0000 l OCE 0100 LDS #$100 START STACK AT MEMORY LOCATION
* OOFF
0004 B D 0020 JSR STLEN DET�RMINE STRING LENGTH
0007 OD FCB $00 STRING TERMINATOR
0008 0043 FOB $43 STARTING ADDRESS OF STRING
OOOA D 7 42 STB $4 2 SAVE STRING LENGTH
oooc 3F SWI
*
*

0020 ORG $0020


0020 34 53 STLEN PSHS U,X,A,CC SAVE REGISTERS
0022 EE 66 LOU 6,S ACCESS PARAMETER LIST
0024 37 12 PULU A,X GET STRING TERMINATOR,
0026 C6 FF LDB II$FF STARTING ADDRESS
0028 sc CHKTRM INCB ADD 1 TO STRING LENGTH
0029 A1 80 CMPA ,X+ IS NEXT CHARACTER A TERMINATOR?
002B 26 FB BNE CHKTRM NO, KEEP LOOKING
002D EF 66 STU 6,S MOVE RETURN ADDRESS PAST
* PARAMETER LIST
002F 35 03 PULS PC ,U,X,A,CC RESTORE REGISTERS AND
* RETURN

Subroutine Documentation:

*SUBROUTINE STLEN
*
* PURPOSE: STLEN DETERMINES THE LENGTH OF A STRING (NUMBER OF
* CHARACTERS PRECEDING A TE R M INATOR )
*
*INITIAL CONDITIONS: TERMINATOR IN BYTE IMMEDIATELY FOLLOWING
* SUBROUTINE CALL, STARTING ADDRESS OF STRING IN NEXT TWO
* 8YTES (MSA'S IN FIRST BYT E)
*
*FINAL CONDITIONS: NUMBER OF CHARACTERS IN B
*
*REGISTERS AFFECTED: B
*
*SAMPLE CASE:
* OD,
INITIAL CONDITIONS: TERMINATOR � STARTI N G ADDRESS 0042
* (0042) = 4D, (004ll 41, (ooa4) � 4E, ( 0 04 5 ) � oo
* f'INAL CONDITIONS: (B) = 03
*
*TYPICAL CALL:
* .JSR STLEN
* FCB TERM TERMINATOR
* FOB START STARTING ADDRESS OF STRING
*

The parameters follow the subroutine call in memory. We are mixing instructions
and assembler directives, a practice that is acceptable as long as the processor never acci­
dentally executes anything that is not an instruction. The result ofthe JSR instruction is:
11-6 6809 Assembly Language Programming

((5)-1) = (OOFF)-(PCL) = 07
((5)-2) = (OOFE)-(PCHl = 00
(8)-(8) - 2 = OOFE

The subroutine begins by storing all the incidental registers that it uses in the
Stack with PSHS. The result is:
((5) -1 l = (OOFD)-(UL)
((8)-2) = (OOFC)-(UHl
((8)-3) = (OOFBJ-(XL)
((5)-4) = (OOFAl-(XH)
((5)-5) = (00F9)-(Al
((5)-6) = (OOF8)-(CC)
(8)-(5) - 6 = OOFE - 6 = OOFB

Now the instruction LOU 6,S loads the return address from memory locations
OOFE and OOFF into the User Stack Pointer.

(U) -((5)+6):((8)+7) = (OOF8+6l (OOF8+ 7) = (OOFE)(OOFF) = 0007

The instruction PULU A,X loads the parameters into Accumulator A (the ter­
minating character) and Index Register X. Note that the order of the parameters is criti­
cal- it must be the same as the pulling order of PULU.

(A)- ((U)) = (0007) = OD


(XH)-((U) + 1) = (0008) = 00
(XL)-((U) + 2) = (0009) = 43
(U)-(U) + 3 = OOOA

Not only does PULU load all the parameters into the registers, but it also adjusts
the return address to the end of the parameter list.
After the length of the string has been determined in the same way as before, the
instruction STU 6,S saves the adjusted return address in the Hardware Stack.

((8) + 6) = (00F8 + 6) = (OOFE)-(UH) = 00


((8) + 7) = (OOFB + 7) = (OOFF)-(UL) = OA

Finally PULS PC,X,U,A,CC restores all the registers and transfers control back to
the main program. No RTS instruction is necessary.
(CC)-((5)) = (00F8)
(A)-((8)+1) = (00F9)
(XH)-((5)+2) = (OOFA)
(XL)-((5)+3) = (OOFB)
(UH)-((8)+4) = (OOFC)
(UL)-((5)+5) = (OOFD)
(PCH)-((5)+6) = (OOFE) = 00
(PCL) -((8) + 7) = (OOFF) = OA
(8)-(S) + 8 = OOFB + 8 = 0100

Obviously the programming here is a great deal more complex and harder to
understand than in the earlier version, Program J 0-2. However, this version is
reentrant, general, has no incidental side effects, and allows simple variation of the
starting address and terminating character in different calls. Other parameters that we
could add easily include a limiting number of characters (the maximum number that the
routine will examine), an error exit (in the event that the processor does not find a ter­
minating character), a starting character, and a memory address in which to store the
result. You might try to expand the routine in a general way to include some or all of
these parameters.
Parameter Passing Techniques 11-7

11-2a. MULTIPLE-PRECISION ADDITION

Purpose: Add two multi-byte binary numbers. The starting addresses of the numbers
and the result, as well as the length of the numbers in bytes, follow the
subroutine call. No registers or flags are affected.

Sample Problem:

The subroutine call is followed by:

FCB 4 LENGTH OF STRINGS (IN BYTES)


FOB $48 ADDRESS OF LSB'S OF 1ST NUMBER
FOB $4C ADDRESS OF LSB'S OF 2ND NUMBER
FOB 50 ADDRESS OF LSB'S OF SUM

(0048) C3
(0049) A7
2F5BA7C316 is first number
(004A) 58
(0048) 2F

(004C) 88
(0040) 35
14DF35BS16 is second number
(004E) DF
(004Fl 14

Result: (0050) 78
(0051) DD
(0052) 3A 443ADD7B16 is sum
(0053) 44

Program 11-2a:

The calling program starts the Stack at memory location OOFF and calls the multi­
ple-precision addition subroutine, specifying the length (in bytes) and the starting
addresses of the operands and sum in the next seven bytes.

0000 ORG $0000


0000 lOCE 0100 LDS J$100 START STACK AT MEMORY LOCATION
*
OOFF
0004 BD 0020 JSR MPADD PERFORM MULTIPLE-PRECISION
*
ADDITION
0007 04 FCB 4 LENGTH OF STRINGS (IN BYTES)
0008 0048 FDB $48 ADDRESS OF LSB'S OF FIRST NUMBER
OOOA 004C FDB $4C ADDRESS OF LSB'S OF SECOND
*
NUMBER
oooc 0050 FDB $50 ADDRESS OF LSB'S OF SUM
OOOE 3F SWI
*

0020 ORG $0020


0020 34 77 MPADD PSHS X,Y,U,A,B,CC SAVE ALL REGISTERS
0022 EE 69 LDU 9,S ACCESS PARAMETER LIST
0024 37 34 PULU X,Y,B GET LENGTH, ADDRESSES OF
*
OPERANDS
0026 EE' C4 LDU ,U GET ADDRESS OF SUM
0028 lC FE ANDCC #%11111110 CLEAR CARRY TO START
002A A6 80 ADBYTE LDA ,X+ GET BYTE FROM FIRST NUMBER
002C A9 AO ADCA ,Y+ ADD BYTE FROM SECOND NUMBER
002E A7 co STA ,U+ STORE RESULT
0030 SA DECB ALL BYTES ADDED?
0031 26 F7 BNE ADBYTE NO, CONTINUE
0033 EE 69 LDU 9,S A�JUST RETURN ADDRESS PAST
0035 33 47 LEAU 7,U ARGUMENT LIST
0037 EF 69 STU 9,S
0039 35 F7 PULS PC,U,Y,X,B,A,CC RESTORE REGISTERS AND
*
RETURN
11-8 6809 Assembly Language Programming

Subroutine Documentation:
*
SUBROUTINE MPADD
*
* PURPOSE: MPADD ADDS TWO MULTI-BYTE BINARY NUMBERS
*
* INITIAL CONDITIONS: SUBROUTINE CALL IS FOLLOWED BY LENGTH OF
* STRINGS (IN BYTES), STARTING ADDRESSES OF LSB'S OF OPERANDS,
* AND STARTING ADDRESS OF LSB'S OF SUM
*
* REGISTERS AFFECTED: NONE
*
* SAMPLE CASE:
* INITIAL CONDITlONS: LENGTH = 02, OPERAND ADDRESSES = 0048 AND
* 004C,
* ADDRESS OF SUM = 0050
* (0048) = C3, (0049) = A7, (004C) = B8, (004D) = 35
* RESULT: (0050) = 7B, (0051) = DD (A7C3 + 35B8 = DD7B)
*
*TYPICAL CALL:
* JSR MPADD
* FCB LNGTH LENGTH OF STRINGS (IN BYTES)
* FOB OPERI STARTING ADDRESS (LSB'S) OF OPERAND 1
* FDB OPER� STARTING ADDRESS (LSB'S) OF OPERAND 2
* FDB SUM STARTING ADDRESS (LSB'S) OF SUM

The only new problem here is that we cannot pull U from its own stack and we are
very reluctant to changeS (since it is used automatically in interrupts as we shall see in
Chapter 15). So we must tiptoe around this limitation, retaining reentrancy as follows:

1. PULU X,Y,B loads the length of the numbers into Accumulator B and the
starting addresses of the operands into Index Registers X andY, respectively.

2. LDU , U loads the starting address of the result into the UserStack Pointer U.

3. The ending sequence


LDU 9,S
LEAU 7,U
STU 9,S

adds 7 to the return address stored in theStack, so that it now points to the
address immediately following the list of arguments.

PASSING PARAMETERS ON THE STACK

In the second approach, all parameters and results are passed in the Hardware
Stack. Here the parameters can be variables, since they are placed in RAM, not in ROM.
The programmer must implement this approach as follows:

1. Use the LEAS instruction to decrement the Hardware Stack Pointer to


leave room for results on the Hardware Stack.
2. Use the PSHS instruction to save all the parameters on the Hardware
Stack.
3. Access the parameters by means of indexed offsets from the Hardware
Stack Pointer, remembering that JSR or BSR places the return address at the
top of the Stack. The User Stack Pointer can be used to remove many
parameters at once.
4. Access the results by means of indexed offsets from the Hardware Stack
Pointer. Again, the UserStack Pointer can be used to store many results at
one time.

5. Clean up the stack after returning from the subroutine, so that the
parameters are removed and the results are handled appropriately.
Parameter Passing Techniques 11-9

11-1 b. LENGTH OF A STRING OF CHARACTERS

Purpose: Determine the length of a string of ASCII characters. The starting address of
the string and the terminating character are placed in the Hardware Stack. The
length of the string (excluding the terminating character) is returned at the
top of the Hardware Stack. No registers are affected.

Sample Problems:

a. The subroutine call occurs with the top of the Hardware Stack containing:

OD String terminator
00 MSBs of starting address of string
43 LSBs of starting address of string
empty byte "Hole" for length of string

(0043) 52 ' R'

(0044) 41 ' A '

(0045) 54 T
(0046) 48 'H'

(0047) 45 ' E '

(0048) 52 'R'

(0049) OD CR

Result: The top of the Hardware Stack contains:

OD String terminator
00 MSBs of starting address of string
43 LSBs of starting address of string
06 Length of string (in bytes)

/ b. The subroutine call occurs with the top of the Hardware Stack containing:

OD String terminator
00 MSBs of starting address of string
43 LSBs of starting address of string
empty byte "Hole" for length of string

(0043) = OD CR

Result: The top of the Hardware Stack contains:

00 String terminator
00 MSBs of starting address of string
43 LSBs of starting address of string
00 Length of string (in bytes)

Program 11-1 b:

The calling program starts the stack at memory location OOFF, leaves an empty
byte on the stack for the string length, stores the terminator and starting address on the
stack, calls the string length subroutine, removes the parameters from the stack (by
incrementing the Hardware Stack Pointer), loads the string length from the stack, and
stores the string length in memory location 0042.

0000 ORG $0000


0000 lOCE 0100 LDS J$100 START STACK AT MEMORY LOCATION
*
DOFF
0004 32 7F LEAS -1,S LEAVE ROOM FOR LENGTH OF STRING
0006 86 OD LDA I SOD GET TERMINATOR
0008 BE 0043 LDX f$43 GET STARTING ADDRESS OF STRING
OOOB 34 12 PSHS A,X SAVE PARAMETERS IN HARDWARE
*
STACK
11-10 6809 Assembly Language Programming

0000 BD 0020 JSR STLEN DETERMINE STRING LENGTH


0010 32 63 LEAS 3,S REMOVE PARAMETERS FROM STACK
0012 35 02 PULS A GET STRING LENGTH FROM STACK
0014 97 42 STA $42 SAVE StRING LENGTH
0016 3F SWI
*
*

0020 ORG $0020


0020 34 57 STLEN PSHS U,X,B,A,CC SAVE REGISTERS
0022 33 69 LEAU 9,S ACCESS PARAMETER LIST IN STACK
0024 37 12 PULU A,X GET STRING TERMINATOR,
* STARTING ADDRESS
0026 C6 FF LOB #$FF STRING LENGTH = -1
0028 5C CHKTRM !NCB ADD 1 TO STRING LENGTH
0029 A 1 80 CMPA ,X+ I S NEXT CHARACTER A TERMINATOR?
0028 26 FB BNE CHKTRM NO, KEEP LOOKING
0020 E7 C4 STB ,U SAVE STRING LENGTH IN STACK
002F 35 07 PULS PC,X,U,B,A,CC RESTORE REGISTERS AND
* RETURN

Subroutine Documentation:

* S UBROUTINE STLEN
*
*PURPOSE: STLEN DETERMINES THE LENGTH OF A STRING (NUMBER OF
* CHARACTERS PRECEDING A TERMINATOR)
*
*INITIAL CONDITION S: TERMINATOR ON TOP OF STACK, FOLLOWED BY
* S T ARTING ADDRE S S OF STRING A N D AN E MP T Y BYTE FOR THE S TRING
* LENGTH
*
* FINAL CONDITIONS: STRING LENGTH ON STACK UNDER PARAMETERS
*
*REGISTERS AFFECTED: NONE
*
* S AMPLE CASE:
* INITIAL CONDITIONS: TERMINATOR = OD, STARTING ADDR ES S 0042
* (0042) = 4D, (0043) = 41, (0044) = 4E, (0045) = OD
* FINAL CONDITION S: STRING LENGTH = 03
*
* TYPICAL CALL:
*
* LEAS -l,S LEAVE EMPTY BYTE FOR LENGTH OF STRING
* LOA #TERM S T R I NG TERM INA TOR
* LOX #ST!I.RT STARTING ADDRESS OF STRING
* PSHS A,X SAVE PAtlAMETERS IN STACK
* J SR STLEN DETERMINE STRING LENGTH
*

Here the idea is to leave space for the results on the stack, store the parameters on
top of that space, call the subroutine, save the registers, use the parameters to calculate
the results, save the results on the Stack, restore the registers, return to the main pro­
gram, clear the parameters from the stack by increasing the Stack Pointer, and remove
the results from the top of the stack.
LEAS -1 ,S leaves one location in the Stack for the length of the string. The result
is:
IS)�(S) - 1 = 0100 - 1 = OOFF

The processor does not store anything in the extra stack location.
PSHS A,X stores the parameters in the Hardware Stack. The result is:

((S)-1) (OOFE)-(XL)
= = 43
((S)-2) (OOFD)�(XH)
= =00
((S)-3) (OOFC)-(A)
= = OD
(S)�(Sl - 3 OOFC
=
Parameter Passing Techniques 11-11

JSR STLEN transfers control to the subroutine and saves the return address
(0010) at the top of the Stack. The result is:
((S)-1)"' (OOFB)�(PCL)"' 10
((S)-2) = (OOFA)�(PCH) = 00
(S)-(S) - 2 = OOFC - 2 = OOFA

PSHS U,X,B,A,CC saves all the incidental registers in the Hardware Stack. The
result is:
((Sl-1) = (OOF9)�(UL)
((S)-2) = (00F8)�(UH)
((S)-3) = (00F7)-(XL)
((S)-4) = (00F6)�(XH)
((S)-5) = (OOF5)�(B)
((S)-6) = (00F4)�(A)
((S)-7) = (00F3)-(CC)
(S)�(S) - 7 = OOFA - 7 = OOF3

LEAU 9,S loads the User Stack Pointer with the starting address of the list of
parameters.
(U)�(S) + 9 = OOF3 + 9 = OOFC

PULU A,X loads the parameters into Accumulator A (the terminating character)
and Index Register X (the starting address of the string).

(A)-((U)) = (OOFC) = OD
(XH)�((U)+1) = (OOFD) = 00
(XL)-((U)+2) = (OOFE) = 43
(U) �(U) + 3 = OOFC + 3 = OOFF

STB ,U stores the length of the string in the "hole" in the stack.

((U)) = (OOFF)-(B)

PULS PC,X,U,B,A,CC restores all the incidental registers and transfers control
back to the main program.

(CC)�((S) = (OOF3)
(A)�((S)+ 1) = (00F4)
(B)-((5)+2) = (00F5)
(XH)�((S)+3l = (00F6)
(XL)�((S)+4) = (00F7)
(UH)�((S)+5) = (OOF8)
(UL)-((5)+6) = (OOF9)
(PCH)�((S)+7) = (OOFA) = 00
(PCL)-((5)+8) = (OOFB) = 10
(S)�(Sl +9 = OOF3 + 9 = OOFC

Back in the main program, LEAS 3,S cleans the stack, essentially removing all the
parameters.
(Sl-15)+3 = OOFC + 3 = OOFF

Finally PULS A removes the result (the length of the string) from the Hardware
Stack.
(A)�((S)) = (OOFF)
(S)�(S)+1 = OOFF + 1 = 0100

Here again the programming is more complex and harder to understand than in
our initial simple version, but this version is also reentrant, general, has no incidental
side effects, and allows simple variation of parameters and generalization.
11-12 6809 Assembly Language Programming

11-2b. MULTIPLE-PRECISION ADDITION

Purpose: Add two multi-byte binary numbers. The starting addresses of the numbers
and the result, as well as the length of the numbers in bytes, are on the Hard­
ware Stack. The starting address of the result ends up at the top of the Hard­
ware Stack. No registers or flags are affected.

Sample Problem:

The subroutine call occurs with the top of the Hardware Stack containing:

04 Length of strings (in bytes)

}
00 Starting address of operand 1
48

00
4C
} Starting address of operand 2

}
}
00
Starting address of sum
50

(0048) C3
(0049) A7

}
2F5BA7C316 is first number
(004A) 58
(0048) 2F

(004C) =
88
(0040) 35

}
14DF35B816 is second number
(004E) OF
(004Fl 14

Result: (0050) 78
(0051) DO
443ADD7E!,6 is sum
(0052) 3A
(0053) 44

The Hardware Stack is unchanged.

Program 11-2b:

The calling program starts the stack at memory location OOFF, stores the starting
addresses of the strings and the length in the stack, calls the multiple-precision addition
subroutine, removes the parameters from the stack (by increasing the Hardware Stack
Pointer), loads the starting address of the sum from the stack, and stores the starting
address in memory locations 0040 and 0041.

0000 ORG $0000


0000 lOCE 0100 LOS J$100 START STACK AT MEMORY LOCATION
*
OOFF
0004 CE 0050 LOU t$50 GET STARTING ADDRESS OF RESULT
0007 8E 0048 LOX 1$48 GET STAR!ING ADDRESSES OF
* OPERANDS
OOOA 108E 004C LOY I$4C
OOOE 86 04 LOA 14 GET LENGTH OF STRINGS
0010 34 72 PSHS U,Y,X,A SAVE PARAMETERS IN HARDWARE
* STACK
0012 BD 0020 JSR MPADD PERFORM MULTIPLE-PRECISION
* ADDITION
Parameter Passing Techniques 11-13

0015 32 65 LEAS 5,S REMOVE PARAMETERS FROM STACK


0017 35 10 PULS X GET ADDRESS OF RESULT
0019 9F 40 STX $40 SAVE ADDRESS OF RESULT IN MEMORY
0018 3F SWI
*

0020 ORG $0020


0020 34 77 MPADD PSHS U,Y,X,B,A,CC SAVE REGISTERS
0022 33 !)B LEAU 1l,S ACCESS PARAMETER LIST IN STACK
0024 37 34 PULU X,Y,B GET LENGTH, ADDRESSES OF
*
OPERANDS
0026 EE C4 LOU ,u GET STARTING ADDRESS OF RESULT
0028 1C FE ANDCC 1%11111110 CLEAR CARRY TO START
002A AI) 80 ADBYTE LOA ,X+ GET BYTE FROM FIRST NUMBER
002C A9 AO ADCA ,Y+ ADD BYTE FROM SECOND NUMBER
002E A7 co STA 'U+ STORE RESULT
0030 SA DECB ALL BYTES ADDED?
0031 26 F7 BNE ADBYTE NO, CONTINUE
0033 35 F7 PULS PC,U,Y,X,B,A,CC RESTORE REGISTERS AND
* RETURN

Subroutine Documentation:

•SUBROUTINE MPADD
*
* PURPOSE: MPADD ADDS TWO MULTI-BYTE BINARY NUMBERS
*
*INITIAL CONDITIONS: LENGTH OF STRINGS (IN BYTES) ON TOP OF
* STACK, FOLLOWED BY STARTING ADDRESSES OF LSB'S OF OPERANDS
* AND STARTING ADDRESS OF LSB'S OF SUM
*
*REGISTERS AFFECTED: NONE
*
*SAMPLE CASE:
* INITIAL CONDITIONS: LENGTH = 02, OPERAND ADDRESSES = 0048
* AND 004C,
* ADDRESS OF SUM 0050
=

* (0048) = C3, (0049) A7, = (004C) = 88, (0040) = 35


* RESULT: (0050) = 78, (0051) = DD ( A7C3 + l5B8 = DD7B)
*
*TYPICAL CALL:
* LDX #OPERl STARTING ADDRESS (LSB'S) OF OPERAND l
* LDY #0PER2 STARTING ADDRESS (LSB'S) OF OPERAND 2
* LDU #SUM STARTING ADDRESS (LSB'S) OF SUM
* LDA LENGTH OF STRINGS (IN BYTES)
#LENGTH
* PSHS U,Y,X,A SAVE PARAMETERS IN HARDWARE STACK
* JSR MPADD PERFORM MULTIPLE-PRECISION ADDITION
*

TYPES OF PARAMETERS
Regardless of our approach to passing parameters, we can specify the
parameters in a variety of ways. For example, we can:

1. Place the actual values in the parameter list. We can use immediate
addressing or OATA directives and retrieve the data, if necessary, by using
indexed offsets. This method is sometimes referred to as call-by-value, since
only the values of the parameters are of concern.
2. Place the addresses of the parameters in the parameter list. We can use
address-length registers or retrieve the data by using the indexed indirect
modes. This method is sometimes referred to as call-by-name, since we are
concerned with the locations of the parameters as well as their values.
11-14 6809 Assembly Language Programming

REFERENCES

1. C. W. Gear. Computer Organization and Programming, 3rd ed., McGraw-Hill, New


York, 1980, Chapter 4.
2. S. Mazor and C. Pitchford. "Develop Cooperative Microprocessor Subroutines,"
Electronic Design, June 7, 1978, pp. 116- 118. Examples are for the 8080
microprocessor.
12
Input/Output

There are two problems in the design of input/output routines: one is how to
interface peripherals to the computer and transfer data, status, and control signals;
the other is how to address 1/0 devices so that the CPU can select a particular one for
a data transfer. Clearly, the first problem is both more complex and more interesting.
We will therefore discuss the interfacing of peripherals here and leave addressing to a
more hardware-oriented book.

1/0 AND MEMORY

In theory, the transfer of data to or from an 1/0 device is similar to the transfer
of data to or from memory. In fact, we can consider the memory as just another 1/0
device. The memory is, however, special for the following reasons:

1. It operates at almost the same speed as the processor.


2. It uses the same type of signals as the CPU. The only circuits usually needed
to interface the memory to the CPU are drivers, receivers, and level transla­
tors.
3. It requires no special formats or any control signals besides a Read/Write
pulse.
4. It automatically latches data sent to it.
5. lts word length is the same as the computer's.

Most 1/0 devices do not have such convenient features. They may operate at
speeds much slower than the processor; for example, a teletypewriter can transfer only
10 characters per second, while a slow processor can transfer 10,000 characters per sec-
12-2 6809 Assembly Language Programming

ond. The range of speeds is also very wide - sensors may provide one reading per
minute, while video displays or floppy disks may transfer 250,000 bits per second.
Furthermore, I/0 devices may require continuous signals (motors or thermometers),
currents rather than voltages (teletypewriters), or voltages at far different levels than
the signals used by the processor (gas-discharge displays). 1/0 devices may also require
special formats, protocols, or control signals. Their word lengths may be much shorter
or much longer than the word length of the computer. These variations make the
design of 1/0 routines difficult and mean that each peripheral presents its own
special interfacing problem.

1/0 DEVICE CATEGORIES


We may, however, provide a general description of devices and interfacing
methods. We may roughly separate devices into three categories, based on their data
rates:

l. Slow devices that change state no more than once per second. Changing
their states typically requires milliseconds or longer. Such devices include
lighted displays, switches, relays, and many mechanical sensors and actua­
tors.
2. Medium-speed devices that transfer data at rates of 1 to 10,000 bits per sec­
ond. Such devices include keyboards, printers, card readers, paper tape
readers and punches, cassettes, ordinary communications lines, and many
analog data acquisition systems.
3. High-speed devices that transfer data at rates of over 10,000 bits per sec­
ond. Such devices include magnetic tapes, magnetic disks, high-speed line
printers, high-speed communications lines, and video displays.

INTERFACING SLOW DEVICES

The interfacing of slow devices is simple. Few control signals are necessary
unless the devices are multiplexed, that is, several are handled from one port, as
shown in Figures 12-1 to 12-4. Input data from slow devices need not be latched, since it
remains stable for a long time interval. Output data must, of course, be latched. The
only problems with input are transitions that occur while the computer is reading the
data. One-shots, cross coupled latches, or software delay routines can smooth the transi­
tions.
A single port can handle several slow devices. Figure 12-1 shows a demultiplexer
that automatically directs the next output data to the next device by counting output
operations. Figure 12-2 shows a control port that provides select inputs to a demulti­
plexer. The data outputs here can come in any order, but an additional output instruc­
tion is necessary to change the state of the control port. Output demultiplexers are com­
monly used to drive several displays from the same output port. Figures 12-3 and 12-4
show the same alternatives for an input multiplexer.
Note the differences between input and output with slow devices.

l. Input data need not be latched since the input device holds the data for an
enormous length of time by computer standards. Output data must be latched
since the output device will not respond to data that is present for only a few
Input/Output 12-3

Data Outputs 0

Output
� Data "
Data Bus � "\ /
... Port ., Inputs

Data Outputs
"
Strobe

Port
:)
Selection Demultiplexer
Logic Data Outputs 2
...
Clock
..

-. Select
Counter Data Outputs 3
- Inputs
-"

The Counter controls where the Demultiplexer sends the data.

Figure 12-1. An Output Demultiplexer Controlled by a Counter

Data Outputs 0
_A

r
D a ta ...

?
Data
Port
'
Inputs
Data Outputs
_,._
..

Data Bus Demultiplexer


Data Outputs 2
_Jo...
..


Control -- Select 3
Data Outputs
... Inputs
Port "

The CPU sends control information to the Control Port; that port then determines where the
Demultiplexer sends the data.

Figure 12-2. An Output Demultiplexer Controlled by a Port


12-4 6809 Assembly Language Programming

Data Inputs 0
A

..

A Input Data
Data Bus
Port .. Outputs

Data Inputs
_.
Enable

Port
"'
Selection -
� Multiplexer
Logic lr Data Inputs 2
A
Clock
"

--
- Select
Counter Data Inputs 3
Inputs ..._

' \

The Counter controls which input the Multiplexer routes to the Input Port.

Figure 12-3. An Input Multiplexer Controlled by a Counter

Data Inputs 0
..

Input A_ Data Data
Data Bus Port ' Outputs

Data Inputs
..

..

Multiplexer
Data Inputs 2
..._

"
l

Output ... Control -- Select


Data Bus
t ... Port : Inputs A
Data Inputs 3


'-

The control information which the CPU sends to the Control Port (with an output operation)
determines which input the Multiplexer routes to the Data Port.

Figure 12-4. An Input Multiplexer Controlled by a Port


Input/Output 12-5

CPU clock cycles. Remember that the CPU is constantly using its data bus to
perform ordinary memory transfers.
2. Input transitions cause problems because of their duration; brief output
transitions cause no problems because the output devices (or the observers)
react slowly.
3. The major constraints on input are reaction time and responsiveness; the
major constraints on output are response time and observability.

INTERFACING MEDIUM-SPEED DEVICES

Medium-speed devices must be synchronized in some way to the processor


clock. The CPU cannot simply treat these devices as if they held their data forever or
could receive data at any time. Instead, the CPU must be able to determine when a
device has new input data or is ready to receive output data. It must also have a way of
telling a device that new output data is available or that the previous input data has been
accepted. Note that the peripheral may be or contain another processor.

Handshake

The standard unclocked procedure is the handshake. Here the sender indicates
the availability of data to the receiver and transfers the data; the receiver completes
the handshake by acknowledging the receipt of the data. The receiver may control the
situation by initially requesting the data or by indicating its readiness to accept data� the
sender then sends the data and completes the handshake by indicating that data is
available. In either case, the sender knows that the transfer has been completed suc­
cessfully and the receiver knows when new data is available. The handshake procedure
can operate at any speed, since the sender and receiver (not the clock) control the
sequence of events.
Figures 12-5 and 12-6 show typical input and output operations using the
handshake method. The procedure whereby the CPU checks the readiness of the pe­
ripheral before transferring data is called "polling." Clearly, polling can occupy a large
amount of processor time if there are many 1/0 devices. There are several ways of pro­
viding the handshake signals. Among these are:

Separate dedicated 1/0 lines. The processor may handle these as additional
1/0 ports or through special lines or interrupts. The 6809 microprocessor does
not have special serial I/0 lines, but the 6820 and 6821 Peripheral Interface
Adapters (or programmable parallel interface chips) do.
Special patterns on the 1/0 lines. These may be single start and stop bits or
entire characters or groups of characters. The patterns must be easy to dis­
tinguish from background noise or inactive states.

Strobe

We often call a separate 1/0 line that indicates the availability of data or the
occurrence of a transfer a "strobe." A strobe may, for example, clock data into a latch
or fetch data from a buffer.
12-6 6809 Assembly Language Programming

Input
Acknowledge
_...

Data Bus Data


1/0 A
CPU Peripheral
r-..� Section �

Data Ready

a. Peripheral provides data and Data Ready signal to computer 110 section.

Input
Acknowledge

Data Bus Data


1/0 A
CPU '(' Section "
Peripheral
""'
Data Ready
...

b. CPU reads Data Ready signal from 1/0 section (this may be a hardware connection, e.g., interrupt).

Input
Acknowledge
-

Data Bus Data


A 1/0 A
CPU K Section
Peripheral

Data Ready
-

c. CPU reads data from 1/0 section.

Input
Acknowled e _?
Data Bus Data
1/0
CPU Peripheral
Section r-....
Data Ready
...

d. CPU sends Input Acknowledge signal to 1/0 section which then provides Input Acknowledge
signal to Peripheral (this may be a hardware connection).

Figure 12-5. An Input Handshake


Input/Output 12-7

Output
Ready
_

Data Bus Data


1/0 ..
CPU Peripheral
... Section "'
Peripheral
Ready
-

a. Peripheral provides Peripheral Ready signal to computer 1/0 section.

Output
Ready
-

Data Bus Data


A 1/0
CPU Peripheral
...
Section /
Peripheral
Ready
-

b. CPU reads Peripheral Ready signal from 1/0 section (this may be a hardware connection. e.g ..
interrupt).

Output
Ready

Data Bus Data


" 1/0 ..
CPU .
)
.. Section / Peripheral
Periphera r
Ready

c. CPU sends data to Peripheral.

Output
Ready _

Data Bus Data


1/0 A
CPU Peripheral
.. Section
Peripheral
.-Ready
-

d. CPU sends Output Ready signal to Peripheral (this may be a hardware connection).

Figure 12-6. An Output Handshake


12-8 6809 Assembly Language Programming

Many peripherals transfer data at regular intervals: i.e., synchronously. Here the
only problem is starting the process by lining up to the first input or marking the first
output. In some cases, the peripheral provides a clock input from which the processor
can obtain timing information. In synchronous 1/0, the clock controls the speed of the
transfers, rather than the sender and receiver.

Reducing Transmission Errors

Transmission errors are a problem with medium�speed devices. Several


methods can lessen the likelihood of such errors; they include:

Sampling input data at the center of the transmission interval in order to


avoid edge effects; that is, keep away from the edges where the data is chang­
ing.
Sampling each input several times and using majority logic. For example,
one could read each bit 5 times and choose the value that occurred most
often.'
Generating and checking parity; an extra bit is used that makes the number of
l bits in the correct data even or odd.
Using other error detecting and correcting codes such as checksums, LRC
(longitudinal redundancy check), and CRC (cyclic redundancy check) .2

INTERFACING HIGH-SPEED DEVICES

High�speed devices that transfer more than 10,000 bits per second require
special methods. The usual technique is to construct a special�purpose controller that
transfers data directly between the memory and the 1/0 device. This process is called
direct memory access (DMA). The DMA controller must force the CPU off the busses,
provide addresses and control signals to the memory, and transfer the data. Such a con­
troller will be fairly complex, typically consisting of 50 to 100 chips, although LSI
devices such as the 6844 DMA controller3 for 6809-based microcomputers are now
available. The CPU must initially load the Address and Data Counters in the controller
so the controller will know where to start and how much data to transfer.
Input/Output 12-9

TIME INTERVALS

A common problem in 1/0 programming is how to provide time intervals of


various lengths between operations. Such intervals are necessary to debounce
mechanical switches (i.e., to smooth their irregular transitions), to provide pulses with
specified lengths and frequencies for displays, and to time l/0 operations for devices
that transfer data regularly (e.g., a teletypewriter that sends or receives one bit every 9.1
ms).

METHODS FOR PRODUCING TIME INTERVALS

We can produce time intervals in several ways:

1. In hardware with one-shots or monostable multi vibrators. These devices


produce a single pulse of fixed duration in response to a pulse input.
However, one-shots create reliability problems and they should be avoided
whenever possible.
2. In a combination of hardware and software with a flexible device such as the
6840 Programmable Timer for 6809-based microcomputers.<� The 6840 device
can provide time intervals of various lengths with a variety of starting and
ending conditions.
3. In software with delay routines. A delay routine has no purpose other than
to waste time; it is the computer equivalent of counting on your fingers. We
can easily specify how much time the computer is to waste, since we know the
clock speed of our particular microcomputer (this is system-dependent) and
the number of clock cycles required to execute instructions (Appendices B
and C). The problem with pure delay routines is that the processor cannot do
other tasks while it is wasting time; however, delay routines require no hard­
ware and may use processor time that would be wasted anyway.

The choice among these three methods depends on your application. The soft­
ware method is inexpensive but may overburden the processor. The programmable
timers are relatively expensive but are easy to interface and may be able to handle
many complex timing tasks.
The timer in the 6846 Multifunction Support Device (ROM/10/Timer)' is availa­
ble at no extra cost if this part is being used. The part is somewhat more expensive than
simpler devices, but may be justifiable as a complete, one-chip package. 6846 devices
are used in many board-level microcomputers.

DELA V ROUTINES

A simple delay routine works as follows:

STEP 1 - Load a register with a specified value.

STEP 2 - Decrement the register.


STEP 3 - If the result is not zero, repeat STEP 2.

This routine does nothing except use time. The amount of time used depends on
the execution time of the various instructions. The maximum length of the delay is
12-10 6809 Assembly Language Programming

limited by the size of the register; however, the entire routine can be placed inside a
similar routine that uses another register, etc.
Be careful - the actual time used depends on the clock rate at which the pro­
cessor is running, the speed of memory accesses, and operating conditions such as
temperature, power supply voltage, and circuit loading which may affect the speed at
which the processor executes instructions.
The following example subroutine (starting in memory address 0030) uses the
two Accumulators to produce delays as long as 255 ms. The routine saves Accumula­
tor B and the Condition Code Register in the Hardware Stack so they are not changed.
We could use either of the general parameter passing techniques from Chapter 11 to
write a completely "transparent" subroutine that would not affect any registers or flags.
Of course, we would have to include the extra instructions that transfer parameters,
save and restore registers, and adjust the return address in the time budget.

Program Example: A Delay Subroutine

Purpose: The subroutine produces a delay of l ms times the contents of Accumulator


A.

Flowche.ri::

COUNT = MSCNT

COUNT=
COUNT - 1

(A)= (A)- 1

The value of MSCNT depends on the rate at which the CPU executes instruc-
tions.
Input/Output 12-11

Program a:
OOC3 MSCNT EQU SC3
*

ORG $0030
0030 34 05 DELAY PSHS B,CC SAVE INCIDENTAL REGISTERS
0032 C6 C3 DLYl LDB #MSCNT GET COUNT FOR 1 MS DELAY
0034 SA DLY DECB
0035 26 FD BNE DLY COUNT WITH B FOR 1 MS
0037 4A DECA COUNT NUMBER OF MILLISECONDS
0038 26 FB BNE DLYl
003A 35 85 PULS PC,B,CC RESTORE INCIDENTAL REGISTERS
* AND RETURN

Time Budget:
Instruction Number of Times Executed

PSHS B.CC 1
LDB #MSCNT (A)
DECB lA) X MSCNT
BNE DLY lA) x MSCNT
DECA (A)
BNE DLY1 lA)
PULS PC.B.CC 1

The total time used should be (A) x 1 ms. If the memory is operating at full
speed, the instructions require the following numbers of clock cycles (according to
Appendix C).

Instruction Number of Clock Cycles

PSHS B.CC 7
LDB #MSCNT 2
DECA or DECB 2
BNE 3
PULS PC.B.CC 9

Remember that PSHS and PULS require 5 clock cycles plus 1 clock cycle for each
byte pushed or pulled.
Ignoring the Jump or Branch-to-Subroutine instruction (its execution time
depends on the addressing mode used), the program takes

lA) X 17 + 5 X MSCNT) + 1 6 clock cycles

The 7 is the number of cycles required by LDB #MSCNT, DECA, and BNE DL Y L the
5 is the number of cycles required by DECB and BNE DLY; the 16 is the number of
cycles required by PSHS B,CC and PULS PC,B,CC.
So, to make the delay 1 ms,

23 + 5 x MSCNT = Nc

where Nc is the number of clock cycles per millisecond. At a 1 MHz 6809 clock rate, Nc
= 1000 so
5 x MSCNT = 977

MSCNT 195 IC316) at a 6809 clock


=

rate of 1 MHz

The next version is a subroutine using Index Register X to produce a delay of 1


millisecond without affecting any registers.
12-12 6809 Assembly Language Programming

Flowchart:

(X)= MSCNT

(X)= (X)- 1

The value of MSCNT depends on the execution time of the instructions in the
program.

Program b:
007A MSCNT EQU $007A
*

ORG $0030
0030 34 10 DELAY PSHS X
0032 BE 007A LDX fMSCNT GET COUNT FOR 1 MS DELAY
0035 30 1F DLY LEAX -1,X COUNT X DOWN FOR 1 MS
0037 26 FC BNE DLY
0039 35 90 PULS PC,X

Remember that MSCNT is a 16-bit number.

Time Budget:

Instruction Number of Times Executed Number of Clock Cycles

PSHS X 7
LOX '*I=MSCNT 1 3
LEAX -1 .X MSCNT 5
BNE DLY MSCNT 3
PULS PC.X 1 9

Ignoring the JSR or BSR instruction, the program takes

1 9 + 8 x MSCNT clock cycles

For this program to take 1 ms to execute at a 1 MHz clock rate, we need

1 9 + 8 x MSCNT = 1 000
MSCNT = 1 22 (007 A16)

At a 2 MHz clock rate, we need

19 + 8 X MSCNT = 2000
MSCNT = 24 7 (OOF7 16)
Input/Output 12-13

LOGICAL AND PHYSICAL DEVICES6


An important goal in writing 1/0 routines is to make them independent of par­
ticular physical hardware. The routines can then transfer data to or from 1/0
devices, with the actual addresses being supplied as parameters. The 1/0 device that
can actually be accessed through a particular interface is referred to as a physical
device. The 1/0 device to which the program transfers data is referred to as a logical
device. The operating system or supervisor program must provide a mapping of logical
devices on to physical devices, that is, assign actual physical 1/0 addresses and
characteristics to be used by the 1/0 routines.
Note the advantages of this approach:
1. The operating system can vary the assignments under user control. Now
the user can easily substitute a test panel or a development system interface
for the actual 1/0 devices. This is useful in field maintenance as well as in
debugging and testing. Furthermore, the user can change the 1/0 devices for
different situations; typical examples are directing intermediate output to a
video display and final output to a printer or obtaining some input from a
remote communications line rather than from a local keyboard.

2. The same 1/0 routines can handle several identical or similar devices. The
operating system or user only has to supply the address of a particular
teletypewriter, RS-232 terminal, or printer, for example.

3. Changes, corrections, or additions to the 1/0 configuration are easy to


make since only the assignments (or mapping) must be changed. On the 6809
microprocessor, the 1/0 routines can use the indexed addressing modes to
provide independence of specific physical addresses. Indirect addressing
allows one to access a physical device through a table. You can also use the
LEA instruction to load the actual device address into an Index Register or
Stack Pointer.

1/0 DEVICE TABLE

If the system has a table of 1/0 addresses in memory (for example, starting at
address IODEV) all an 1/0 routine needs is an index into the table. It can then
access the 1/0 device using the indirect accumulator indexed mode. If, for example,
the device address is table entry DEY, the foliowing program calculates the index and
loads the base address of the table into Index Register X:

LDA DEV GET DEVICE NUMBER


ASLA MULTIPLY DEVICE NUMBER BY 2 FOR 2-BYTE ADDRESS TABLE
LDX #IODEV GET 0ASE ADDRESS OF I/0 TABLE

The program can now transfer data to or from the 1/0 device using the instruc-
tions
LDB DATA GET DATA
STB [A, X} SEND DATA T O LOGICAL I/0 DEVICE

or

LDB [ A, X) GET DATA FROM LOGICAL I/0 DEVICE


STB DATA SAVE DATA IN MEMORY
12-14 6809 Assembly Language Programming

If the program uses an 1/0 device address repeatedly, it can load it into Index
Register X with the instruction LOX [A,X] or LEAX [A,X]. Later instructions can then
use the non-indirect indexed addressing mode with no offset.
Using this approach, a single 1/0 routine can transfer data to or from many
different l/0 devices. The main program simply supplies the 1/0 routine with the index
for the device table. Compare the flexibility of this approach with the inflexibility of 1/0
routines that use direct or extended addressing to transfer data to or from 1/0 devices
and are therefore tied to specific physical addresses.

STANDARD INTERFACES

You can use other standard interfaces besides the TTY current-loop and RS-
232 to connect peripherals to a microcomputer. Popular ones include ;7.8

1. The serial RS-449, RS-422, and RS-423 interfaces.9


2. The 8-bit parallel General Purpose Interface Bus, also known as IEEE 488 or
Hewlett-Packard Interface Bus (HPIB) .10
3. The S-100 or IEEE 696 bus . II This 8-bit bus can also be used as a 16-bit bus.

4. The Intel Multibus.12 This is another 8-bit bus that can be expanded to han­
dle 16 bits in parallel.

5. Limited busses such as the Mostek/Pro-Log STD bus1J and the Intel iSBX
bus.l4 These are 8-bit busses that are intended to handle small additions to
standard boards.

The S-100 and Multibus differ from the others listed in that they are "mother­
board" busses which connect circuit boards within a single chassis. Such a bus connects
peripheral interface control logic to the central processor and memory; a different inter­
face (either a custom job or one of the standards we have mentioned) connects the pe­
ripheral device itself to the interface card in the microcomputer chassis.

6809 INPUT/OUTPUT CHIPS

Most 6809 input/output routines are based on LSI interface chips. These
devices combine latches, buffers, flip-flops, and other logic circuits needed for
handshaking and other simple interfacing techniques. They contain many logic con­
nections, certain sets of which can be selected according to the contents of program­
mable registers. Thus the designer has the equivalent of a Circuit Designer's Casebook
under his or her control. The initialization phase of the program places the appropriate
values in registers to select the required logic connections. Input or output routines
based on programmable LSI interface chips can handle many different applications, and
changes or corrections can be made in software rather than by rewiring.
Input/Output 12-15

Designers often use the following LSI interface chips with the 6809
microprocessor:

1. The 6820 or 6821 Peripheral Interface Adapter. We will discuss this device
in the next chapter. It contains two 8-bit 1/0 ports and four serial control
lines. There are minor hardware differences between the 6820 and 6821
devices, but we will treat them as identical since they are the same from the
programmer's point of view.
2. The 6850 Asynchronous Communications Interface Adapter. This device
transforms data between the 8-bit parallel form and the serial form required in
most communications applications. We will discuss the 6850 ACIA in
Chapter 14.
3. The 6551 Asynchronous Communications Interface Adapter. This device is
similar to the 6850 ACIA but includes an on-chip baud rate generator.
4. The 6522 Versatile Interface Adapter,tS.t6 which includes two 8-bit 1/0
ports, four serial control lines, two 16-bit counter/timers, and an 8-bit shift
register.

REFERENCES

1. J. Barnes and V. Gregory. "Use Microprocessors to Enhance Performance with


Noisy Data," EDN, August 20, 1976, pp. 71-72.
2. S. V. Alekar. "M6800 Program Performs Cyclic Redundancy Checks," Electronics,
December 6, 1979, p. 167.
J. E. McNamara. Technical Aspects of Data Communications, Digital Equipment
Corporation, Maynard, Mass., 1977, Chapter 13.
R. Swanson. "Understanding Cyclic Redundancy Codes," Computer Design,
November 1975, pp. 93-99.
J. Wong et at. "Software Error Checking Procedures for Data Communications
Protocols," Computer Design, February 1979, pp. 122-125.
3. A. Osborne et at. An Introduction to Microcomputers: Volume 2 - Some Real
Microprocessors, Osborne/McGraw-Hill, 1978, pp. 9-106 through 9-123.

4. A. Osborne et at. An Introduction to Microcomputers: Volume 2- Some Real


Microprocessors, pp. 9-78 through 9-106.
5. A. Osborne et at. An Introduction to Microcomputers: Volume 2- Some Real
Microprocessors, pp. 9-124 through 9-130.
6. C. W. Gear. Computer Organization and Programming, 3rd ed., McGraw-Hill, New
York, 1980, Chapter 6.
7. J. Kane et al. An Introduction to Microcomputers: Volume 3- Some Real Support
Devices, Chapter J, Osborne/McGraw-Hill, Berkeley, Calif.

C. A. Ogdin. "Microcomputer Buses," Mini-Micro Systems, June 1978, pp. 97-


104 (Part 1); July 1978, pp. 76-80 (Part 2).
12-16 6809 Assembly Language Programming

8. E. Teja and R. Peterson. "Selecting the Proper Bus," EDN, December 15, 1979,
pp. 231-236.
9. D. Morris. "Revised Data Interface Standards," Electronic Design, September 1,
1977,pp.l38-14l.
10. Institute of Electrical and Electronic Engineers."IEEE Standard Digital Interface
for Programmable Instrumentation," IEEE Std488-1978,IEEE,445 Hoes Lane,
Piscataway, N.J. 08854.

J. B. Peatman. Microcomputer-Based Design, McGraw-Hill, New York, 1977, pp.


299-311.

S.C. Baunach. "An Example of an M6800-Based GPIB Interface," EDN, Septem­


ber 20,1977, pp. 125-128. A more detailed version of this article,complete with
program listing and schematics, is available from Tektronix, Inc., Box 500,
Beaverton,OR 97077.
S. M. Babb et al. "A General-Purpose IEEE-488 Bus Interface," Proceedings of
the 1979 Conference on Industrial Applications of Microprocessors,Philadelphia,
Pa.,March 1979, pp. 121-125. This article also includes basic talker code for an
M6800.
ll. G. Morrow and H. Fullmer. "Proposed Standard for the S-100 Bus," Computer,
May 1978, pp. 84-89.
K. A. Elmquist et al. "Standard Specification for S-100 Bus Interface Devices,"
Computer, July 1979, pp. 28-51.
12. T. Rolander. "Intel Multibus Interfacing," Intel Application Note AP-28, Intel
Corporation,Santa Clara,CA,1977.
An Introduction to Microcomputers: Volume 3 - Some Real Support Devices, Section
J.
13. M. Biewer. "This Bus Handles Different Microprocessors," Electronic Design,
October 11, 1978,pp. 220-224.
14. G. Sawyer et al. "Special-Function Modules Ride on Computer Board,"
Electronics, April 10,1980,pp. 135-140.
15. A. Osborne et al. An Introduction to Microcomputers: Volume 2- Some Real
Microprocessors, pp. 10-34 through 10-53.
16. L. A. Leventhal. 6502 Assembly Language Programming, Osborne/McGraw-Hill,
pp. 11-23 through 11-38.
13
Using the 6820 Peripheral
Interface Adapter (PIA)

The 6820 PIAU is a device which supports many modes of parallel 1/0. In this
chapter we will discuss the programming of this device in some detail, and give
several examples of fundamental 1/0 routines. The discussion in this chapter
applies to the 6821 PIA as well; it and the 6820 appear equivalent to the programmer.

REGISTERS AND CONTROL LINES

Figure 13-1 is the block diagram of a PIA. The device contains two nearly iden­
tical 8-bit ports - A, which is usually an input port, and B, which is usually an out­
put port. Each port contains:

A Data or Peripheral register that holds either input or output data. This
register is latched when used for output but unlatched when used for input.

A Data Direction register. The bits in this register determine whether the cor­
responding data register bits (and pins) are inputs (0) or outputs ( 1).
A Control register that holds the status signals required for handshaking, and
other bits that select logic connections within the PIA.

Two control lines that are configured by the control registers. These lines can
be used for the handshaking signals shown in Figures 12-5 and 12-6.

The meanings of the bits in the Data Direction and Control Registers are related
to the underlying hardware and are entirely arbitrary as far as the assembly language
programmer is concerned. You must either memorize them or look them up in the
appropriate tables (Tables 13-2 through 13-6).
13-2 6809 Assembly Language Programming

Interrupt CBl
Status
IRQB��------� Control B CB2

Figure 13-1. Block Diagram of the 6�20 Peripheral Interface Adapter


Using the 6820 Peripheral Interface Adapter (PIA) 13-3

Table 13-1. Addressing 6820 PIA Internal Registers

Address Control
lines Register Bit Offset Address
Register Selected (Index Register or Stack Pointer) =

Address of Peripheral (Datal Register A


RS1 RSO CRA-2 CRB-2

0 0 1 X Peripheral Register A 0
0 0 0 X Data Direction Register A 0
0 1 X X Control Register A 1
1 0 X 1 Peripheral Register B 2
1 0 X 0 Data Direction Register B 2
1 1 X X Control Register B 3

X = Either 0 or 1

Addresses

Each PIA occupies four memory addresses. The RS (register select) lines
choose one of the four registers, as described in Table 13-1. Since there are six
registers (two peripheral, two data direction, and two control) in each PIA, one further
bit is needed for addressing. Bit 2 of each Control Register determines whether the
other address on that side refers to the Data Direction Register (0) or to the Periph­
eral Register (1). This sharing of an external address means that

I. A program must change the bit in the Control Register in order to use the
register that is not currently being addressed.
2. The programmer must know the contents of the Control Register to deter­
mine which register is being addressed. RESET clears the Control Register
and thus addresses the Data Direction register.

Table 13- 1 also shows a convenient way to address the registers in a PIA. If, as is
usually the case, the register select lines are tied to the least significant address lines
(RSO to AO and RS 1 to A I), the programmer can load an Index Register or Stack
Pointer with the address of Data (Peripheral) Register A and refer to the other register
by means of the constant offsets in the last column of Table 13-1.

PIA Control Registers

fable 13-2 shows the organization of the PIA Control Registers. We may de­
scribe the general purpose of each bit as follows:

Bit 7: status bit set by transitions on control line 1 and cleared by reading the Pe-
ripheral (Data) register
Bit 6: same as bit 7 except set by transitions on control line 2
Bit 5: determines whether control line 2 is an input (0) or output (I)
Bit 4: Control line 2 input: determines whether bit 6 is set by high-to-low transi­
tions (0) or low-to-high transitions ( 1) on control line 2
Control line 2 output: determines whether control line 2 is a pulse (0) or a
level (l)
Bit 3: Control line 2 input: if 1, enables interrupt output from bit 6
13-4 6809 Assembly Language Programming

Control line 2 output: determines ending condition for pulse (0 =

handshake acknowledgment lasting until next transition on control line 1,


1 = brief strobe lasting one clock cycle) or value of level

Bit 2: selects Data Direction Register (0) or Data Register (1)

Bit 1: determines whether bit 7 is set by high-to-low transitions (0) or low-to­


high transitions (1) on control line 1

Bit 0: if 1, enables interrupt output from bit 7 of Control Register

Tables 13-3 through 13-6 describe the bits in more detail. Since E is normally
tied to the <1>2 clock, you can interpret "E" pulse as "clock pulse."

Table 13-2. Organization of the PIA Control Registers

7 6 5
I 4
I 3 2 1
I 0

CRA DDRA
IRQA1 IRQA2 CA2 Control CA1 Control
Access

7 6 5
1 4
I 3 2 1
I 0

CRB DDRB
IRQB1 IRQB2 CB2 Control CB1 Control
Access

Table 13-3. Control of 6820 PIA Interrupt Inputs CAl and CBI

CRA 1 CRA-0 Interrupt Input Interrupt Flag MPU Interrupt Request


(CRB-1) (CRB-0) CA1 (CB1) CRA-7 (CRB-7) IRQA (i'R'QB)

Set high on J of CA1


0 0 J Active Disabled - IRQ remains high
(CB1)

Goes low when the


Set high on J of CA1
interrupt flag bit CR A- 7
0 1 J Active
(CB1)
(CAB- 7) goes high

Set high on 1 of CA1


1 0 1 Active Disabled - IRQ remains high
(CB1)

Goes low when the


Set high on 1 of CA1
1 1 I Active interrupt flag bit CRA- 7
(CB1)
(CAB- 7) goes high

Notes:
1. I indicates positive transition (low to high)

2. j indicates negative transition (high to low)

3. The interrupt flag bit CRA- 7 is cleared by an MPU Read of the A Data Register, and CRB- 7 is cleared
by an MPU Read of the B Data Register
4. If CRA-0 (CRB-0) is low when an interrupt occurs (interrupt disabled) and is later brought high, IRQA
(IRQB) occurs after CRA-0 (CRB-0) is written to a "one."
Using the 6820 Peripheral Interface Adapter (PIA) 13-5

Table 13-4. Control of 6820 PIA Interrupt Inputs CA2 and CB2 (CRAS (CR85) is Low)

CRA-5 CRA-4 CRA-3 Interrupt Input Interrupt Flag MPU Interrupt Request
(CRB-5) (CRB-41 (CRB-3) CA2 (CB2l CRA-6 (CRB-6) iiffiA (IRQB)

0 0 0 1 Active
Set high on 1 of CA2
Disabled - IRQ remains high
(CB2)

Goes low when the


Set high on 1 of CA2
0 0 1 1 Active interrupt flag bit CRA-6
(CB2)
(CRB-6) goes high

Set high on t of CA2


0 1 0 T Active Disabled - IRQ remains high
(CB2)

Goes low when the


Set high or t of CA2
0 1 1 1 Active interrupt flag bit CRA-6
(CB2)
(CRB-6) goes high

Notes
1. 1 indicates positive transition (low to high)

2. 1 indicates negative transition (high to low)

3. The Interrupt flag bit CRA-6 is cleared by an MPU Read of the A Data Register and CRB-6 is cleared
by an MPU Read of the B Data Register

4. If CRA-3 (CRB-3) is low when an interrupt occurs (Interrupt disabled) and is later brought high. IRQA
(IRQB) occurs after CRA-3 (CRB-3) is written to a "one"

Table 13-5. Control of 6820 PIA CB2 Output Line (CRBS is High)

CB2
CRB- CRB- CRB- Mo de
5 4 3 Cleared Set

Low on the positive transition of High when the interrupt flag bit Automatic Output
the first E pulse following an CRB- 7 is set by an active transi- Acknowledge
1 0 0
MPU Write "B" Data Register tion of the CB 1 signal.
operation.

Low on the positive transition of High on the positive edge of the Automatic Output
the first E pulse after an MPU first "E" pulse following an "E" (Write) Strobe
1 0 0 Write "B" Data Register opera- pulse which occurred while the
tion. part was deselected.

Low when CRB-3 goes low as a Always low as long as CRB-3 is Manual Output (Low)
result of an MPU Write in Con- low. Will go high on an MPU
1 1 0 trol Register "B". Write in Control Register "B"
that changes CRB-3 to "one".

Always high as long as CRB-3 is High when CRB-3 goes high as Manual Output (High)
high. Will be cleared when an a result of an MPU Write into
1 1 1 MPU Write Control Register Control Register "B".
"B" results in clearing CRB-3 to
ro
..

" ze
13-6 6809 Assembly Language Programming

Table 13-6. Control of 6820 PIA CA2 Output Line (CRA5 is High)

CA2
CRA- CRA- CRA- Mode
5 4 3 Cleared Set

low on negative transition of E High when the interrupt flag bit Automatic Input
after an MPU Read "A" Data CRA- 7 is set by an active transi- Acknowledge
1 0 0
operation. tion of the CA 1 signal.

low on negative transition of E High on the negative edge of the Automatic Input
after an MPU Read "A" Data first "E" pulse which occurs {Read) Strobe
1 0 1 operation. during a deselect

low when CRA-3 goes low as a Always low as long as CRA-3 is Manual Output (low)
result of an MPU Write to Con- low. Will go high on an MPU
1 1 0
trol Register "A". Write to Control Register "A"
that changes CRA-3 to "one".

Always high as long as CRA-3 High when CRA-3 goes high as Manual Output (High)
is high. Will be cleared on an a result of an MPU Write to
1 1 1 MPU Write to Control Register Control Register "A".
"A" that clears CRA-3 to a
"zero".

INITIALIZING A PIA

As part of the general system initialization, the program must determine how
each PIA will operate. Remember that a PIA contains a large number of logic connec­
tions, much as the processor itself does. The data stored in the control and data direction
registers activates certain connections within the PIA, much as the data loaded into the
instruction register of the CPU activates certain connections. The differences are that
the PIA contains far fewer connections than the CPU and the program rarely, if ever,
changes the active connections in a PIA.
The steps in determining how the PIA will operate are:

1. Address the Data Direction Registers by clearing bit 2 of each Control


Register. This allows the program to determine which 1/0 pins will be inputs
and which outputs. Since RESET clears the entire control register, this step is
unnecessary in the overall system startup routine.

2. Determine which I/0 pins will be inputs and which outputs by loading the
appropriate combinations of O's (for inputs) and l 's (for outputs) into the
Data Direction Registers.

3. Determine how the status and control lines will operate by loading the
appropriate values into bit positions 0, 1, 3, 4, and 5 of the Control Registers.
Address the Data Registers by setting bit 2 of each Control Register.

The program can address a Data Direction Register as follows:

CLR PIACR CLEAR PIA CONTROL REGISTER

or
LDA PIACR
ANDA #%11111011 ADDRESS DATA DIRECTION REGISTER
STA PIACR
Using the 6820 Peripheral Interface Adapter (PIA) 13-7

The second version is more general, since it does not change any of the other bits in the
Control Register.
After the program has addressed the Data Direction Register, it can select the
appropriate combination of inputs and outputs by storing the corresponding pattern of
O's and 1 's in that register. Some simple examples are:

1. CLR PIADDR MAKE ALL DATA LINES INPUTS

2. LOA #SFF MAKF. ALL DATA LINES OUTPUTS


STA PIADDR

3. LOA #$FO MAKE DATA LINES 4-7 OUTPUTS, 0-3 INPUTS


STA PIADDR

The third step is clearly the most difficult, since it involves selecting the active logic con­
nections in the PIA and thus determining how the device will operate.
Some factors to rem em� er are:

1. You cannot change bits 6 and 7 of the Control Register by writing data into
them. Only transitions on the control lines set these bits and only the reading
of the corresponding Data Registers clears them.
2. You must set bit 2 of each Control Register to address the Data Register
and allow the transfer of data to or from the outside world. As long as bit 2 of
a Control Register is zero, the CPU can only access the corresponding Data
Direction Register; it cannot transfer data to or from the 1/0 pins through the
Data Register.
3. Bit 1 of the Control Register determines which edge of a pulse on control
line 1 will set bit 7. If bit 1 is 0, a high-to-low transition (rising edge) on con­
trol line 1 will set bit 7; if bit 1 is 1, a low-to-high transition (falling edge) on
control line 1 will perform that function. If control line 2 is an input, bit 4 pro­
vides the same choice for it.

4. Bit 0 of the Control Register is an interrupt enable for control line 1.


Remember that this bit must be set to enable interrupts, unlike the 6809
Interrupt Mask bit, which must be cleared to enable interrupts. Chapter 15 de­
scribes interrupts in more detail. If control line 2 is an input, bit 3 performs
the same function for it.
5. Bit 5 determines whether control line 2 is an output (1) or an input (0). Bits
3 and 4 determine how control line 2 will operate. In the pulse or automatic
strobe mode, ports A and B differ; port A produces a pulse on CA2 only after
the processor reads Data Register A, while port B produces a pulse on CB2
only after the processor writes into Data Register B.
6. You must determine the operating mode of each port of each PIA in your
system. Each port has a separate Control Register, Data Direction Register,
and pata Register.

PIA OPERATING MODES

We can refer to the operating modes in which CA2 or CB2 are output control
signals as follows:
The modes in which the PIA automatically produces a pulse on CA2 after an
13-8 6809 Assembly Language Programming

input operation or on CB2 after an output operation are called automatic modes, since
the PIA produces the entire pulse without any explicit CPU intervention. The pro­
grammer has no control over the length or polarity of the pulse.
The mode in which bit 3 of the PIA Control Register determines the level of
control line 2 is called a manual mode, since the CPU must produce changes by
explicitly setting or clearing control register bit 3. The PIA does nothing automatically.
This mode requires extra instructions, but gives the programmer complete control over
the length and polarity of pulses.
Control line 2 has the following functions in the two automatic modes:
In the mode in which the automatic pulse lasts until the next active transition on
control line I, control line 2 is an acknowledgment. The active part of the pulse (the low
period) signifies that the CPU has completed its part of the most recent 1/0 operation;
the I/0 device may start the next operation by sending data (input) or indicating its
readiness (output).
In the mode in which the automatic pulse lasts one clock cycle, control line 2 is
a strobe. The pulse indicates that the CPU has performed an 110 operation.

Examples of Selecting a PIA Operating Mode

1. A simple input port with no control lines (for example, as needed for a set of
switches):

CLR PTACR ADDRRSS DATA DIRECTION REGISTER


CLR PIADDR MAK� ALL DATA LINES INPUTS
LOA J%00000100 AnDR�SS DATA REGISTER
STA PIACR

The program first clears bit 2 of the Control Register to gain access to the
Data Direction Register. It then makes all the data lines inputs by storing O's
in all the bits of the Data Direction Register and sets bit 2 of the Control
Register to gain access to the Data Register (and the input port itself). The
same sequence of instructions will handle the case in which a high-to-low
transition ( falling edge) on control line 1 indicates OAT A READY or PE­
RIPHERAL READY.

2. A simple output port with no control lines (for example, as needed for a set
of single LED displays):

CLR PIACR ADDRESS DATA DIRECTION REGISTER


LOA �$FF MAKE ALL DATA LINE OUTPUTS
STA PIADDR
LOA #%00000100 ADDRESS DATA REGISTER
STA PIACR

The only difference from the previous example is that the program makes all
the data lines outputs by storing l 's in all the bits of the Data Direction
Register.

3. An input port with a status input that indicates DATA READY with a low­
to-high transition (positive transition on control line 1).

CLR PIACR ADDRESS DATA DIRECTION REGISTER


CLR PIADDR MAKE ALL DATA LINES INPUTS
LOA �%00000110 MAKE DATA READY ACTIVE LOW-TO-HIGH
STA PIACR

The only difference from Example 1 is that the program sets bit 1 of the Con­
trol Register. The result is that low-to-high transitions on control line 1 will
Using the 6820 Peripheral Interface Adapter (PI A) 13-9

set bit 7 of the Control Register. This operating mode is suitable for most
encoded keyboards.

4. An output port that produces a brief strobe to indicate DATA READY or


OUTPUT READY. This strobe could be used to multiplex displays or to pro­
vide a DATA AVAILABLE signal to a printer.

CLR PIACR ADDRESS DATA DIRECTION REGISTER


LOA nSFF MAKE ALL DATA LINES O UTPUTS
STA PIADDR
LOA �%00101100 MAKF. CONTROL LINE 2 A BRIEF STROBE
STA PIACR

This program selects an operating mode for control line 2 as follows:

Bit 5 l to make control line 2 an output.

Bit 4 0 to make control line 2 a pulse, rather than a level.


Bit 3 1 to make the pulse one clock period long.

After each instruction that writes data into PIA Data Register B, control line 2
will go low for one clock cycle. For example, the instruction

STA PIADB

will both send data to the Data Register (and hence to the output port) and
cause a strobe on control line 2. However, the A port of a PIA will produce a
strobe only after a read operation. The sequence

STA PIADA WRITE DATA


LOA PIADA PRODUCE AN OUTPUT STROBE

will both send the data to the output port and cause a strobe. The LOA
instruction is a "dummy read;" it has no effect except causing the strobe (and
wasting a few clock cycles). Other instructions besides LOA could serve the
same purpose� you should try to name some of them.

5. An input port with a handshake INPUT ACKNOWLEDGE strobe. The


strobe goes low when the CPU has read the data in the port and can accept
more.
CLR PIACR ADDRESS DATA DIRECTION REGISTER
C LR PIADDR MAKE ALL DATA LINES INPUTS
LOA n%00100100 CONTROL LINE 2 - HANDSHAKE ACKNOWLEDG�
STA PIACR

Control register bit 5 = l to make control line 2 an output, bit 4 = 0 to make


it a pulse, and bit 3 = 0 to make it an active-low acknowledgment that
remains low until the next active transition on control line I. The port oper­
ates as follows:

a. A high-to-low transition on control line 1 indicates that the input periph­


eral has sent the computer new data. Bit 7 of the PIA Control Register is
set and control line 2 goes high.

b. The CPU determines that new data is available by examining bit 7 of the
PIA Control Register. It therefore loads the data from the Data Register,
thus clearing bit 7 of the Control Register and sending control line 2 low.

c. The input peripheral can determine that the CPU has accepted the most
recent data by examining control line 2. It can then repeat step a with
complete assurance that no data will be lost.
13-10 6809 Assembly Language Programming

The acknowledgment automatically follows any instruction that reads PIA


Data Register A; for example, the instruction

LDA PIADl>.

will both read the data and cause the acknowledgment. However, the B port
will produce an acknowledgment only after an instruction that writes into the
Data Register. The sequence

LDA PIADB READ DATA


STA PIADB PRODUCE ACKNOWLEDGEMENT

will both read data and produce an acknowledgment. The STA instruction is a
"dummy write;" it has no effect other than to cause an acknowledgment
(that is, to send control line 2 low) and use a few clock cycles. Note that the
instructions here are in the opposite order from those in Example 4. This
operating mode is suitable for many CRT terminals that require a complete
handshake.

6. An output port with a latched zero control bit (latched serial output or level
output with value 0). The serial output can be used to turn a peripheral on or
off or to determine its mode of operation.
CLR PIACR ADDRESS DATA DIRECTION REGISTER
LDA �$FF MAKE ALL DATA LINES OUTPUTS
STt, l'IADDR
�DA i%00110100 CONTROL LINE 2 - LATCHED OUTPUT, VALUE 0
)TA i'IACR

Bit 5 = 1 to make control line 2 an output, bit 4 = l to make it a level or


latched bit, and bit 3 = 0 to make the value of the level zero. Operations on
the Data Register do not affect control line 2 in this operating mode, so it will
not automatically change value. The only way to change its value is for the
program to change the value of bit 3 of the PIA control register; i.e.,
Lf1i\ PIACR
OHA '%00001000 MAKE SERIAL OUTPUT ONE
STI\ f'IACR

or
LDA ?IACR
ANDA �%11110111 MAKE SERIAL OUTPUT ZERO
STA PIACR

You can use this operating mode to produce active-high strobes or to provide
pulses with lengths determined by the program, rather than by the hardware.

USING THE PIA TO TRANSFER DATA


Once the program has determined the operating mode of the PIA, you may use its
data registers like any other memory locations. The most straightforward instructions
for transferring data from an input device or to an output device are as follows:

Load Accumulator transfers 8 bits of data from the specified input pins to an
Accumulator.
Store Accumulator transfers 8 bits of data from an Accumulator to the specified
output pins.
Using the 6820 Peripheral Interface Adapter (PIA) 13-11

You must be cautious in situations in which input and output ports do not
behave like memory locations. For example, it often makes no sense to write
data into input ports or read data from output ports. Be particularly careful if the
input port is not latched or if the output port is not buffered.

Other instructions that transfer data to or from memory can also serve as 1/0
instructions. Typical examples are:

Clear places zeros on a set of output pins.

Test sets the flags according to the values of a set of input pins.

Compare sets the flags as if the values of a set of input pins had been subtracted
from the contents of an Accumulator.

Here also you must be aware of the physical limitations of the 1/0 ports. Be particu­
larly careful of instructions like Test, Shift, Complement, Increment, and Decrement,
which involve both read and write cycles.
We cannot overemphasize the importance of careful documentation. Often, com­
plex 1/0 transfers can be concealed in instructions with no obvious functions. You
must describe the purposes of such instructions carefully. For example, one could
easily be tempted to remove the dummy read and write operations mentioned earlier
since they do not appear to accomplish anything.

PIA Status Bits

Bit 7 of the PIA Control Register often serves as a status bit, such as Data
Ready or Peripheral Ready. You can check its value with either of the following
sequences:
LDA PIACR IS READY FLAG 1?
B"1 [ DEVRDY YES, DEVICE READY

TST PIACR IS READY FLAG 1?


B"ll DEVRDY YES, DEVICE READY

Note that you should not use the shift instructions, since they will change the contents
of the Control Register (why?). The following program will wait for the Ready flag to go
high:
>\'I\ ITR LDA PIACR IS READY FLAG 1?
BPL vJI\ITR NO, WAIT

How would you change these programs to examine bit 6 instead of bit 7?
The only way to clear bit 7 (or bit 6) is to read the Data Register. A dummy read
will be necessary if a read operation is not normally part of the response to the bit being
set. If the port is used for output, the sequence

ST.l\ FIADR SEND DATA


L[',\ ;'IADR CLEAR READY FLAG

will do the job. Note that here the dummy read is necessary on either port of the PIA.
The Test instruction can also clear the strobe without changing anything except the
flags. Be particularly careful of situations in which the CPU is not ready for input data or
has no output data to send.
13-12 6809 Assembly Language Programming

+5 v

I 6820 J\.
- To CPU
PIA v

Pushbutton -i 0
l
Figure 13-2. A Pushbutton Circuit

EXAMPLES

13-1. A PUSHBUTTON

We will interface a pushbutton to a 6809 microprocessor by means of a 6820 Pe­


ripheral Interface Adapter. The pushbutton is a mechanical switch; pressing the button
closes the switch and connects the input bit to ground (see Fig. 13-2).
The 6820 PIA acts as a buffer; no latch is needed since the pushbutton remains
closed for many CPU clock cycles. Pressing the button grounds one bit of the PIA. The
pullup resistor ensures that the input bit is one if the button is not being pressed.
We will perform two tasks with this circuit. They are:

a. Set a memory location based on the state of the button.


b. Count the number of times the button is pressed.

Task 13-1 a. Determine Switch Closure

Purpose: Set memory location 0040 to one if the button is not being pressed, and to zero
if it is.

Sample Cases:

1. Button open (not pressed)


Result = (0040) = 01
2. Button closed (pressed)
Result = (0040) = 00
Using the 6820 Penpheral Interface Adapter (PIA) 13-13

Flowchart:

(0040) = 0

Input and mask


Pushbutton Data

(0040) = 1

Program 13-1a:

8001 PIACA EQU $8001


8000 PIADDA EQU $8000
8000 PIADA EQU $8000
0001 MASK EQU %00000001
..

0 000 ORG $0000


0000 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTER
0003 7F 8000 CLR PIADDA MAKE ALL DATA LINES INPUTS
0006 86 04 LDA t%00000100 ADDRESS DATA REGISTER
OOOfl 87 8001 STA PIACA
OOOB OF 40 CLR $40 CLEAR BUTTON MARKER
0000 B6 8000 LDA PIADA READ BUTTON POSITION
0010 84 01 ANDA �MASK IS BUTTON CLOSED (LOGICAL ZERO)?
OOP 27 02 BEQ DONE YES, DONE
0014 oc 40 INC $40 NO, SET BUTTON MARKER
0016 3F DONE swr

The addresses PJACA (Control Register A), PIADDA (Data Direction Register
A), and PIADA (Data Register A) depend on how the PIA is connected in your
microcomputer. This example does not use the PIA control lines.
MASK depends on the bit to which the pushbutton is connected. It has a one in
the button position and zeros elsewhere.
13-14 6809 Assembly Language Programming

Mask
Button Position
(Bit Number)
Binary Hexadecimal

0 00000001 01
1 00000010 02
2 00000100 04
3 00001000 08
4 00010000 10
5 00100000 20
6 01000000 40
7 10000000 80

Jf the button is attached to bit 7 of the PIA input port, the program can use a LDA
or TST instruction to set the Sign (Negative) Oag and thereby determine the button's
state. For example,
LOA PIADA IS BUTTON CLOSED (LOGIC ZERO)?
BPL DONE YES, DONE:

TST PIADA IS BUTTON CLOSED (LOGIC ZERO)?


BPL DONE YES, DONE:

We could also use shift instructions if the button is attached to bit 0, 6, or 7. The
sequence for bit 0 is:

LSR PI ADA IS �UTTON CLOSED (LOGIC ZERO)?


BCC DONE YES, DONE

The instructions ASL or ROL can be used with bit 6 or 7. Do the contents of the PIA
data register actually change? Explain your answer.

Task 13-1 b. Count Switch Closures

Purpose: Count the number of button closures by incrementing memory location 0040
after each closure.

Sample Case:

Pressing the button ten times after the start of the program should result in

(0040) = OA

In order to count the number of times the button has been pressed, we must be
sure that each closure causes a single transition. However, a mechanical pushbutton
does not produce a single transition for each closure, because the mechanical contacts
bounce back and forth before settling into their final positions. We can use a one-shot
to eliminate the bounce or we can handle it in software.
The program can debounce the pushbutton by waiting after it finds a closure.
The required delay is called the debouncing time and is part of the specifications of the
pushbutton. It is typically a few milliseconds long. The program should not examine the
pushbutton during this period because it might mistake the bounces for new closures.
The program may either enter a delay routine like the one described previously or may
simply perform other tasks for the specified amount of time.
Using the 6820 Peripheral Interface Adapter (PI A) 13-15

Even after debouncing, the program must still wait for the present closure to
end before looking for a new closure. This procedure avoids double counting. The
following program uses a software delay of 10 ms to debounce the pushbutton. You may
want to try varying the delay or eliminating it entirely to see what happens. To run this
program, you must also enter the delay subroutine into memory starting at location
0030.

Flowchart:

COUNT= 0

COUNT=
COUNT+

Debounce button
with 1 0 ms wait

Program 13-1 b:
0030 DELAY EQU $0030
8001 PIACA EQU $8001
8000 PIADDA EQU $8000
8000 PIADA EQU $8000
0001 MASK EQU %00000001
*

0000 ORG $0000


0000 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTER
0003 7F 8000 CLR PIAOOA MAKE PORT A LINES INPUTS
000fi 86 04 LOA #%00000100 ADDRESS DATA REGISTER
0008 87 8001 STA PIACA
0008 OF 40 CLR $40 COUNT = ZERO INITIALLY
OOOD B6 8000 CHKCLO LOA PIADA
0010 84 01 ANOA !!MASK IS BUTTON BEING PRESSED?
OOP 26 F9 BNE CHKCLO NO, WAIT UNTIL I T I S
0014 oc 40 INC $40 YES, ADD 1 TO CLOSURE COUNT
001r; 86 OA LOA 1110 WAIT 10 MS TO DEBOUNCE BUT TON
OOlS 90 30 JSR DELAY
0(]1A B6 8000 CHKOPN LOA PI ADA IS BUTTON STILL BEING PRESSED?
OOlD 84 01 ANDA #MASK
OOlF 27 F9 BEQ CHKOPN YES, WAIT FOR RELEASE
0021 20 EA BRA CHKCLO NO, LOOK FOR NEXT CLOSURE
13-16 6809 Assembly Language Programming

The three instructions beginning with the label CHKOPN determine when the
switch reopens (i.e., when the button is released). If the PIA is addressed as shown in
the last column of Table 13-1, we can load Index Register X with the address of Data
Register A, and we can then use indexed offsets to address the PIA as follows:

Original Replacement
(X)= PIADRA

CLR PIACRA CLR 1, X


CLR PIADORA CLR ,X
STA PIACRA STA l,X
LOA PIADRA LOA , X

Clearly we do not need a PIA for this simple interface. An addressable tristate buffer
would do the job at far lower cost.

13-2. A MULTIPLE-POSITION (ROTARY, SELECTOR,


OR THUMBWHEEL) SWITCH
We will interface a multiple-position switch to a 6809 microprocessor. The lead
corresponding to the switch position is grounded, while the other leads are high (logic
ones).
Figure 13-3 shows the circuitry required to interface an 8-position switch. The
switch uses all eight data bits of one port of a PIA. Typical tasks are to determine the
position of the switch and to check if that position has changed. The program must
handle two special conditions:

1. The switch is temporarily between positions so no leads are grounded.

2. The switch has not reached its final position.

The first condition can be handled by waiting until the input is not all ones, i.e.,
until a switch lead is grounded. We can handle the second condition by examining the
switch again after a delay (such as 1 or 2 seconds) and only accepting the input when it

,... 7 .. PA7
�6 PA6
�5 - PA5
t ::: 4 PA4
(�3 .. PA3 6820 "
�2
� ::: -- ) To CPU
I PA2 PIA v

�0 -
PA1
PAO

Common

--
--

Figure 13-3. A Multiple-Position Switch


Using the 6820 Peripheral Interface Adapter (PIA) 13-17

Table 13-7. Data Input vs Switch Position

Date Input
Switch Position
Binary Hex

0 11111110 FE
1 11111101 FD
2 11111011 FB
3 11110111 F7
4 11101111 EF
5 11011111 OF
6 10111111 BF
7 01111111 7F

This scheme is inefficient, since it requires eight bits to distinguish among eight different positions

remains the same. This delay will not affect the responsiveness of the system to the
switch. Alternatively, we could use another switch (i.e., a Load switch) to tell the pro­
cessor when to read the selector switch.
We will perform two tasks involving the circuit of Figure 13-3. These are:

a. Monitor the switch until it is in a definite position, then determine the posi­
tion and store its binary value in a memory location.

b. Wait for the position of the switch to change, then store the new position in a
memory location.

If the switch is in a position, the lead from that position is grounded through the com­
mon line. Pullup resistors on the input lines avoid problems caused by noise.

Task 13-2a. Determine Switch Position

Purpose: The program waits for the switch to be in a specific position and then stores the
position number in memory location 0040.
Table 13-7 contains the data inputs corresponding to the various switch positions.
This scheme is inefficient, since it requires eight bits to distinguish among eight
different positions.
We have arranged the loop that identifies the switch position for somewhat
increased efficiency. The program initializes the position to -1 and then increments the
position (with INCB) before shifting the input (with LSRA). What happens if you
initialize the switch position to zero and shift and check the input before incrementing
the position? The approach in which you start the program one step backward often
increases execution speed because it lets you handle the first iteration in the same way as
the subsequent ones.

A short, quick way to determine if the switch is in a position is:


CHKSW INC PIADA IS SWITCH IN A POSITION?
BEQ CHKSW NO, WAIT UNTIL IT IS

Why does this approach work'! Do the contents of the PIA Data Register actually
change? Could you use the CARRY flag instead of the ZERO flag? Explain your
answers.
This example assumes that the switch is debounced in hardware. How would you
change the program to debounce the switch in software?
13-18 6809 Assembly Language Programming

Flowchart:

DATA=
Switch position

POSITION= 0

Shift DATA
right 1 bit

Yes

POSITION= (0040) =
POSITION+ 1 POSITION

Program 13-2a:

8001 PIACA EQU $8001


8000 PIADDA EQU $8000
8000 PI ADA EQU $8000
*

0000 ORG $0000


0000 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTER
0003 7F 8000 CLR PIADDA MAKE ALL DATA LINES INPUTS
0006 86 04 LDA J%00000100 ADPRESS DATA REGISTER
0008 B7 8001 STA PIACA
OOOB B6 8000 CHKSW LOA PI ADA
OOOE 81 FF CMPA J$FF IS SWITCH IN A POSITION?
0010 27 F9 BEQ CHKSW NO, WAIT UNTIL IT IS
0012 C6 FF LOB JSFF SWITCH POSITION = -1
0014 5C CHKPOS !NCB ADD 1 TO SWITCH POSITION
0015 44 LSRA IS NEXT BIT GROUNDED POSITION?
0016 25 FC BCS CHKPOS NO, KEEP LOOKING
0018 07 40 STB $40 SAVE SWITCH POSITION
001A 3F SWI
Using the 6820 Peripheral Interface Adapter (PI A) 13-19

,... 7 .. 10
(;6 i1
�5 .. 12
tn4
�3
-- i3
:. i4 74LS148 02 To CPU
- PA2
·�
�1
2 -- 15 8-to-3 01 PA1
6820
.. i6 Encoder 00 :- PIA
;:;o
PAO
....,
__iii, 17

Common

--
-
-

Figure 13-4. A Multiple-Position Switch with an Encoder

A TTL or MOS encoder could reduce the number of input bits needed. Figure 13-
4 shows a circuit using the 74LS148 TTL 8-to-3 encoder.J We attach the switch outputs
in inverse order, since the 74LS148 device has active-low inputs and outputs. The out­
put of the encoder circuit is a 3-bit representation of the switch position. Many switches
include encoders so their outputs are coded, usually as a BCD digit (in negative logic).
The encoder produces active-low outputs, so, for example, switch position 5,
which is attached to input 2, produces an output of 2 in negative logic (or 5 in positive
logic). You may want to verify the double negative for yourself.
Suppose that a faulty switch or defective PIA results in the input always being
FF16. How could you change the program so it would detect this situation?

Task 13-2b. Wait for Switch Position to Change

Purpose: The program waits for the switch position to change and places the new posi­
tion (decoded) into memory location 0040. The program waits until the switch
reaches its new position.

Program 13-2b:

8001 PIACA EQU $8001


8000 PIADDA EQU $8000
8000 PI ADA EQU $8000
*

0000 ORG $0000


0000 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTER
0003 7F 8000 CLR PIADDA MAKE ALL DATA LINES INPUTS
0006 86 04 LDA ll%00000100 ADDRESS DATA REGISTER
0008 B7 8001 STA PIACA
OOOB B6 8000 CHKFST LDA PI ADA GET SWITCH DATA
OOOE 81 FF CMPA *SFF IS THE SWITCH IN A POSITION?
0010 27 F9 BEQ CHKFST NO, WAIT UNTIL IT IS
0012 97 40 STA $40 YES, SAVE SWITCH POSITION
0014 B6 8000 CHKSEC LOA PIADA GET NEW SWITCH DATA
0017 91 40 CMPA $40 IS POSITION SAME AS BEFORE?
0019 27 F9 BEQ CHKSEC YES, WAIT FOR POSITION TO
* CHANGE
13-20 6809 Assembly Language Programming

001B C6 FF LOB J$FF NO, START POSITION AT -1


0010 sc CHKPOS !NCB ADD 1 TO SWITCH POSITION
001E 44 LSRA IS NEXT BIT GROUNDED POSITION?
001F 25 FC BCS CHKPOS NO, KEEP LOOKING
0021 07 40 STB $40 YES, STORE SWITCH POSITION
0023 3F SWI

Flowchart:

Old data=
Position= 1
Switch position
-

Position=
Position+ 1

New data = Shift data


Switch position right 1 bit

(0040) = Position

The last two programs both need one byte of temporary storage. How would you
rewrite each example to use the Hardware Stack for that storage? What are the advan­
tages and disadvantages of using the Stack? Note that it makes the programs reentrant
and more general, as well as easier to use since they do not incidentally change specific
memory locations.

13-3. A SINGLE LED

We will interface a single light-emitting diode to a 6809 microprocessor, providing


separate interfaces and programs to handle positive logic (a '1' lights the LED and a '0'
turns it off) and negative logic (a '0' lights the LED and a '1' turns it off).
Figure 13-5 shows the circuitry required to interface an LED. The LED lights
when its anode is positive with respect to its cathode (Figure 13-Sa). Therefore, you
Using the 6820 Peripheral Interface Adapter (PI A) 13-21

R Anode 8 Cathode

+5V�------ �

1
a. Basic LED circuitry. The resistor R should limit the maximum current to 50 mA and
the average current to 1 0 mA

6820
Driver
PIA

-
-

b. Interfacing an LED with positive logic. A logic 1 from the CPU lights the LED.

+5 v

6820
Driver
PIA

c. Interfacing an LED with negative logic. A logic '0' from the CPU lights the LED.
Either the driver or the CPU may invert the logic levels.

Figure 13-5. Interfacing an LED

can light the LED either by grounding the cathode and having the computer supply a
one to the anode (Figure 13-Sb) or by connecting the anode to + 5 volts and having the
computer supply a zero to the cathode (Figure 13-Sc). Controlling the cathode is the
more common approach since most MOS or TTL l/0 ports perform better in this mode.
The LED is brightest when it operates from pulsed currents of about 10 or 50 rnA
applied a few hundred times per second. LEOs have a very short turn-on time (in the
microsecond range) so they are well suited to multiplexing (operating several from a
�ingle port). LED circuits usually need peripheral or transistor drivers and current-limit­
ing resistors. MOS devices normally cannot drive LEOs directly and make them bright
enough for easy viewing.
The PIA has an output latch on each port. However, the B port is normally used
13-22 6809 Assembly Language Programming

for output, since it has somewhat more drive capability. In particular, the B port outputs
are capable of driving Darlington transistors (providing 3.2 rnA minimum at 1.5V).
Darlington transistors are high-gain transistors capable of switching large amounts of
current at high speed; they are useful in driving solenoids, relays, and other devices.

Task 13-3. Turn the Light On or Off

Purpose: The program turns a single LED either on or off.

A. Send a Logic One to the LED (light a display that operates in positive logic or turn
off a display that operates in negative logic).

Program 13-3:

(form data initially)

8003 PIACB EQU $8003


8002 PIADDB EQU $8002
8002 PIADB EQU $8002
0080 MASKP EOU %10000000
*

0000 ORG $0000


0000 7F 8003 CLR PIACB ADDRESS DATA DIRECTION REGISTER
0003 86 FF LOA J$FF MAKE ALL DATA LINES OUTPUTS
0005 87 8002 STA PIADDB
0008 86 04 LOA J%00000100 ADDRESS DATA REGISTER
OOOA 87 8003 STA PIACB
0000 85 80 LOA JMASKP GET DATA FOR LED
OOOF 87 8002 STA PIADB SEND DATA TO LED
0012 3F SWI

We use the B side of the PIA because of the buffering. This allows the CPU to read
the data back (if necessary) without any difficulty.

(update data)

0013 86 8002 LDA PIADB GET OLD DATA


0016 8A 80 ORA #MASKP SET LED OUTPUT BIT TO 1
0018 87 8002 STA PIADB
0018 3F SWI

MASKP has a '1' bit in the LED position and zeros elsewhere. Logically ORing
the contents of Accumulator A with MASKP leaves the other bit positions unchanged;
those positions may control unrelated LEOs. Note that the CPU can read the PIA data
register even when some or all the pins have been assigned as outputs.

B. Send a Logic Zero to the LED (turn off a display that operates in positive logic or
light a display that operates in negative logic).

The differences are that MASKP must be replaced by its logical complement
MASKN and ORA#MASKP must be replaced by ANDA =#:MASKN. MASKN has a
zero bit in the LED position and ones elsewhere. Logically ANDing with MASKN does
not affect the other bit positions.

13-4. SEVEN-SEGMENT LED DISPLAY

We will interface a seven-segment LED display to a 6809 microprocessor. The dis­


play may be either common-anode (negative logic) or common-cathode (positive logic).
Using the 6820 Peripheral Interface Adapter (PI A) 13-23

-
PB6 g
PB5 - - f

PB4 -
-- e
6820
From CPU [ /
r PIA
PB3 Drivers - d Display
.. -
PB2 - c

PB1 b

PBO - a
Common
-

__ I __

(Common- (Common-
Cathode) Anode)
PB7 may be used for a decimal point LED.

Figure 13-6. Interfacing a Seven-Segment Display

Figure 13-6 shows the circuitry required to interface a seven-segment display.


Each segment may have one, two, or more LEOs attached in the same way. There are
two ways of connecting the displays. One is tying all the cathodes together to ground
(see Figure l3-7a); this is a "common-cathode display," and a logic one at an anode
lights a segment. The other is tying all the anodes together to a positive voltage sup­
ply (see Figure 13-7b); this is a "common-anode display," and a logic zero at a
cathode lights a segment. So the common-cathode display uses positive logic and the
common-anode display negative logic. Either display requires appropriate drivers and
resistors.
The Common line from the display is tied either to ground or to + 5 volts. The
display segments are customarily labelled:

e c

The seven-segment display is widely used because it contains the smallest


number of separately controlled segments that can provide recognizable representa­
tions of all the decimal digits (see Figure 13-8 and Table 13-8). Seven-segment dis­
plays can also produce some letters and other characters (see Table 13-9). Better repre­
sentations require a substantially larger number of segments and more circuitry.4 Since
seven-segment displays are so popular, low-cost seven-segment decoder/drivers have
become widely available. The most popular devices are the 7447 common-anode driver
and the 7448 common-cathode driver;s these devices have Lamp Test inputs (that turn
13-24 6809 Assembly Language Programming

+5 v

a. Common-cathode b. Common-anode

Figure 13-7. Seven-Segment Display Organization

Table 13-8. Seven-Segment Representations of Decimal Numbers

Hexadecimal Representation
Number
Common-cathode Common-anode

0 3F 40
1 06 79
2 58 24
3 4F 30
4 66 19
5 60 12
6 70 02
7 07 78
8 7F 00
9 67 18

Bit 7 is always zero and the others are g. f. e. d. c. b. and a in decreasing order of significance.

all the segments on) and blanking inputs and outputs (for blanking leading or trailing
zeros).

Task 13-4a. Display a Decimal Digit

Purpose: Display the contents of memory location 0040 on a seven-segment display if it


contains a decimal digit. Otherwise, blank the display.

Sample Problems:

a. (0040) = 05
Result is 5 on display

b. (0040) = 66
Result is a blank display
Using the 6820 Peripheral Interface Adapter (PIA) 13-25

0. Segments f. e. d. c. b. a on 5. Segments g, f. d. c. a on
a a

d d

1. Segments c. b on 6. Segments 9. f. e. d. c. a on
a

e c

d
Note that the alternate representat1on w1th a off
may be reserved for the lower case letter ·b·
2 Segments g. e. d. b. a on 7. Segments c. b. a on
a
a

b
b

g
c
e

d
8. Segments g. f. e. d. c. b. a on
3. Segments g. d. c. b. a on
a
a

b
b

g
g

e
c

d
d
Th1s 1s the same as LAMP TEST

4. Segments g, f. c. b on g, Segments g, f. c. b. a on
d

I b

I
f b

9 9

An alternate has segment d on also

Figure 13-8. Seven-Segment Representation of Decimal Digits


13-26 6809 Assembly Language Programming

Table 13-9. Seven-Segment Representations of Letters and Symbols

Lower-case Letters
Upper-case Letters
and Special Characters

Hexadecimal Hexadecimal
Representation Representation
Letter Character
Common· Common- Common· Common-
cathode anode cathode anode

A 77 08 b 7C 03
c 39 46 c 58 27
E 79 06 d 5E 21
F 71 OE h 74 OB
H 76 09 n 54 28
I 06 79 0 5C 23
J 1E 61 r 50 2F
L 38 47 u 1C 63
0 3F 40 - 40 3F
p 73 oc ? 53 2C
u 3E 41
y 66 19

Source Program:

8003 PIACB EQU $8003


8002 PIADB EQU $8002
8002 PIADDB EQU $8002
DOFF BLANK EQU SFF
*

0000 ORG $0000


0000 7F 8003 CLR PIACB ADDRESS DATA DIRECTION REGISTER
0003 86 FF LOA �SFF MAKE ALL DATA LINES OUTPUTS
0005 87 8002 STA PIADDB
0008 Bfi 04 LOA 1%00000100 AD DRESS DATA REGISTER
OOOA 87 8003 STA PIACB
OOOD C6 FF LOB tBLANK GET BLANK CODE
OOOF 96 40 LOA $40 GET DATA
0011 Bl 09 CMPA 19 IS DATA A DECIMAL DIGIT (9 OR
* LESS)?
0013 22 05 BHI DSPLY NO, DISPLAY BLANK CODE
0015 BE OllE LOX tSSEG YES, CONVERT DIGIT TO SEVEN-
0018 Eli 8') LOB A, X SEGMENT CODE
001A F7 fl002 DSPLY STB PIA DB SEND CODE TO DISPLAY
0010 3F SWI

BLANK is 00 for a common-cathode display, FF for a common-anode display. An


alternative procedure would be to put the blank code at the end of the table and replace
all improper data values with I 0; i.e., the instructions after ST A PIACRB are:

LDA $40 GET DATA


CMPA #9 IS DATA A DECIMAL DIGIT (9 OR LESS)?
BLS CNVRT
LOA uo NO, REPLACE DATA WITH INDEX FOR BLANK
CODE
CNVRT LOX #SSEG CONVERT DATA TO SEVEN-SEGMENT CODE
LOB A, X
STB PIADRB S E N D COD E TO D I S P L AY
SWI

Table SSEG is either the common-cathode or the common-anode representation


of the decimal digits from Table 13-8 with the appropriate blank code in the tenth posi­
tion.
Figure 13-9 shows how to multiplex displays (i.e., drive several displays from the
same port).o A brief pulse on control line CB2 automatically clocks the decade counter
Using the 6820 Peripheral Interface Adapter (PJA) 13-27

Flowchart:

CODE: Blank
OAT A = (0040)

CODE = (SSEG +

DATA)

Send CODE
to display

after each output operation, thus directing the data to the next display. RESET initial­
izes the decade counter to 9 so that the first output operation clears the counter and
directs data to the first (actually, the zeroth) display.
The next program uses a transparent 1 ms delay routine (described earlier in this
chapter) to pulse each of ten common-cathode displays for 1 ms. An observer will see a
continuous ten-digit display much like the ones typical of electronic calculators,
watches, and point-of-sale terminals.

Task 13-4b. Display Ten Decimal Digits

Purpose: Continuously display the contents of memory locations 0040 through 0049 on
ten 7-segment displays that are multiplexed with a counter and a decoder. The
most significant (leftmost) digit is in memory location 0040.

Sample Problem:

(0040) 66
(0041) 3F
(0042) 7F
(0043) 7F
(0044) 06
(0045) 58
(0046) 07
(0047) 4F
(0048) 60
(0049) 70
The number on the displays is 4088127356
13-28 6809 Assembly Language Programming

0, C, B, and A (0 most significant,


A least significant) are the 4-bit
output from the counter. These 4
bits activate the correspondingly
numbered o u t put from the
decoder, and hence the correspon­
dingly numbered display.

6820
PIA

From CPU PBO-PB7

98765432 1 0
0 0
Clock
7490 c c 7442
Decade 4 to 10
Counter B B Decoder Driver

Reset A A

Reset

Figure 13-9. Multiplexed Seven-Segment Displays


Using the 6820 Peripheral Interface Adapter (PIA) 13-29

Program 13-4b:

0030 DELAY EQU $0030


8003 PIACB EQU $8003
8002 PIADDB EQU $8002
8002 PIADB EQU $8002

0000 ORG $0000


0000 7F 8003 CLR PIACB ADDRESS DATA DIRECTION REGISTER
0003 86 FF LDA tSFF MAKE ALL DATA LINES OUTPUTS
0005 B7 8002 STA PIADDB
0008 86 2C LDA 11%00101100 MAKE CB2 A BRIEF PULSE,
*
ADDRESS I/0
OOOA B7 8003 STA PIACB
0000 BE 0040 SCAN LOX t$40 POINT TO START OF DATA
0010 C6 OA LOB flO NUMBER OF DISPLAYS 10 =

0012 A6 80 DSPLY LOA ,X+ GET DATA FOR A DISPLAY


0014 B7 8002 STA PIA DB· SEND DATA TO DISPLAY
0017 90 30 JSR DELAY WAIT 1 MS
0019 SA DECB COUNT DISPLAYS
001A 26 F6 BNE DSPLY
OOlC 20 EF BRA SCAN START ANOTHER SCAN

Control register bit 5 = 1 to make CB2 an output, bit 4 = 0 to make it a pulse, and
bit 3 = 1 to make it a brief pulse lasting one clock cycle. We have assumed here that
subroutine DELAY (starting at address 0030) provides a transparent 1 ms wait (i.e., it
does not affect any registers).

MORE COMPLEX 1/0 DEVICES

More complex 1/0 devices differ from simple keyboards, switches, and dis-
plays in that:

1. They transfer data at higher rates.


2. They may have their own internal clocks and timing.
3. They produce status information and require control information, as well
as transferring data.

Because of their high data rates, you cannot handle these 110 devices casually. If
the processor does not provide the appropriate service, the system may miss input data
or produce erroneous output data. You are therefore working under much more exact­
ing constraints than in dealing with simpler devices. Interrupts are a convenient method
for handling complex 1/0 devices, as we shall see in Chapter 15.

SYNCHRONIZATION

Peripherals such as keyboards, teletypewriters, cassettes, and floppy disks pro­


duce their own internal timing. These devices provide streams of data separated by
specific timing intervals. The computer must synchronize the initial input or output
operation with the peripheral clock and then provide the proper interval between sub­
sequent operations. A simple delay loop like the one shown previously can produce
the time interval. The synchronization may require one or more of the following pro­
cedures:

1. Looking for a transition on a clock or strobe line provided by the peripheral


for timing purposes. The simplest method is to tie the strobe to a PIA control
13-30 6809 Assembly Language Programming

line and wait until the appropriate bit of the PIA control register is set.
2. Finding the center of the time interval during which the data is stable. We
would prefer to determine the value of the data at the center of the pulse
rather than at the edges, where the data may be changing. Finding the center
requires a delay of one-half of a transmission interval (bit time) after the
edge. Sampling the data at the center also means that small timing errors have
little effect on the accuracy of the reception.
3. Recognizing a special starting code. This is easy if the code is a single bit or if
we have some timing information. The procedure is more complex if the code
is long and could start at any time. Shifting will be necessary to determine
where the transmitter is starting its bits, characters, or messages (this is often
called a search for the correct "framing").
4. Sampling the data several times. This reduces the probability of receiving
data incorrectly from noisy lines. Majority logic (such as best 3 out of 5 or 5
out of 8) can be used to decide on the actual data value.

Reception is, of course, much more difficult than transmission, since the periph­
eral controls the reception and the computer must interpret timing information gener­
ated by the peripheral. In transmission, the computer provides the proper timing and
formatting for a specific peripheral.

CONTROL AND STATUS INFORMATION

Peripherals may require or provide other information besides data and timing.
We refer to other information transmitted by the computer as "control information;"
it may select modes of operation, start or stop processes, clock registers, enable buffers,
choose formats or protocols, provide operator displays, count operations, or identify the
type and priority of the operation. We refer to other information transmitted by the pe­
ripheral as "status information;" it may indicate the mode of operation, the readiness
of devices, the presence of error conditions, the format of protocol in use, and other
states or conditions.
The computer handles control and status information just like data. This informa­
tion seldom changes, even though actual data may be transferred at a high rate. The
control or status information may be single bits, digits, bytes, or multiple bytes. Often
single bits or short fields are combined and handled by a single input or output port.

Separating Status Information

Combining status and control information into bytes reduces the total number of
1/0 port addresses required by the peripherals. However, the combination does mean
that individual status input bits must be separately interpreted and control output bits
must be separately determined. The procedure for isolating status bits is as follows:

Step 1. Read status data from the peripheral.


Step 2. Logical AND with a mask (the mask has ones in bit positions that must
be examined, and zeros elsewhere).
Step 3. Shift the separated bits to the least significant bit positions.

Step 3 is unnecessary if the field is a single bit, since the Zero nag will contain the
Using the 6820 Peripheral Interface Adapter (PIA) 13-31

complement of that bit after Step 2 (try it!). A Shift or Load instruction can replace Step
2 if the field is a single bit and occupies the least significant, most significant, or next to
most significant bit position (positions 0, 7, or 6). These positions are often reserved for
the most frequently used status information. You should try to write the required
instruction sequences for the 6809 processor. Note, in particular, the use of the Bit Test
instruction. This instruction performs a logical AND between the contents of the
Accumulator and the contents of a memory location but does not save the result; the
flags are set as follows:

Zero flag l if the logical AND produces a zero result, 0 if it does not.

Sign flag bit 7 of the result of the logical AND.

Combining Control Information

This is the procedure for setting and clearing control bits:

Step 1. Read prior control information.


Step 2. Logical AND with mask to clear bits (mask has zeros in bit positions to
be cleared, ones elsewhere).

Step 3. Logically OR with mask to set bits (mask has ones in bit positions to be
set, zeros elsewhere).

Step 4. Send new control information to peripheral.

Here again the procedure is simpler if the field is a single bit and occupies a posi­
tion at either end of a data byte.
Some examples of separating and combining status bits are:

l. A 3-bit field i n bit positions 2 through 4 of a PIA Data Register is a scaling fac­
tor. Place that factor in Accumulator A.
*
*READ STATUS DATA FRO� INPUT PORT
*

LOA PIA DR READ STATUS DATA


*
*MASK OFF UNWANTED RITS AND SHIFT RCSULT
*

ANDA 1%00011100 SAVE SCALING FACTOR


L:3R.I\ SHIFT TWICE TO �IOR/VIALIZE
LSR!\

2. Accumulator A contains a 2-bit field that must be placed in bit positions 3 and
4 of a PIA Data Register.
*
*MOVE DATA TO FIELD POSITIONS
*

ASLA SHIFT DATA TO BIT POSITIONS 3 AND 4


ASLA
ASLA
ANDA #%00011000 CLEAR OUT OTHER BITS
*
*COMBINE NEW FIELD POSITIONS WITH OTHER DATA
*

PSHS A SAVE NEW FIELD VALUE AT TOP OF STACK


LOA PIADR CLEAR OLD FIELD VALUE
ANDA #%11100111
ORA ,S+ INSERT NEW FIELD VALUE AND CLEAR STACK
STA PIADR

The instruction ORA ,S+ not only logically ORs the accumulator with the data we
13-32 6809 Assembly Language Programming

I

+5 v

----e�-I
--0

1 +5 v
Key 2

j_
--------���--�0 nu------e

I

+5 v

Key3

_ ____...! - -oj_
Each key is a switch just like a pushbutton and grounds an input

bit if it is pressed.

Figure 13-10. A Small Keyboard

saved at the top of the Hardware Stack, but it also increments the Hardware Stack
Pointer and thus removes the data from the Stack.

Documenting Status and Control Transfers

Documentation is a serious problem in handling control and status information.


The meanings of status inputs or control outputs are seldom obvious. The pro­
grammer should clearly indicate the purposes of input and output operations in the
comments, for example, "CHECK IF READER IS ON," "CHOOSE EVEN PARITY
OPTION," or "ACTIVATE BIT RATE COUNTER." The Logical and Shift instruc­
tions will otherwise be very difficult to remember, understand, or debug.

13-5. AN UNENCODED KEYBOARD

The processor will recognize a key closure from an unencoded 3 x 3 keyboard


and place the number of the key that was pressed in Accumulator B.
Keyboards are just collections of switches (see Figure 13-10). Small numbers of
keys are easiest to handle if each key is attached separately to a bit of an input port.
Interfacing the keyboard is then the same as interfacing a set of switches.
Using the 6820 Peripheral Interface Adapter (PIA) 13-33

Matrix Keyboard

Keyboards with more than eight keys require more than one input port and
therefore multibyte operations. This is particularly wasteful if the keys are logically sepa­
rate, as in a calculator or terminal keyboard where the user will only strike one at a time.
The number of input lines required may be reduced by connecting the keys into a
matrix, as shown in Figure 13-ll. Now each key represents a potential connection
between a row and a column. The keyboard matrix requires n + m external lines,
where n is the number of rows and m is the number of columns. This compares to n x
m external lines if each key is separate. Table 13-lO compares the number of keys
required by typical configurations.

Column 0 Column 1 Column 2

KeyO Key 1Y Key2

Y Y
RowO ----��----4---�--�--�.- +----

Key Key4 Key


3 5
Y Y Y
Row 1

Key6 Key Key8

Y 7Y Y
Row 2 ----�----4---�---;--�.-

Pressing a key connects a row to a column. For example, pressing key2 connects row 0 to column 2.

Figure 13-11. A Keyboard Matrix

Table 13-10. Comparison Between Independent Connections


and Matrix Connections for Keyboards

Number of Lines with Number of Lines with


Keyboard Size
Independent Connections Matrix Connections

3 X 3 9 6
4 X 4 16 8
4 X 6 24 10
5 X 5 25 10
6 X 6 36 12
6 X 8 48 14
8 X 8 64 16
13-34 6809 Assembly Language Programming

+5 v

KeyO 'y Key 1

y
00 Row 0

Key 3'y Key 4


Data Bus
(from CPU)
PIA
y
Output 01 Row 1
Port

Key6 'y Key 7 Key8 y


y
02 Row 2

Column 0 Column 1 Column 2

10 11 12

PIA
Input
Port

Data Bus (to CPU)

Figure 13-12.1/0 Arrangement for a Keyboard Scan

Keyboard Scan

A program can determine which key has been pressed by using the external
lines from the matrix. The usual procedure is a "keyboard scan." We ground Row 0
and examine the column lines. If any lines are grounded, a key in that row has been
pressed, causing a row-to-column connection. We can determine which key was pressed
by determining which column line is grounded; that is, which bit of the input port is
zero. If no column line is grounded, we proceed to Row land repeat the scan. Note that
we can check to see if any keys at all have been pressed by grounding all the rows at
once and examining the columns.
The keyboard scan requires that the row lines be tied to an output port and the
column lines to an input port. Figure 13-12 shows the arrangement. The CPU can
Using the 6820 Peripheral Interface Adapter (PIA) 13-35

ground a particular row by placing a zero in the appropriate bit of the output port and
ones in the other bits.
The CPU can determine the state of a particular column by examining the
appropriate bit of the input port.

Task 13-5a. Wait for Key Closure

Purpose: Wait for a Key to be Pressed


The procedure is as follows:

1. Ground all the rows by clearing all the output bits.

2. Fetch the column inputs by reading the input port.

3. Return to Step 1 if all the column inputs are ones.

Flowchart:

Ground all
keyboard rows

Program 13-5a:

8001 PIACA EQU $8001


8000 PIADDA EQU $8000
8000 PIADA EQU $8000
8003 PIACB EQU $8003
8002 PIADDB EQU $8002
8002 PIADB EQU $8002
*

0000 ORG $0000


0000 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTERS
0003 7F 8003 CLR PIACB
0006 7F 8000 CLR PIADDA MAKE A SIDE DATA LINES INPUTS
0009 86 FF LOA t$FF
OOOB B7 8002 STA PIADDB MAKE B SIDE DATA LINES OUTPUTS
OOOE 86 04 LOA t%00000100 ADDRESS DATA REGISTERS
0010 B7 8001 STA PIACA
0013 B7 8003 STA PIACB
0016 7F 8002 CLR PIADB GROUND ALL KEYBOARD ROWS
0019 86 8000 WAITK LOA PI ADA GET DATA FROM KEYBOARD COLUMNS
001C 84 07 ANDA t%00000111 MASK COLUMN BITS
001E 81 07 CMPA t%00000111 ARE ANY KEYS CLOSED?
0020 2 7 F7 BEQ WAITK NO, WAIT
0022 3F SWI

Masking off the column bits eliminates any problems that could be caused by the
states of the unused input lines.
13-36 6809 Assembly Language Programming

We could generalize the routine by naming the output and masking patterns:

ALLGND EQU %11111000


OPEN EQU %00000111

We could then use these names in the program; changing to a different keyboard
would require only a change in the definitions and a re-assembly.
Of course, a 3 x 3 or 4 x 4 keyboard only needs one port of a PIA. Rewrite the
program to use only port A.

Task 13-5b. Identify Key

Purpose: Identify a key closure by placing the number of the key in Accumulator B.
The procedure is as follows:

1. Set key number to 1, keyboard output port to all ones except for a zero in bit
0, and row counter to number of rows.

2. Fetch the column inputs by reading the input port.

3. If any column inputs are zero, proceed to Step 7.

4. Add the number of columns to the key number to reach next row.
5. Update the contents of the output port by shifting the zero bit left one posi­
tion.

6. Decrement row counter. Go to Step 2 if any rows have not been scanned;
otherwise, go to Step 9.
7. Add I to key number. Shift column inputs right one bit.

8. If Carry = 1, return to Step 7.

9. End of program.

This program does not wait for the operator to press a key, so the key must be
pressed before the program is executed. How would you modify the program to wait for
at least one key to be pressed?

Program 13-5b:

8001 PIADA EQU $8001


8000 PIADDA EQU $8000
8000 PIADA EQU $8000
8003 PIACB EQU $8003
8002 PIADDB EQU $8002
8002 PIADB i:QU $8002
*

0000 ORG soooo


0000 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTERS
0003 7F 8003 CLR PIACB
0006 7F 8000 CLR PIADDA MAKE A SIDE DATA LINES INPUTS
0009 86 FF LOA #SFF MAKE B SIDE DATA LINES OUTPUTS
OOOB 87 8002 STA PIADDB
OOOE 86 04 LDA ll%00000100 ADDRESS DATA REGISTERS
0010 B7 8001 STA PIACA
0013 B7 8003 STA PIACB
0016 86 FE LDA #%11111110 START BY GROUNDING ROW ZERO
0018 B7 8002 STA PIADB
001B 86 03 LDA #3 COUNTER = NUMBER OF ROWS
0010 97 40 STA $4 0
001F Cli FF LDB tSFF KEY NUMBER = -1
0021 B6 8000 FROW LOA PI ADA GET COLUMN INPUTS
0024 84 07 ANDA #%00000111 MASK OFF COLUMN BITS
0026 81 07 CMPA #%00000111 ARE ANY KEYS C LOSED IN THIS
*
ROW?
Using the 6820 Peripheral Interface Adapter (PIA) 13-37

0028 26 OA BNE FCOL YES, DETERMINE WHICH ONE


002A CB OJ ADDB t3 NO, PROCEED TO NEXT ROW
002C 78 8002 ASL PIADB UPDATE SCAN PATTERN
002F OA 40 DEC $40 CONTINUE IF ANY ROWS NOT SCANNED
0031 26 EE BNE FROW
0033 3F SWI
0034 5C FCOL INCB KEY NUMBER = KEY NUMBER + 1
0035 44 LSRA IS THIS COLUMN GROUNDED?
0036 25 FC BCS FCOL NO, EXAMINE NEXT COLUMN
0038 3F SWI YES, KEY CLOSURE IDENTIFIED

Flowchart:

KEY NUMBER = -1
COUNTER= Number
of rows
Keyboard output
port = 11 111 11 02

Update keyboard KEY NUMBER=


output port by KEY NUMBER + 1
shifting contents Shift column
left arithmetically inputs right 1 bit

KEY NUMBER=
KEY NUMBER+
number of columns
COUNTER =
COUNTER - 1

Yes

Each time a row scan fails, we must add the number of columns (3 in the exam­
ple) to the key number to move to the next row (try the procedure on the keyboard in
Figure 13-12).
We could generalize the program by making the number of rows, the number of
columns, and the masking patterns into named parameters with Equate (EQU) direc­
tives.
What result does the program produce in Accumulator B if no keys are being
pressed? Change the program so that it starts the scan over again in that case.
An alternative approach is to use the bidirectional capability of the PIA. 7 The pro­
cedure would be:

I. Ground all columns and save the row inputs.


13-38 6809 Assembly Language Programming

A Keyboard
PAO-PA7
"
} data inputs

Data Bus 6820


to CPU � PIA

Keyboard
CA1
strobe

( _J\_ or -u- )

Figure 13-13. 1/0 Interface for an Encoded Keyboard

2. Ground all rows and save the column inputs.


3. Use both the row and the column inputs to determine the key number from a
table.

Write a program to implement this procedure.

13-6. AN ENCODED KEYBOARDS

The processor will fetch data, when it is available, from an encoded keyboard that
provides a strobe along with each data transfer.
An encoded keyboard provides a unique code for each key. It has internal
electronics that perform the scanning and identification procedure of the previous
example. The tradeoff is between the simpler software required by the encoded
keyboard and the lower cost of the unencoded keyboard.
Encoded keyboards may use diode matrices, TTL encoders, or MOS encoders.
The codes may be ASCII, EBCDIC, or a custom code. PROMs are often part of the
encoding circuitry.
The encoding circuitry may do more than just encode key closures. It may also
debounce the keys and handle "rollover," the problem of more than one key being
struck at the same time. Common ways of handling rollover are "2-key rollover," in
which two keys (but not more) struck at the same time are resolved into separate
closures, and "n-key rollover," in which any number of keys struck at the same time
are resolved into separate closures.
The encoded keyboard also provides a strobe with each data transfer. The
strobe indicates that another key has been pressed. Figure 13-13 shows the interface
between an encoded keyboard and the 6809 microprocessor. We tie the keyboard strobe
line to input CAl; a pulse on the strobe line sets bit 7 of the PIA Control Register. Bit 1
of the Control Register determines which edge (leading or trailing) of the pulse the PIA
recognizes. Bit l = 0 to recognize the trailing edge (high-to-low transition), and 1 to
recognize the leading edge (low-to-high transition).
The PIA thus contains an edge-sensitive latched serial status port as well as a
parallel data port. It also contains an inverter that allows it to recognize either edge of a
pulse. A PIA can therefore replace many simple circuit elements, such as flip-flops,
gates, inverters, and buffers. The designer can correct errors by changing the contents of
Using the 6820 Peripheral Interface Adapter (PI A) 13-39

the PIA control register (a simple software change) rather than by rewiring a bread­
board. For example, changing the active edge on the strobe line requires the changing of
one bit in a program, wherease it might require additional parts and rewiring on a bread­
board.
Be careful, however, of the fact that the PIA does not contain an input latch. An
actual interface may require a latch if the keyboard is not guaranteed to hold its data.
The latch can also be controlled by the strobe signal.

Task: Wait for an active-low strobe on control line CA 1 and then load the keyboard
data into Accumulator A.
Note that reading the data from the Data Register clears the status bit (this circui­
try is part of the 6820 PIA).

Flowchart:

Read Control
register

Read Data
register

The hardware must hold the control lines in a logic one state while RESET is
active to prevent the accidental setting of status flags. An initial read of the Data
Registers in the startup routine may be used to clear the PIA status bits.9

Program 13-6:

8001 PIACA EQU $8001


8000 PIADDA EQU $8000
9000 PIADA EQU $8000
*

0000 ORG $0000


0000 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTER
0003 7F 8000 CLR PIADDA MAKE ALL DATA LINES INPUTS
0006 86 04 LDA #%00000100 ADDRESS DATA REGISTER
0008 B7 8001 STA PIACA
OOOB 86 8001 KBWAIT LDA PIACA HAS KEY BEEN PRESSED?
OOOE 2A FB BPL KBWAIT NO, WAIT
0010 s�; 8000 LDA PIADA YES, FETCH DATA FROM KEYBOARD
0013 3F SWI

To set control register bit 7 on low-to-high transitions on the keyboard strobe line,
simply replace LOA :*f01r>00000100 with LOA :*f%00000110.
13-40 6809 Assembly Language Programming

If we tied the keyboard strobe line to CA2, control register bit 6 would then serve
as the status latch.
Show that reading the Data Register clears the status bit, indicating that the CPU
has read the most recent data and allowing the next input operation to occur. Hint: Save
the contents of the PIA control register in memory before and after the instruction LOA
PIADA is executed. What happens if you replace LOA with STA? How about TST,
CLR, COM, ADD? Remember that writing data into the Data Register does not clear
the status bit, nor does writing data into or reading data from the control register. What
happens if you replace LOA PIADA with LOA PIACA or STA PIACA?
One reason why we are concerned with the effects of instructions on PIA
registers is that we may want to use the control lines for purposes that have nothing
to do with the data ports. For example, we may be using a PIA to interface a simple pe­
ripheral (e.g., a set of switches or single LEOs) that does not require any status or con­
trol lines. The control lines are then available as serial 1/0 lines at no additional hard­
ware cost. The only problem is that we must manipulate these lines using facilities that
are provided on the assumption of a direct connection between the serial lines and the
parallel data port.

13-7. A DIGITAL-TO-ANALOG CONVERTER10-13

The processor sends data to an 8-bit digital-to-analog converter, which has an


active-low latch enable.
Digital-to-analog converters produce the continuous signals required by
solenoids, relays, actuators, and other electrical and mechanical output devices. Typi­
cal converters consist of switches and resistor ladders with the appropriate resistance
values. The user must generally provide a reference voltage and some other digital and
analog circuitry, although complete units are becoming available at low cost.
Figure 13-14 describes the 8-bit Signetics NE5018 D/ A converter, which con­
tains an on-chip 8-bit parallel data input latch. A low level on the LE (Latch Enable)
input gates the input data into the latches, where it remains after LE goes high.

0/A Converter Interface

Figure 13-15 illustrates the interfacing of the NE5018 to a 6809 system. Note
that port B of the PIA automatically produces the active-low pulse required to latch the
data into the D/ A converter; CB2 acts as an OUTPUT READY signal, indicating that
the CPU has sent data to the output port. Remember that in the brief pulse mode, CB2
goes low automatically on the clock pulse following a write operation on Data Register
B, and remains low until the next clock pulse (see Table 13-5). The control register bits
that cause the PIA to operate this way are:

Bit 5 1 to make CB2 an output

Bit 4 0 to make CB2 a pulse

Bit 3 = 1 to make CB2 a brief pulse that typically lasts one clock cycle. (Enable
pulses and clock pulses are the same in typical 6809 systems).

Note that the PIA contains an output latch. The data therefore remains stable dur­
ing and after conversion, even though the processor only leaves it on the data bus for
one clock cycle. Output latches are essential in microcomputer systems, since the pro-
D1gital
LE DB7 DB6 DB5 084 083 DB2 081 DBO GND
MSB LSB

Latches and
Switch Drivers
�, sum
vee
---
.._ 0
�•.,..... . Node

VREF O--­ ...._


...._. _OV
Out o ut
DAC Current
Output c
Amp
"'
::::
VR

.___
EF 0 ___. ___ I -----0 Comp (J(l
Ad1
::r
_0 Analog (1)
,.____
• .._ 0'-
GND 00
_l_ DAC Switches -
N
0
- '"tl
(1)
�.
R "0
::r
• I (1)
....,
"'
::::
;:;
....,
;;;;"'
t:')
(1)

Bipolar >
c.
Offset "'
Vee ?.
(1)
....,
All R values equal 5 kll and are thermally matched.


>

Figure 13-14. Signetics NE5018 D/ A Converter ....


Co)


....
13-42 6809 Assembly Language Programming

6820 NE5018
PIA 0/A

-
Converter
Data Bus Analog
(from CPU) t )

PBO-PB7
v) Output

-
LE
CB2

I l

Figure 13-15. 1/0 Interface for an 8-Bit Digital-to-Analog Converter

cessor uses its data bus constantly to transfer data and instructions to and from memory.
The converter typically requires only a few microseconds to produce analog outputs, but
other peripherals may need the data for much longer periods.
In applications where eight bits of resolution are not enough, you can use the
widely available 10 to 16-bit converters. Ones that are advertised as "microprocessor­
compatible" usually have separate data ports for the most and least significant bytes.
Such devices are much easier to interface than devices that only accept all the data at one
time through a single port.
The PIA serves as both a parallel data port and a serial control port. CB2 pro­
vides a pulse that lasts one clock cycle after the CPU latches output data into the PIA.
This pulse is long enough to meet the requirements (typically 400 ns) of the NE5018
converter.

Task 13-7. Send Data to D/ A Converter

Purpose: Send data from memory location 0040 to the D/ A converter.

Flowchart:

Data = (0040)

Send data to
converter and
latch it
Using the 6820 Peripheral Interface Adapter (P! A) 13-43

Program 13-7:

8003 PIAC8 EQU $8003


8002 PIADD8 EQU $8002
8002 PIAD8 EQU $8002
*

0000 ORG $0000


0000 7F 8003 CLR PIAC8 ADDRESS DATA DI RECTION REGISTER
0003 86 FF LOA #$FF MAKE ALL DATA LINES OUTPUTS
0005 87 8002 STA PIADD8
0008 86 2C LOA #%00101100 ADDRES S DATA REGISTER,
OOOA 87 8003 STA PIACB PROVIDE BRIEF STROBE
0000 06 40 LOB $40 GET DATA
OOOF F7 8002 STB PIADB SEND DATA TO 0/A CONVERTER
*
A ND LATCH
0012 3F SWI

The PIA produces the Load pulse automatically after the CPU stores the data in
the Data Register. No explicit instructions are necessary. Although automatic opera­
tions like this save time and memory, they also result in documentation problems since
there is no record in the program of when they occur. To understand the operation of
this interface, you would need a detailed understanding of the 6820 device as well as a
hardware schematic and a program listing. Such requirements make maintenance and
updating difficult.
The automatic pulse lasts only one clock cycle. If this is not long enough (or if an
active-high pulse is necessary), we could use the level output from CB2. This operating
mode is often called a manual mode, since the PIA does not produce any pulses auto­
matically. The program to use the mode would be:

CLR PIACB ADDRESS DATA DIRECTION REGISTER


LOA nSfF MAKE ALL DATA LINES OUTPUTS
STA PIADDB
LDA #%00110100 ADDRESS DATA REGISTER, PULSE LOW
STA PIACB
LOB $40 GET DATA
STB PIADB SEND DATA TO DAC
ORA #%00001000 OPEN DAC LATCH (BRING ENABLE HIGH)
STA PIACB
ANDA #%11110111 LATCH DATA (BRING ENABLE LO\•i)
STA PIACB
SWI

This approach requires more instructions, but it produces a longer pulse and is
easier to understand. Here bit 4 of the PIA control register is set to make CB2 a level
with the value of bit 3. We can then set and clear bit 3 using the logical instructions (OR
with '1' to set, AND with '0' to clear).
In the level or manual mode, CB2 is completely independent of operations on
the parallel data port. It is simply a serial output that is available for any purpose.
The only precaution one must take in using it is to avoid changing any of the other
bits in the PIA control register, since they have unrelated functions. Using the logical
OR and AND instructions makes the procedure independent of the contents of the PIA
control register, since only bit 3 is changed.

13-8. ANALOG-TO-DIGITAL CONVERTER14-19

The processor fetches data from an 8-bit analog-to-digital converter that requires
a Start Conversion pulse to start the conversion process and provides an End of Con ver­
sion output to indicate the completion of the process and the availability of valid data.
13-44 6809 Assembly Language Programming

Analog-to-digital converters handle the continuous signals produced by various


types of sensors and transducers. The converter produces the digital input that the
computer requires.
One form of analog-to-digital converter is the successive approximation device,
which makes a direct 1-bit comparison during each clock cycle. Such converters are fast
but have little noise immunity. Dual slope integrating converters are another form of
analog-to-digital converter. These devices take longer to con vert data but are more
resistant to noise. Other techniques, such as the incremental charge balancing techni­
que, are also used.
Analog-to-digital converters usually require some external analog and digital cir­
cuitry, although complete units are becoming available at low cost.

NATIONAL
MM5357 8-bit AID converter

General Description

The MM535 7 is an 8-bit monolithic A/D converter using P-channel ion-implemented MOS technology. It
contains a high input impedance comparator. 256 series resistors and analog switches, control logic and
output latches. Conversion is performed using a successive approximation technique where the unknown
analog voltage is compared to the resistor tie points using analog switches. When the appropriate tie
point voltage matches the unknown voltage, conversion is complete and the digital outputs contain an 8-
bit complementary binary word corresponding to the unknown. The binary output is tri-state to permit
bussing on common data lines.

Features Key Specs

Low cost Resolution 8 bits

+5V, 10 V input ranges Linearity + 1/2 LSB


No missing codes Conversion speed 401-'S
Ratiometric conversion Input impedance > 100 Met>
Tri-state outputs Supply voltages +5 V, -12 V, GND
Contains output latches Clock range 5.0 kHz to 2.0 MHz
TTL compatible

Timing Diagram:

Clock Input

Start +5 V r\_
-

Conversion
ov--1 ��-----------------�
EOC

---,1
Output Enable +5V ----- r-
0 v -------11�--JJ

Disable Delay -

Data is complementary binary (Full scale is "Os" output).

Figure 13-16. General Description and Timing Diagram


for the National 5357 AID Converter
Using the 6820 Peripheral Interface Adapter (PI A) 13-45

Connection Diagram

2-4 1 18 Voo
2-3 2 17 2-5
2-2 3 16 2-6
15 +V REF
MM5357
(MSBl 2-1 4
R Network 5 AD 14 2-7
STRT CONY 6 Converter 13 2-s (LSB)
Output Enable 7 12 v,N
VGG 8 11 Clock
EOC 9 10 Vss

Typical Application

15 4
+5V +VREF 2-1 a MSB
10 3
+5V Vss 2-2 a
18 2
GND Voo 2-3 -
1
-5 v 2-4 a
--�
8
R NET
11 Digital Output
-12 v VGG 2-5
12 16
Analog Input v 2-6 -

Clock
11-
C � MM535
A D
7 2_7
14
..
6a I 2-8
13
Converter
Start Conversation SC - LSB
7 9
Output Enable OE EOC End of Conversion

+5 v < v,
N < -5 v

Figure 13-17. Connection Diagram and Typical Application


for the National 5357 AID Converter

Figure 13-16 contains a general description and a timing diagram for the
National MM5357 8-bit AID converter. The device contains output latches and tristate
data outputs. A pulse on the Start Conversion (STRT CONY) line starts conversion of
the analog input; after about 40 clock cycles (the converter requires a TTL level clock
with a minimum pulse width of 400 ns), the result will go to the output latches and the
End of Conversion (EOC) output will indicate this by going high. Data is read from the
latches by applying a '1' to the OUTPUT ENABLE input. Figure 13-17 shows the con­
nections for the device and some typical applications circuits.

A/D Converter Interface

Figure 13-18 shows the interface between the 6809 microprocessor and the 5357
AID converter. Control line CA2 is used in the level (manual) output mode to provide
an active-high Start Conversion pulse of sufficient length. The End of Conversion signal
is tied to control line CAl so bit 7 of PIA Control Register A is set when EOC goes high.
The important transition on the End of Conversion line is the leading edge (low-to-high
transition), which indicates the completion of the conversion. Here we are using the
6820 PIA to handle parallel input, serial input, and serial output, since the AID con­
verter requires a complete handshake. The OUTPUT EN ABLE pin on the converter is
tied high, since we are not placing the data directly on the microprocessor's tristate data
bus. Note (see Fig. 13-16) that the converter's data outputs are complementary binary
(an all zeros output is full scale).
13-46 6809 Assembly Language Programming

6820 National
PIA 5357
A/0
Data Bus
to CPU
...


PAO-PA7 v

Converter -
Analog
Input

STAT
CA2 CA 1 EOC CONV

� + I t
Figure 13-18. Interface for an 8-Bit Analog-to-Digital Converter

Task 13-8. Input from Converter

Purpose: Start the conversion process, wait for End of Conversion (EOC) to go high,
then read the data and store it in memory location 0040.

Program 13-8:
8001 PIACA EQU $8001
8000 PIADDA EQU $8000
8000 PIADA EQU $8000
*

0000 ORG $0000


0000 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTER
0003 7F 8000 CLR PIADDA MAKE ALL DATA LINES INPUTS
0006 86 36 LDA #%00110110 BRINGSTART LOW, TRIGGER ON
0008 B7 8001 STA PIACA EOC GOING HIGH
OOOB 8A 08 ORA #%00001000 BRING START CONVERSION HIGH
OOOD 87 8001 STA PIACA
0010 84 F7 ANDA #%11110111 BRING START CONVERSION LOW
0012 B7 8001 STA PIACA
0015 B6 8001 WTEOC LDA PIACA HAS CONVERSION BEEN COMPLETED?
0018 2A FB BPL WTEOC NO, WAIT
001A 86 8000 LDA PIADA YES, FETCH DATA FROM CONVERTER
001D 43 COMA COMPLEMENT DATA TO PRODUCE TRUE

VALUE
001E 97 40 STA $40 SAVE DATA IN MEMORY
0020 3F SWI

This program would use less time and memory if we used Index Register X to
address the PIA. Rewrite the program to do this. We have used explicit addresses in the
interest of clarity.
The PIA control register bits are determined as follows:

Bit 5 = 1 to make CA2 an output.


Bit 4 = 1 to make CA2 a level (i.e., to operate in the manual mode).
Bit 3 0 to bring Start Conversion low initially.
Bit 1 1 to set bit 7 on a low-to-high transition (leading edge) on the End of
Conversion line.

A delay routine of appropriate length Oonger than the maximum guaranteed


conversion time) could replace the examination of the status bit.
Using the 6820 Peripheral Interface Adapter (PIA) 13-47

Flowchart:

Pulse Start
Conversion
line

No

(Has EOC gone high?)

Read data from


data input port
(0040) = Data

Here the PIA serves as a parallel data port, a serial status port, and a serial control
port. An initial read of the Data Register in the startup routine would clear the status
flags originally and eliminate problems that might be caused by stray pulses on the con­
trol lines.

13-9. A TELETYPEWRITER (TTY)

We will transfer data to and from a standard 1 0-character-per-second serial


teletypewriter.

Standard TTY Character Format

The common teletypewriter transfers data in an asynchronous serial mode. The


procedure is as follows:

1. The line is normally in the mark state (logic 'I').


2. A Start bit (space state or logic '0').
3. The character is usually 7-bit ASCII with the least significant bit transmitted
first.
4. The most significant bit is a Parity bit, which may be even, odd, or fixed at
zero or one.
5. Two stop bits (logic 'I 's) follow each character to provide a minimum separa­
tion between characters.

Figure 13-19 shows the format. Note that each character requires the transmission
of eleven bits, of which only seven contain information. Since the data rate is ten charac­
ters per second, the bit rate is 1 0 x 11, or 110 Baud. Each bit therefore has a width of
11110 of a second, or 9.1 milliseconds. This width is an average; the teletypewriter does
not maintain it to any high level of accuracy.
13-48 6809 Assembly Language Programming

Mark ('1')--..,

Space ('0')
. ·o· '1' ·o· ·o· ·o·
,.

---- -..- --
Start
...______-v---
,..-- -------
�- -..- '-..,.
Parity Stop Stop .-
Bit 7 Data Bits Bit Bit Bit

Character is ASCII 'E' with odd parity (45 hex)

The transmission order is: Start bit ('0'). bit 0. bit 1, bit 2. bit 3, bit 4, bit 5. bit 6.
Parity bit. Stop bit ('1'). Stop bit ('1').

Figure 13-19. Teletypewriter Data format

TTY Receive Mode

This is the receive procedure, flowcharted in Figure 13-20:

Step 1. Look for a Start bit (a logic zero) on the data line.
Step 2. Center the reception by waiting one-half bit time, or 4.55 milliseconds.
Step 3. Fetch the data bits, waiting one bit time before each one. Assemble the
data bits into a word by tirst shifting the bit to the Carry and then cir­
cularly shifting the data with the Carry. Remember that the least signifi­
cant bit is received first.
Step 4. Generate the received Parity and check it against the transmitted Parity.
If they do not match, indicate a "Parity error."
Step 5. Fetch the Stop bits (waiting one bit time between inputs). If they are not
correct (if both Stop bits are not one), indicate a "framing error."

TTY Transmit Mode

This is the transmit procedure, flowcharted in Figure 13-21:

Step 1. Transmit a Start bit (i.e., a logic zero).


Step 2. Transmit the seven data bits, starting with the least significant bit.

Step 3. Generate and transmit the Parity bit.

Step 4. Transmit two Stop bits (i.e., logic ones).

The transmission routine must wait one bit time between output operations.

Task 13-9a. Read Data from TTY

Purpose: Fetch data from a teletypewriter using bit 7 of a PIA data port and place the
data in memory location 0060. Figure 13-20 describes the procedure.
Using the 6820 Peripheral Interface Adapter (PIA) 13-49

Start

Get input data

Parity
error

Wait one-half
COUNT= 2
bit time

COUNT= 8
Wait one bit time
DATA= 0

Wait one bit time Get input data

Get input data


Carry = Input data
Shift data right
with Carry

COUNT= Framing
COUNT- error

COUNT=
COUNT -1

Generate
received parity

Figure 13-20. Flowchart for Receive Procedure


13-50 6809 Assembly Language Programming

Carry = Start bit


Get output data
Shift data left
circularly with Carry
COUNT= 11

Send data to
Output Port

Shift data right


circularly with Carry
Carry = 1 (Stop bit)
Wait 1 bit time

COUNT=
COUNT -1

Figure 13-21. Flowchart for Transmit Procedure

Program 13-9a:

Assume that the serial port is bit 7 of the PIA and that no parity or framing check
is necessary. 8001 PIACA EQU $8001
8000 PIADDA EQU $8000
8000 PI ADA EQU $8000
*

0000 ORG $0000


0000 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTER
0003 7F 8000 CLR PIADDA MAKE ALL DATA LINES INPUTS
0006 86 04 LOA l%00000100 ADDRESS DATA REGISTER
0008 B7 8001 STA PIACA
OOOB B6 8000 WTSTB LDA PI ADA IS THERE A START BIT?
OOOE 2B FB BMI WTSTB NO, WAIT
0010 BD 00 3 0 JSR DLY'2 YES, DELAY HALF BIT TIME TO
*
CENTER RE.C.EPTION
0013 86 80 LOA 1%10000000 COUNT WITH '1' BIT IN MSB
0015 BD 00 35 TTYRCV JSR DELAY WAIT 1 BIT TIME
0018 79 8000 ROL PIADA GET NEXT DATA BIT
0018 46 RORA COMBINE WITH PREVIOUS DATA
OOlC 24 F7 BCC TTYRCV CONTINUE UNTIL
COUNT BIT
OOlE 97 60 STA $60 TRAVERSES DATA
0020 3F SWI
Using the 6820 Peripheral Interface Adapter (PIA) 13-51

(Delay program)

0030 8E 0231; DLY2 LOX t$0236 COUNT FOR 4.55 MS (CLOCK


0033 20 03 BRA DLY RATE = 1 MHZ)
0035 8E 046C DELAY LOX I$046C COUNT FOR 9.1 MS
0038 30 1F DLY LEAX -l,X
003A 21; FC BNE DLY
003C 39 RTS

Remember that bit 0 of the data is received first.


This program assumes that the monitor has initialized the Hardware Stack
Pointer. If this is not the case, you will have to initialize the Hardware Stack Pointer with
LOS as shown in Chapter 10.
We obtained the constants for the delay routine as described earlier in this
chapter, assuming a clock rate of 1 MHz. You may want to check them for yourself. The
delay times do not have to be highly accurate because the routine centers the reception,
each character is handled separately, the bit rate is low, and the teletypewriter itself is
not highly accurate.
How would you extend this program to check parity?

Task 13-9b. Write Data to TTY

Purpose: Transmit data to a teletypewriter using bit 0 of a PIA data port. The data is in
memory location 0060.

Program 13-9b:

Assume that parity need not be generated.


0035 DELAY EQU $0 035
8001 PIACA EQU $8001
8000 PIADA EQU $8000
8000 PIADDA EQU $8000
*

0000 ORG $0000


0000 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTER
0003 86 FF LDA tSFF MAKE ALL DATA LINES OUTPUTS
0005 B7 8000 STA PIADDA
0008 86 04 LDA l%00000100 ADDRESS DATA REGISTER
OOOA B7 8001 STA PIACA
OOOD 96 60 LDA $60 GET DATA
OOOF C6 OB LDB U1 COUNT = 11 BITS IN CHARACTER
0011 7F 8000 CLR PIADA SEND START BIT
0014 9D 35 TBIT JSR DELAY WAIT 1 BIT TIME
0016 1A 01 ORCC 1%00000001 SET CARRY TO FORM STOP BIT
0018 46 RORA GET NEXT BIT OF CHARACTER
0019 79 8000 ROL PIADA SEND NEXT BIT TO TTY
001C SA DECB
001D 26 FS BNE TBIT
001F 3F SWI

The DELAY subroutine is the same as before. Remember that bit 0 of the data
must be transmitted first.
'1' on the teletypewriter line as part
In actual applications, you should place a logic
of the startup routine, since that line should normally be in the mark (1) state.
Each character consists of 11 bits, beginning with a start bit ('0') and ending with
two stop bits ( 1 's). The instruction ORCC =#:%0000000 1 sets the least significant bit of
'

the Condition Code Register (the Carry flag), thus generating a logic '1' which RORA
then shifts into the most significant bit of Accumulator A.
We can generate parity by counting bits as shown in Chapter 6. The program is
13-52 6809 Assembly Language Programming

as follows:

LDA Sf'iO GET DATA


CLRB BIT COUNT = ZERO INITIALLY
CHBIT ASLA SHIFT A DATA BIT TO CARRY
ADCG �0 IF BIT IS l, ADD 1 TO BIT COUNT
TSTA KEEP COUNTING UNTIL DATA BECOMES ZERO
BNE CHBIT
SWI

Accumulator B contains the number of' I' bits in the data. The least significant bit
of Accumulator B is therefore an even Parity bit.

UART

These procedures are sufficiently common and complex to merit a special LSI
device: the UART, or Universal Asynchronous Receiver/Transmitter.zu The UART
will perform the reception procedure and provide the data in parallel form and a Data
Ready signal. It will also accept data in parallel form, perform the transmission pro­
cedure, and provide a Peripheral Ready signal when it can handle more data. UARTs
may have many other features, including:

I. Ability to handle various bit lengths (usually 5 to 8), parity options, and num­
bers of Stop bits (usually 1, 1-1/2, and 2).
2. Indicators for framing errors, parity errors, and "overrun errors" (failure to
read a character before another one is received).
3. RS-23221 compatibility; i.e., a Request-to-Send (RTS) output signal that indi­
cates the presence of data to communications equipment and a Clear-to-Send
(CTS) input signal that indicates, in response to RTS, the readiness of the
communications equipment. There may be provisions for other RS-232 sig­
nals, such as Received Signal Quality, Data Set Ready, or Data Terminal
Ready.
4. Tristate outputs and control compatibility with a microprocessor.
5. Clock options that allow the UART to sample incoming data several times in
order to detect false Start bits and other errors.
6. Interrupt facilities and controls.

UARTs act as four parallel ports: an input data port, an output data port, an input
status port, and an output control port. The status bits include error indicators as well as
Ready flags. The control bits select various options. UARTs are inexpensive ($5 to $50,
depending on features) and easy to use.

PROBLEMS

13-1. An On-Off Pushbutton

Purpose: Each closure of the pushbutton complements (inverts) all the bits in memory
location 0040. The location initially contains zero. The program should con­
tinuously examine the pushbutton and complement location 0040 with each
Using the 6820 Peripheral Interface Adapter (PIA) 13-53

closure. You may wish to complement a display output port instead, so as to


make the results easier to see.

Sample Case:

Location 0040 initially contains zero.


The first pushbutton closure changes location 0040 to FF16, the second changes it
back to zero, the third back to FF11, etc. Assume that the pushbutton is debounced in
hardware. How would you include debouncing in your program?

13-2. Debouncing a Switch in Software

Purpose: Debounce a mechanical switch by waiting until two readings, taken a


debounce time apart, give the same result. Assume that the debounce time
(in ms) is in memory location 0040 and store the switch position in memory
location 0041.

Sample Problem:

(0040) = 03 causes the program to wait 3 ms between readings

13-3. Control for a Rotary Switch

Purpose: Another switch serves as a Load switch for a four-position unencoded rotary
switch. The CPU waits for the Load switch to close (be zero), and then reads
the position of the rotary switch. This procedure allows the operator to move
the rotary switch to its final position before the CPU tries to read it. The pro­
gram should place the position of the rotary switch into memory location
0040. Debounce the Load switch in software.

Sample Problem:

Place rotary switch in position 2. Close Load switch.

Result: (0040) = 02

13-4. Record Switch Positions on lights

Purpose: A set of eight switches should have their positions renected on eight LEOs.
That is to say, if the switch is closed (zero), the LED should be on; otherwise,
the LED should be off. Assume that the CPU output port is connected to the
cathodes of the LEOs.

Sample Problem:

SWITCH 0 CLOSED Result: LED 0 ON


SWITCH 1 OPEN LED 1 OFF
SWITCH 2 CLOSED LED 2 ON
SWITCH 3 OPEN LED 3 OFF
SWITCH 4 OPEN LED 4 OFF
SWITCH 5 CLOSED LED 5 ON
SWITCH 6 CLOSED LED 6 ON
SWITCH 7 OPEN LED 7 OFF
13-54 6809 Assembly Language Programming

How would you change the program so that a switch attached to bit 7 of Port A of
PIA #2 determines whether the displays are active ( i.e., if the control switch is closed,
the displays attached to Port B reflect the switches attached to Port A; if the control
switch is open, the displays are always off) ? A control switch is useful when the displays
may distract the operator, as in an airplane.
How would you change the program to make the control switch an on-off
pushbutton; that is, each closure inverts the previous state of the displays? Assume that
the displays start in the active state and that the program examines and debounces the
pushbutton before sending data to the displays.

13-5. Count on a Seven-Segment Display

Purpose: The program should count from 0 to 9 continuously on a seven-segment dis­


play, starting with zero.
Hint: Try different timing lengths for the displays and see what happens. When does the
count become visible? What happens if the display is blanked part of the time?

13-6. Separating Closures from an Unencoded Keyboard

Purpose: The program should read entries from an unencoded 3 x 3 keyboard and save
them in an array. The number of entries required is in memory location 0040
and the array starts in memory location 0041.
Separate one closure from the next by waiting for the current closure to end.
Remember to debounce the keyboard ( this can be simply a 1 ms wait) .

Sample Problem:
(0040) = 04
Entries are 7. 2, 2, 4

Result: (0041) 07
(0042) 02
(0043) 02
(0044) = 04

13-7. Read a Sentence from an Encoded Keyboard

Purpose: The program should read entries from an ASCII keyboard (7 bits with a zero
Parity bit ) and place them in an array until it receives an ASCII period ( hex
2E ) . The array starts in memory location 0040. Each entry is marked by a
strobe as in Example 13-6.

Sample Problem:
Entries are H. E. L. L, 0.

Result: (0040) 48 'H'


(0041) 45 'E'
(0042) = 4C ' L'
(0043) 4C 'L'
(0044) 4F ·o·
. .
(0045) = 2E
Using the 6820 Peripheral Interface Adapter (PIA) 13-55

13-8. A Variable Amplitude Square Wave Generator

Purpose: The program should generate a square wave, as shown in the next figure,
using a 01 A converter. Memory location 0040 contains the scaled amplitude
of the wave, memory location 0041 the length of a half cycle in milliseconds,
and memory location 0042 the number of cycles.
Assume that a digital output of 8016 to the converter results in an analog output of
zero volts. In general, a digital output of D results in an analog output of (D-80)180 x
-V REF volts.

Sample Problem:

(0040) A0 16
(0041) 04
(0042) 03
Result.

+ VREF
I
"'
g> -
VREF
4-
I
I
r---JF---1c---i----,-----r
F
o �---- ----
g

l �:::: L-.1
::4ms "ms
I T1me --------•

The base voltage is 80 16 = 0 volts.


Full scale is 1 0016= - VR EF volts.

So A015 = (A0-80)/80 x 1-VREFI = -VR EF/4

The program produces 3 pulses of amplitude V REF 14 with a half cycle length of 4 ms.

13-9. Averaging Analog Readings

Purpose: The program should take four readings from an AID converter 10 millise­
conds apart and place the average in memory location 0040. Assume that the
AID conversion time can be ignored.

Sample Problem:

Hexadecimal readings are 86 , 89, 81, 84

Result: (0040) = 851s

13-1 0. A 30 Character-per-Second Terminal

Purpose: Modify the transmit and receive routines of Example 13-9 to handle a 30 cps
terminal that transfers ASCII data with one stop bit and even parity. How
could you write the routines to handle either terminal depending on a flag in
memory location 0061; e.g., (0061) = 0 for the 30 cps terminal, and (0061) =

I for the 10 cps terminal?


13-56 6809 Assembly Language Programming

REFERENCES

I. A. Osborne et at. An Introduction to Microcomputers: Volume 2- Some Real


Microprocessors, pp. 9-45 through 9-54.

2. J. Gilmore and R. Huntington. "Designing with the 6820 Peripheral Interface


Adapter," Electronics, December 23, 1976, pp. 85-86.
3. The TTL Data Book for Design Engineers, Texas Instruments Inc., P.O. Box 5012,
Dallas, Tex. 75222, pp. 7-I5I through 7-156.
4. E. Dilatush. "Special Report: Numeric and Alphanumeric Displays," EDN, Janu­
ary 5, 1978, pp. 26-35.

5. The TTL Data Book for Design Engineers, Texas Instruments Inc., P.O. Box 5012,
Dallas, Tex. 75222, pp. 7-22 through 7-34.

6. A. Pshaenich. "Interface Considerations for Numeric Display Systems," Motorola


Semiconductor Products Inc., Application Note AN-741,Phoenix, Ariz. 1975.

7. Motorola Semiconductor Products Inc., Microprocessor Applications Manual,


McGraw-Hill, New York, I 975, pp. 5-6 through 5-11.

8. Motorola Semiconductor Products Inc., Microprocessor Applications Manual,


McGraw-Hill, New York, 1975, pp. 5- I through 5-5.

9. See Reference 2.
10. J. Kane et al. An Introduction to Microcomputers: Volume 3- Some Real Support
Devices, Osborne/McGraw-Hill, Berkeley, Calif. I 979, Section El.

11. E. R. Hnatek. A User's Handbook of DIA and AID Converters, Wiley, New York,
1976.

12. P. H. Garrett. Analog Systems for Microprocessors and Minicomputers, Reston Pub­
lishing Co. (Prentice-Hall), Reston, VA, 1978.

13. B. Amazeen. "Monolithic D-A Converter Operates on Single Supply," Electronics,


February 28, 1980, pp. 125-31.

14. See Reference 11.

15. See Reference 12.

16. J. Kane et al. An Introduction to Microcomputers: Volume 3- Some Real Support


Devices, Osborne/McGraw-Hill, Berkeley, Calif. 1979, Section E2.

17. D. Aldridge. ''Analog to Digital Conversion Techniques with the M6800


Microprocessor System," Motorola Semiconductor Products Inc. Application
Note AN-757, Phoenix, Ariz. 1975.

18. P. Bradshaw. "Two-Chip AID Converter," Electronic Design, March 29, 1979, pp.
128-36.
19. M. Tuthill and D. P. Burton. "Low-Cost AID Converter Links Easily with
Microprocessors," Electronics, August 30, 1979, pp. 149-55.

20. For a discussion ofUARTs, seeP. Ronyet al. "The Bugbook lla," E and L Instru­
ments Inc., 61 First Street, Derby, Conn. 06418 or D. G. Larsen et at. "INWAS:
Interfacing with Asynchronous Serial Mode," IEEE Transactions on Industrial
Electronics and Control Instrumentation, February 1977, pp. 2- I 2.
Using the 6820 Peripheral Interface Adapter (PI A) 13-57

21. "Interface Between Data Terminal Equipment and Data Communications Equip­
ment Employing Serial Binary Data Interchange," EIA RS-232C, Electronic
Industries Association, 2001 I Street N.W., Washington, D.C. 20006, August
1969.

J. Kane et al. An Introduction to Microcomputers: Volume J- Some Real Support


Devices, Osborne/McGraw-Hill, Berkeley, Calif. pp. J5-9 through J5-14.

G. Pickles. "Who's Afraid of RS-232?", Kilobaud, May 1977, pp. 50-54.

C. A. Ogdin. "Microcomputer Buses- Part II," Mini-Micro Systems, July 1978,


pp. 76-80.
14
Using the 6850 ACIA

The 6850 ACIA, or Asynchronous Communications Interface Adapter, (see


Figure 14-1) is a UART specifically designed for use in 6800, 6809, and 6502-based
microcomputers. It occupies two memory addresses and contains two read-only
registers (received data and status) and two write-only registers (transmitted data
and control). Tables 14-1 and 14-2 describe the contents of these registers.

ADDRESSING THE 6850 ACIA

The internal registers of the ACIA are addressed by means of the RS (register
select) and R/W (read/write) lines (see Table 14-3). If, as is usual, RS is tied to AO,
the least significant bit of the 6809's address bus, then the address of the Data Registers
is one larger than the address of the Control and Status Registers. The use of R/W for
addressing means that read and write cycles access different registers, so the program
can neither read the transmitted data or control registers nor write into the received data
or status registers. If the program must recall what it stored in the write-only registers, it
must retain a copy in RAM. We will refer to the addresses as ACIADR (the receive
data register when reading, the transmitted data register when writing), ACIASR
(the read-only status register), and ACIACR (the write-only control register).
ACIASR and ACIACR are the same physical address.
14-2 6809 Asscm bly Language Programming

Transmit Cl ock -
Clock
Generator

Parity
Generator f4-
Ena ble

t
� f4-
Transmit
Read/Write___.
Shift
Transmit
Chip Selecto-.
Chip
,.. Register
� Data
+
Select Transmit

Chip Select 1 ___. and Data


Read/Write Register
Chip Selec t i___. Control Transmit

Register Select-.
? � Control

j�
Clear-to- Send

Status
DO - -
� Register

D1 - .
.. Interrupt
A
- ...
Interrupt
Logic
� Request
D2 - ...

t +
D3 . Data
Bus
D4 - ... Buffers

. .. -
D5 -
)
.,
D6 - -
Request­
-


-..
Control to-Send
D7 - Register
-
Receive
Control
.--


......
Parity
--
Check �
Receive
Data
Register
Receive
At.,.
,..___

""
Shift
Register


- Clock
Receive Clock ...
Generator


Sync
Logic �._ Receive Data

Figure 14-1. Block Diagram of the 6850 ACIA


Using the 6850 ACIA 14-3

Table 14-1. Definition of 6850 ACIA Register Contents

Buffer Address

Data RS·R/W RS·R/W RS ·R/W RS·R/W


Bus Transmit Receive
Line Data Data Control Status
Number Register Register Register Register

(Write Only) (Read Only) (Write Only) (Read Only)

0 Data Bit 0' Data Bit 0 Counter Divide Receive Data Register
Select 1 (CRO) Full (RDRF)

1 Data Bit 1 Data Bit 1 Counter Divide Transmit Data Register


Select 2 (CR 1 ) Empty (TORE)

2 Data Bit 2 Data Bit 2 Word Select 1 Data Carrier Detect


(CR2) (DCD)

3 Data Bit 3 Data Bit 3 Word Select 2 Clear-to-Send


(CR3) (CTS)

4 Data Bit 4 Data Bit 4 Word Select 3 Framing Error


(CR4) (FE)

5 Data Bit 5 Data Bit 5 Transmit Control 1 Receiver Overrun


(CR5) (OVRN)

6 Data Bit 6 Data Bit 6 Transmit Control 2 Parity Error (PE)


(CR6)

7 Data Bit r·· Data Bit r· Receive Interrupt Interrupt Request


Enable (CR7) (IRQ)

• Leading bit = LSB = Bit 0


•• Data bit will be zero in 7-bit plus parity modes
"' Data bit is "don't care" in 7 -bit plus parity modes

SPECIAL FEATURES

Note the following special features of the 6850 ACIA:

1. Read and write cycles address physically distinct registers. Therefore, you
cannot use the ACIA registers as addresses for instructions like Increment,
Decrement, or Shift, which involve both read and write cycles.

2. The ACIA Control register cannot be read by the CPU. You will have to
save a copy of the Control register in memory if the program needs its value.

3. The ACIA has no Reset input. It can be reset only by placing ones in Control
register bits 0 and 1. This procedure (called "Master Reset") is necessary
before the ACIA is used, in order to avoid having a random starting
character.

4. The RS-232 signals are all active-low. Request-to-Send (RTS), in particu­


lar, should be brought high to make it inactive if it is not in use.
14-4 6809 Assembly Language Programming

Table 14-2. Meaning of the 6850 ACIA Control Register Bits

CR6 CR5 Function

0 0 RTS =low. Transmitting Interrupt Disabled


0 1 irts =low. Transmitting Interrupt Enabled
1 0 RTS = high. Transmitting Interrupt Disabled
1 1 RTS = low. Transmits a Break level on the
Transmit Data Output. Transmitting
Interrupt Disabled

CR4 CR3 CR2 Function

0 0 0 7 Bits + Even Parity + 2 Stop Bits


0 0 1 7 Bits + Odd Parity + 2 Stop Bits
0 1 0 7 Bits + Even Parity + 1 Stop Bit
0 1 1 7 Bits + Odd Parity + 1 Stop Bit
1 0 0 8 Bits + 2 Stop Bits
1 0 1 8 Bits + 1 Stop Bit
1 1 0 8 Bits + Even Parity + 1 Stop Bit
1 1 1 8 Bits + Odd Parity + 1 Stop Bit

CR1 CRO Function

0 0 +1
0 1 +16
1 0 +64
1 1 Master Reset

Table 14-3. Internal Addressing for the 6850 ACIA

R/W Indexed Offset


RS
(Read/Write) Register Addressed from ACIA
(Register Select)
1 = Read, 0 = Write Control Register

0 0 Control Register (write-only) 0


0 1 Status Register (read-only) 0
1 0 Transmit Data Register (write-only) 1
1 1 Receive Data Register (read-only) 1

5. The ACIA requires an external clock. Typically, 1760Hz is supplied and the
+I 6 mode (Control register bit I = 0, bit 0 = 1) is used. The A CIA will use
the clock to center the reception and to avoid false Start bits caused by noise
on the lines.
6. The Data Ready (receive data register full, or RDRF) flag is bit 0 of the
Status register. The Peripheral Ready <transmit data register empty, or
TDRE) flag is bit 1 of the Status register.
Using the 6850 ACIA 14-5

PROGRAM EXAMPLES

14-1. RECEIVE DATA FROM TTY

Purpose: Receive data from a teletypewriter using a 6850 ACIA and store the data in
memory location 0060.

Program 14-1:
8010 ACIACR EQU $8010
8010 ACIASR EQU $8010
8011 ACIADR EQU $8011

0000 ORG $0000


0000 86 03 LOA t%00000011 MASTER RESET ACIA
0002 87 8010 STA ACIACR
0005 86 45 LOA t%0 1000101 ACIA OPERATING MODE -- TTY
0007 87 8010 STA ACIACR W ITH ODD PARITY
OOOA 86 8010 WAITD LOA ACIASR GET STATUS OF ACIA
OOOD 44 LSRA HAS DATA BEEN RECEIVED?
OOOE 24 FA BCC WAITD NO, WAIT
0010 86 BOll LOA ACIADR YES, READ THE DATA
0013 97 60 STA $60 AND SAVE IT IN MEMORY
0015 3 F SWI

The program must reset the ACIA originally by placing ones in Control register
bits 0 and l. The ACIA does have an internal power- on reset which holds the ACIA in
the reset state until Master Reset is applied.
The program determines the operating mode of the ACIA by setting the bits in
the Control Register as follows:

Bit 7 0 to disable the receiver interrupt


Bit 6 1 to make Request-to-Send (RTS) high (inactive)

Bit 5 0 to disable the transmitter interrupt


Bit 4 0 for 7-bit words
Bit 3 0, Bit 2 1 for odd parity with 2 Stop bits
Bit 1 0, Bit 0 I for --; - 16 clock (1760 Hz must be supplied)

The received data status flag is bit 0 of the ACIA Status Register. What would
happen if we tried to replace
LOA ACIASR
LSR A

with the single instruction


LSR ACIASR

Remember that the Status and Control registers share an address but are physically dis­
tinct.
Try adding an error-checking routine to the program. Set

(0061) = 0 if no errors occurred


= 1 if a parity error occurred
(Status register bit 6 = 1)
= 2 1f an overrun error occurred
(Status register bit 5 = 1)
= 3 if a framing error occurred
(Status register bit 4 = 1)

Assume that the priority of the errors is from left to right in the ACIA status
register (i.e., parity errors have priority over overrun errors which, in turn, have priority
over framing errors if more than one error has occurred).
14-6 6809 Assembly Language Programming

14-2. SEND DATA TO TTY

Purpose: Send data from memory location 0060 to a teletypewriter using a 6850 ACIA.

Program 14-2:
8010 ACIACR EQU $8010
8010 ACIASR EQU $8010
8011 ACIADR EQU $8011
*

0000 ORG $0000


0000 86 03 LOA 1%00000011 MASTER RESET ACIA
0002 87 8010 STA ACIACR
0005 86 45 LOA t%01000101 ACIA OPERATING MODE -- TTY
0007 87 8010 STA ACIACR WITH ODD PARITY
OOOA 86 02 LOA t%00000010 IS ACIA READY TO TRANSMIT?
oooc 85 8010 WAITR 8ITA ACIASR NO, WAIT
OOOF 27 F8 8EQ WAITR YES, GET DATA
0011 96 60 LOA $60 AND TRANSMIT IT
0013 87 8011 STA ACIADR
0016 3F SWI

The transmitter status flag is bit 1 of the ACIA Status register. The Bit Test
instruction is convenient here, since it performs a logical AND without changing the
contents of the Accumulator. How could you modify the receive program to use the Bit
Test instruction?

REFERENCES

A. Osborne et al. An Introduction to Microcomputers: Volume 2- Some Real


Microprocessors, pp. 9-55 through 9-61.

K. Fronheiser. "Device Operation and System Implementation of the


Asynchronous Communications Interface Adapter," Motorola Semiconductor
Products Inc. Application Note AN-754, Phoenix, AZ, 1975.
J. Volp. "Software Switches Baud Rate," EDN, November 5, 1979, p. 83.
15
Interrupts

Interrupts are inputs that the CPU examines as part of each instruction cycle.
These inputs allow the CPU to react to asynchronous events more efficiently than by
polling devices. The use of interrupts generally involves more hardware than does
ordinary (programmed) 1/0, but interrupts provide a faster and more direct response. I
Why use interrupts? Interrupts allow events such as alarms, power failure, the
passage of a certain amount of time, and peripherals having data or being ready to
accept data to get the immediate attention of the CPU. The program does not have to
examine (poll) every potential source, nor need the programmer worry about the
system missing events.
An interrupt system is like the bell on a telephone - it rings when a call comes in
so that you don't have to pick up the receiver occasionally to see if someone is on the
line. The CPU can go about its normal business (and get a lot more done). When some­
thing happens, the interrupt alerts the CPU and forces it to service the input before
resuming normal operations. Of course, this simple description becomes more compli­
cated (just like a telephone switchboard) when there are many interrupts of varying
importance and tasks that cannot be interrupted.

CHARACTERISTICS OF INTERRUPT SYSTEMS

The implementation of interrupt systems varies greatly. Among the questions


that characterize a particular system are:
1. How many interrupt inputs are there?
2. How does the CPU respond to an interrupt?
3. How does the CPU determine the source of an interrupt if the number of
sources exceeds the number of inputs?
4. Can the CPU differentiate between important and unimportant interrupts?
5. How and when is the interrupt system enabled and disabled?
15-2 6809 Assembly Language Programming

There are many different answers to these questions. The aim of all the imple­
mentations, however, is to have the CPU respond rapidly to interrupts and resume nor­
mal activity afterwards.
The number of interrupt inputs on the CPU chip determines the number of
different responses that the CPU can produce without any additional hardware or
software. Each input can produce a different internal response. Unfortunately, most
microprocessors have a very small number (one or two, typically) of separate interrupt
inputs.
The ultimate response of the CPU to an interrupt must be to transfer control to
the correct interrupt service routine and to save the current value of the Program
Counter. The CPU must therefore execute a Jump-to-Subroutine or Call instruction
with the beginning of the interrupt service routine as its address. This action will save
the return address in the Stack and transfer control to the interrupt service routine. The
amount of external hardware required to produce this response varies greatly. Some
CPUs internally generate the instruction and the address; others require external hard­
ware to form them. The CPU can only generate a different instruction or address for
each separate input.

Polling and Vectoring

If the number of interrupting devices exceeds the number of inputs, the CPU
will need extra hardware or software to identify the source of the interrupt. In the
simplest case, the software can be a polling routine which checks the status of the
device that may be interrupting. The only advantage of such a system over normal poll­
ing is that the CPU knows that at least one device is active. The alternative solution is
for additional hardware to provide a unique data input (or "vector") for each source.
The two alternatives can be mixed; the vectors can identify groups of inputs from which
the CPU can identify a particular one by polling.

Priority

An interrupt system that can differentiate between important and unimportant


interrupts is called a "priority interrupt system." Internal hardware can provide as
many priority levels as there are inputs. External hardware can provide additional levels
through the use of a Priority register and comparator. The external hardware does not
allow the interrupt to reach the CPU unless its priority is higher than the contents of the
Priority register. A priority interrupt system may need a special way to handle low­
priority interrupts that may be ignored for long periods of time.

Enabling and Disabling

Most interrupt systems can be enabled or disabled. In fact, most CPUs automat­
ically disable interrupts when a RESET is performed (so the startup routine can initialize
the interrupt system) and on accepting an interrupt (so that the interrupt will not inter­
rupt its own service routine). The programmer may wish to disable interrupts while pre­
paring or processing data, performing a timing loop, or executing a multi-byte operation.
An interrupt that cannot be disabled (sometimes called a "nonmaskable inter­
rupt") may be useful to warn of power failure, an event that obviously must take pre­
cedence over all other activities.
Interrupts 15-3

Disadvantages of Interrupts

The advantages of interrupts are obvious, but there are also disadvantages.
These include:

1. Interrupt systems may require a large amount of extra hardware.


2. Interrupts still require data transfers under program control through the CPU.
There is no speed advantage as there is with DMA.
3. Interrupts are random inputs, which make debugging and testing difficult.
Errors may occur sporadically, and therefore may be very hard to locate and
correct.2
4. Interrupts may involve a large amount of overhead if many registers must be
saved and the source must be determined by polling.

6809 INTERRUPT SYSTEM

The 6809 microprocessor's internal response to an interrupt is moderately com­


plex. The interrupt system consists of:

1. Two active-low maskable interrupts (IRQ and FIRQ) and an active-low


nonmaskable interrupt (NMI).
2. Separate interrupt disable (or mask) bits for the two maskable interrupts
(IRQ and FIRQ). If an interrupt mask bit is 1, the corresponding interrupt is
disabled. The IRQ mask bit (or I flag) is bit 4 of the Condition Code Register;
the FIRQ mask bit (or F flag) is bit 6 of the Condition Code Register. The E
(entire) flag (bit 7 of the Condition Code Register) distinguishes FIRQ inter­
rupts from other interrupts as we will describe later. As might be expected,
Reset sets both the I and F bits, thus starting the processor with both inter­
rupts disabled. This allows the programmer to initialize the system before
allowing interrupts.

6809 INTERRUPT RESPONSE

The 6809 checks the current status of the interrupt system at the end of each
instruction. If an interrupt input is active and enabled, the response is as follows:

1. The CPU disables the maskable interrupt (IRQ); that is, it sets bit 4 (the I
flag) of the Condition Code Register. If the active input is FIRQ or NMI, the
CPU also disables the fast interrupt (FIRQ); that is, it sets bit 6 (the F flag) of
the Condition Code Register.
2. If the CPU is not executing CWAI or SYNC (we will discuss those instruc­
tions later), it clears theE flag in response to FIR-Q and sets it otherwise.
The E flag is bit 7 of the Condition Code Register.
3. The CPU saves either the Program Counter and the Condition Code
Register (input is FIRQ) or all the user registers (any other input or
instruction) in the Hardware Stack. Figure 15-1 shows the order in which
15-4 6809 Assembly Language Programming

Before After

5555 - 3 cc f-.--Hardware
5555 - 2 PCH Stack
Pointer
S5SS - 1 PCL
!- Hardware ssss
Stack
Pointer

Stack Stack

ss5s = original contents of Hardware Stack Pointer


cc = Original contents of Condition Code Register (With bit 7. the Entire flag. cleared)
PCH = Original contents of Program Counter high-order byte
PCL = Original contents of Program Counter low-order byte

Figure 15-1. Saving the Limited Processor State in the Hardware Stack (Response to FIRQ)

the limited state is saved after the recognition of FIRQ and Figure 15-2 shows
the order in which the entire state is saved after other inputs or instructions.
TheE (Entire) flag distinguishes the two alternatives (E is 1 if the entire state
has been saved and 0 if only the limited subset has been saved).
4. The CPU fetches an address from a specified pair of memory locations and
loads that address into the Program Counter. Table 15-1 lists the locations
assigned to the various inputs and to the SWI instructions.

Table 15-1. Memory Map for Interrupt Vectors

Memory Map for


Vector Location Interrupt Vector
Description
MSBs LSBs

FFFE FFFF RESET


FFFC FFFD NMI
FFFA FFFB SWI
FFFS FFF9 IRQ
FFF6 FFF7 FIRQ
FFF4 FFF5 SWI2
FFF2 FFF3 SWI3
FFFO FFF1 Reserved

The addresses are stored in the usual 6809 manner with


the most significant bits at the lower address.

SPECIAL FEATURES

Note the following features of the 6809 interrupt system:

1. The M09 automatically saves the entire or limited state of the processor in
Interrupts 15-5

Before After

ssss 12 cc
-4 - Hardware
-
t-� _ _
ssss - 11 aa Stack
Pointer
ssss - 10 bb

ssss- 9 dd

ssss- 8 XH

ssss- 7 XL

ssss - 6 YH

ssss- 5 YL

ssss - 4 UH

ssss - 3 UL

ssss- 2 PCH

ssss - 1 PCL

-Hardware
Stack
Pointer

Stack Stack

ssss = Original contents of Hardware Stack pointer


cc = Contents of Condition Code Register with bit 7, the Entire flag, set to 1.
aa = Contents of Accumulator A
bb = contents of Accumulator B
dd = Contents of Direct Page Register
XH = Index Register X high-order byte
XL = Index Register X low-order byte
YH = Index Register Y high-order byte
YL = Index Register Y low-order byte
UH = User Stack Pointer U high-order byte
UL = User Stack Pointer U low-order byte
PCH = Original contents of Program Counter high-order byte
PCL = Original contents of Program Counter low-order byte

Figure 15-2. Saving the Entire Processor State in the Hardware Stack

the Hardware Stack. The Program Counter is always saved so the inter­
rupted program can be resumed. The Condition Code Register (including the
Interrupt Mask and Fast Interrupt Mask flags) is always saved as well.
2. The Fast Interrupt Request not only provides a second maskable interrupt
input, but it also provides a faster response since only the Program Counter
and the Condition Code Register are saved. Saving only the limited state
reduces the response time by 9 clock cycles, since 1 clock cycle is needed to
transfer each byte to the Stack.
3. The 6809 provides external hardware signals (using the BUS AV AILA­
BLE and BUS STATE lines) to indicate that it has accepted an interrupt.
These lines can be used to activate external hardware.
4. The 6809 has no special internal provisions for determining the source of
an interrupt when there are several sources tied to the same input.
15-6 6809 Assembly Language Programming

lnterrupt·Related Instructions

The following special instructions can be used to manipulate the 6809 interrupt
system:

1. ANDCC =#=%11101111 (or CLI) clears bit 4 of the Condition CodeRegister


and thus enables the regular interrupt. ANDCC =#= %10111111 (or CLF)
similarly clears bit 6 of the Condition CodeRegister and thus enables the fast
interrupt. Of course, ANDCC =tt:%10101111 (or CLIF) enables both inter­
rupts at once.
2. ORCC #%00010000 (or SEI) sets bit 4 of the Condition CodeRegister and
thus disables the regular interrupt. ORCC =#=%01000000 (or SEF) similarly
sets bit 6 of the Condition CodeRegister and thus disables the fast interrupt.
ORCC # %01010000 (or SElF) disables both interrupts at once.

3. SWI (Software Interrupt) sets the Entire flag, saves all the user registers in
the Hardware Stack, and disables the regular and fast interrupts. It then places
the contents of addresses FFFA and FFFB in the Program Counter. SWI2
(Software Interrupt 2) and SWI3 (Software Interrupt 3) are similar, except
that they do not affect the interrupt masks and they use different vector
addresses (FFF4 and FFF5 for SWI2, FFF2 and FFF3 for SWI3).
4. RTI (Return from Interrupt) restores the registers from the Hardware Stack
at the end of an interrupt service routine. If the recovered E flag is cleared,
R TI restores only the Condition CodeRegister and the Program Counter.
ThusRTI is similar toRTS, butRTI restores other registers as well as the
Program Counter.

5. CWAI (Clear and Wait for Interrupt) logically ANDs a byte of immediate
data with the Condition CodeRegister (usually enabling the regular or fast
interrupts), saves all the user registers in the Hardware Stack, and waits for an
interrupt to occur. The response to the interrupt is rapid (9 clock cycles),
since the registers have already been saved. Note that, if a CW AI instruction
has been executed and a fast interrupt occurs, the CPU will enter the fast
interrupt service routine with all its registers saved (and with the E flag in the
Stack set).
6. SYNC (Synchronize to External Event) causes the processor to stop execut­
ing instructions. The CPU simply waits for an interrupt. If the interrupt is
masked or lasts less than 3 clock cycles, the CPU continues to the next
instruction without stacking registers or performing an interrupt service
routine. Otherwise, the CPU performs its normal interrupt response. SYNC
allows an extremely fast response to a single (presumably high-priority) inter­
rupt, since no stacking or vectoring is performed. Obviously, the use of SYNC
is a one-time only approach, since the CPU does not save its previous state or
identify the source. Figure 15-3 illustrates the use of the SYNC instruction in
this manner.

The SWI (Software Interrupt) instructions produce almost exactly the same
response as an interrupt signal (hence the name). The only difference is the locations
from which the CPU obtains the new value of the Program Counter. SWI instructions
are useful for debugging (see Chapter 19) and for returning control to a monitor or
operating system while simultaneously saving the current state in the stack. SWI
Interrupts 15-7

instructions are also referred to as traps, since they can be used to trap the microcom­
puter to special routines in the event of hardware errors or other unusual events.3
SWI is commonly used in packaged monitors and operating systems to transfer control
from user to system; SWI2 is supposed to be available to the end user, and hence should
not be used in packaged systems software.

Fast Interrupt

The fast interrupt is a high-priority maskable interrupt. In response to it, the


CPU clears the E flag and saves the Program Counter and Condition Code Register in
the Hardware Stack (assuming that it is not executing a CW AI instruction). It then
obtains the new value for the Program Counter from memory addresses FFF6 and
FFF7. The differences between regular and fast interrupts are thus minimal from the
programmer's point of view and we will not refer to fast interrupts again.

Nonmaskable Interrupt

The nonmaskable interrupt is an edge-sensitive input. The processor therefore


only reacts to the edge of a pulse on this line, and the pulse will not interrupt its own ser-

SYNC Wait for data byte available

'
Interrupt Device generates an interrupt when
Occurs a byte of data is available.
I

Load byte into


Accumulator and
store in buffer area.

Decrement Byte
Counter

Has all the data


been transferred?

Figure 15-3. Using the SYNC Instruction in Interrupt-Driven Input/Output


15-8 6809 Assembly Language Programming

vice routine. Nonmaskable interrupts are useful for applications that must respond to
loss of power (usually by saving data in a low-power memory or switching to a backup
battery) .4 Typical applications are communications equipment that must retain codes
and partially received messages, and test equipment that must keep track of partially
completed tests. We will not discuss the nonmaskable interrupt any further. Henceforth,
we will assume that- all interrupt inputs are tied to IRQ.

6820 PIA INTERRUPTS

Most 6809 interrupt systems involve 6820 PIAs. Each port of the 6820 PIA has
the following features for use with interrupts:

1. An active-low interrupt output.

2. Interrupt enable bits (bit 0 of the Control Register for control line 1, bit 3 for
control line 2 if it is an input).

3. Interrupt status bits (bit 7 of the Control Register for control line 1, bit 6 for
control line 2).

Bits 1 (control line l ) and 4 (control line 2) determine whether a rising edge (low­
to-high transition) or a falling edge (high-to-low transition) on the control line causes an
interrupt.
Note the following:

1. The PIA has interrupt enable bits, whereas the 6809 microprocessor has
interrupt mask flags. That is, the PIA bits must be 'I' to allow interrupts,
while the microprocessor flags must be '0' to have the same effect.
2. RESET clears the PIA control register and thus disables all interrupts.
Even if the PIA interrupt outputs are tied to NMI on the 6809 CPU, no inter­
rupts will occur until the PIA enable bits have been set.

3. The CPU can check bits 6 and 7 of the Control Register to see if a PIA has a
pending interrupt. Once a status bit has been set, it remains set until the CPU
reads the corresponding PIA Data register.

4. The PIA will remember an interrupt that occurs while PIA interrupts are
disabled and will provide an output as soon as the corresponding enable bit is
set.

6850 ACIA INTERRUPTS

The 6850 ACIA can also produce interrupts. You should note the following
features of the 6850 ACIA in interrupt-based systems:

1. The transmitter interrupt (signifying that the ACIA is ready for data) is
enabled only if Control Register bit 6 = 0 and Control Register bit 5 = 1.
2. The receiver interrupt (signifying that the ACTA has received new data) is
enabled only if Control Register bit 7 = 1.
Interrupts 15-9

3. Master reset does not affect the interrupt enable bits.


4. The occurrence of either interrupt sets bit 7 of the Status Register. Either
reading data from the ACIA or writing data into the ACIA clears bit 7.

6809 POLLING INTERRUPT SYSTEMS

Most 6809 interrupt systems must poll each PIA and ACIA to determine which
one caused an interrupt. The polling method is:

1. Check each PIA by examining bits 6 and 7 of the Control Register:

LOI\ PTACRI\ CS BIT 7 SET?


FF� f INTJ<PJ YES, INTERRUPT l HAS OCCURRED
'' S Ll\ [S BIT !i SET?
f>MI l'ITRP/. YES, INTERRUPT 2 HAS OCCURRED

2. Check each 6850 ACIA by examining bit 7 of the Status Register:

L Dl\ 1\CT Nif1 IS BIT 7 SET?


l:lPL '\JXTCH!< NO, NO INTERRUPTS ON THIS ACIA
LS Rl\ YES, IS BIT 0 SET?
BCS HCVINT YES, RECEIVER INTERRUPT HAS OCCURRED
RHI\ TX l '�T NO, IT MUST HAVE BEEN TRANSMITTER
INTERRUPT

Bit 7 of the ACIA Status Register indicates that either a receiver or a transmit­
ter interrupt has occurred. Bit 0 will be set if a receiver interrupt has occurred
and bit 1 will be set if a transmitter interrupt has occurred. Of course, the
interrupt must be one or the other, so our program assumes a transmitter
interrupt if it does not find a receiver interrupt.

The important features of a 6809 polling interrupt system are:

1. The order in which status bits are examined determines the priority of the
interrupts. Obviously, the CPU will proceed no further if it finds an active
interrupt; thus it ignores activity from sources later in the sequence. Priorities
are easy to establish (merely by selecting the order of examination) but
difficult to change or vary.

2. The service routine must clear a PIA interrupt by reading the correspond­
ing Data Register, even if the port is being used for output or no data
transfer is necessary. Otherwise, the interrupt will remain active. The pro­
grammer can use the TST (test zero or minus) instruction to read the PIA
Data Register without changing its contents or the contents of a User
Register.

DISADVANTAGES OF POLLING INTERRUPTS

Polling routines are adequate if the number of sources is small and the frequency
of interrupts is low. If there are many sources or interrupts are frequent, polling
routines are slow and awkward for the following reasons.
15-10 6809 Assembly Language Programming

1. The average number of polling operations increases linearly with the num­
ber of inputs. On the average, of course, a polling routine will have to
examine half of the inputs before finding the active one. You can reduce the
average number of polling operations somewhat by checking the most fre­
quent inputs first.
2. PIA and ACIA addresses are rarely consecutive or evenly spaced; therefore,
separate instructions are necessary to examine each input. Polling routines
are therefore difficult to expand. You can use tables of 1/0 addresses,
accessed via one of the indexed addressing modes.
3. Interrupts that are polled early may shut out those that are polled later
unless the order of polling is varied. However, varying the order of polling is
difficult since the addresses are not consecutive.

6809 VECTORED INTERRUPT SYSTEMS

The problem of polling in 6809-based systems is typically solved by special


methods, unique to a particular application or microcomputer. The 6828 Priority Inter­
rupt Controllers provides an eight-level vectored interrupt system based on the regu­
lar interrupt input. This device simply recognizes the addresses FFF8 and FFF9 (see
Table 15-1) when they appear on the address bus and replaces them with one of the
eight vectors. Special hardware can also utilize the interrupt acknowledge signal pro­
vided by the 6809 microprocessor. We will not discuss 6809 vectored interrupt systems
any further.

COMMUNICATIONS BETWEEN MAIN PROGRAM


AND SERVICE ROUTINES

A major problem in writing programs for interrupt-based systems is providing


communications between the main program and the service routines. The criteria for
communications methods are:

1. They should not interfere with the normal execution of the main program.
2. They should not depend on how the main program operates. For example,
they should not require the main program to be inactive (i.e., executing
CWAI or SYNC) or assume that certain registers are always available.
3. They should be well-defined and capable of handling varied amounts of data.
4. They should not require instantaneous action by the main program. The more
patient the system is, the easier it will be to develop and maintain.
The idea is to make the service routines and the main program transparent to each
other. This approach allows the programmer to change one without affecting the other.
It also helps limit errors to one or the other, rather than to the connection between
them.
lntern:pts 15-11

SOFTWARE HANDSHAKE

A simple approach to communications is a software "handshake," much like


the hardware handshake used in asynchronous input/output as described in Chapter
12. The provider of data (the interrupt service routine for input or the main program
for output) sets a flag to indicate that new data is available. The receiver or acceptor
of data can then examine that flag (sometimes called a semaphore) and can clear it
after transferring (or accepting) the data. The receiver may itself set another flag (an
acknowledgment) to indicate that the most recent datas been processed and more can
be sent.
Where do we place the flags and the data? A simple approach is to use a single
memory location for each flag and for the data; the location can be a specific memory
address or an address in the Hardware Stack that has been set aside for that purpose.
The main program and the service routines then communicate through those locations,
much as the processor communicates with 1/0 devices through I/0 ports.

BUFFERED INTERRUPTS

The approach outlined above assumes that we handle 110 on a byte-by-byte basis.
The processor must provide each output byte separately and must handle each input
byte separately. Clearly, all operations must proceed at a rate that is guaranteed to be
fast enough to avoid losing data. As with normal 1/0, we can relax the time con­
straints by using buffers. In this approach, the service routine transfers data to or
from a buffer and updates the buffer pointer for the next operation. The only time the
main program has to be concerned is when an input buffer is full or an output buffer
is empty. The service routines act as I/0 devices that have their own local memory in
which data can be stored temporarily. This approach is referred to as buffered interrupts.

Double Buffering

In fact, we can extend this approach. We can provide one buffer for the service
routine and a separate buffer for the main program. Now even the filling or emptying
of a buffer creates no problem as long as the other buffer is immediately available. In
fact, the identities of the buffers can simply be interchanged when the service routine
has filled or emptied its buffer. This approach is known as double buffering; it allows
interrupt-driven input/output to proceed in almost total independence of the main pro­
gram.

ENABLING AND DISABLING INTERRUPTS

A further problem in writing programs for interrupt-based systems is deciding


when to enable or disable interrupts.

WHEN TO DISABLE INTERRUPTS

In general, you disable interrupts in the situations itemized below.


15-12 6809 Assembly Language Programming

l. During the initialization of the interrupt system itself. This may involve
loading initial values into pointers, flags, and counters or determining an
initial order for polling or other operations. Remember that RESET automat­
ically disables the CPU and PIA interrupts, so the system startup routine will
have to explicitly enable them.
2. During the servicing of an interrupt. If interrupts are not disabled at least
until the current one is cleared, the computer will enter an endless loop with
the interrupt endlessly interrupting its own service routine. Remember that
the 6809 microprocessor automatically disables the regular interrupt as part of
its normal response. Note also that an NMI interrupt will not interfere with its
own service routine, since the input is edge-sensitive, rather than level-sensi­
tive.

3. During operations that occur in real time (such as delay loops or high-speed
synchronous 1/0) or that could produce erroneous results if interrupted. A
typical example of the latter situation is the updating of multi-byte data that
the interrupt service routine must use, such as the calendar time or
geographical position. A partial update could produce a highly erroneous
value, such as a clock time that is off by an hour or a day because the interrupt
occurred before that part of the time was changed.

WHEN TO ENABLE INTERRUPTS

On the other hand, you want to enable interrupts as soon as possible whenever
they might occur. Otherwise, the system could miss an interrupt and either lose some
input or fail to produce the proper output data.

INITIALIZING THE INTERRUPT SYSTEM

The normal order in which you initialize a 6809-based interrupt system is as


follows (starting from RESET):

1. Initialize all system parameters.

2. Enable the interrupts from each PIA and ACIA.

3. Enable the CPU interrupts by clearing the appropriate interrupt mask flags.

PIA INTERRUPTS

If you must disable a particular interrupt, you can disable it independently of


other interrupts by clearing the interrupt enable flag for a specific port of a particular
PIA. You can do this without affecting other control register bits by using logical opera­
tions.

l. Disabling a PIA interrupt.


Control line 1
LDA Pl/I.CR
ANDA :!5lllllllrl DISABLE CONTROL LINE 1 INTERRUP'!
STA PIACP

or (if you know that the interrupt is currently enabled)


\

DEC DISABLE CONTROL LINE l INTERRUPT


Interrupts 15-13

Control line 2
LDl\ r> !.C'I(
AND.A. H 1 1 1 I C• l!! DISABLE CONTROL LINE 2 INTERRUPT
ST� P !\CH

2. Enabling a PIA interrupt.


Control line 1
Ll.l/\ r lAC�<
Oil,\ 'l·','l[li;''!J; lJ ENABLE CONTROL LINE 1 INTF.RRUPT
::;T!'. '1 J J\.C t�

or (if you know that the interrupt is currently disabled)


INC PIACR ENABLE CONTROL LINE 1 INTERkUPT

Control line 2
LOA PIACR
ORA l%00001000 ENABLE CONTROL LINE 2 INTERRUPT
STA PIACR

The INC and DEC instructions take advantage of the fact that bit 0 is the interrupt
enable for control line I. However, these instructions can affect the entire PIA control
register if they are inadvertently executed when the interrupt enable is already in the
desired state. Consider, for example, what would happen if the CPU were to execute
DEC PIACR when bit 0 of the control register was already 0. The INC and DEC instruc­
tions arc thus less general, as well as more difficult for the casual reader to understand,
than the logical instructions.

SAVING AND RESTORING INTERRUPT STATUS

A related problem6 is restoring the original state of the interrupt system after
performing operations that require interrupts to be disabled. If, for example, an 1/0 or
other subroutine must be executed with interrupts disabled, the subroutine must
restore the original state of the interrupt system before returning control to the main
program. Clearly, we do not want the subroutine to enable interrupts if they were dis­
abled in the calling program or not re-enable interrupts if they were enabled in the call­
ing program.

The solution is simple: save and restore the condition code register that con­
tains the interrupt mask bits. We can save that register before disabling interrupts with
the instruction PSHS CC; we can restore that register before returning control to the
main program or performing operations that could be interrupted with the instruction
PULS CC.

CHANGING THE VALUES IN THE STACK


The 6809 microprocessor automatically saves all or some of its registers in
response to an interrupt; the RTI instruction at the end of the service routine restores
those registers. Most service routines leave the registers in the stack alone to pro­
mote generality and simplicity. However, programmers occasionally find it necessary
to alter some of the registers. Typical reasons are to force a return to a different
address? or to disable the entire interrupt system. In these cases, the programmer must
know how to find the various registers in the Hardware Stack.
15-14 6809 Assembly Language Programming

Table 15-2. Indexed Offsets for Entire Processor State

Indexed Offset
Register
(Hexadecimal)

Condition Code 00
Accumulator A 01
Accumulator B 02
Direct Page Register 03
High-Order Byte of Index Register X 04
Low-Order Byte of Index Register X 05
High-Order Byte of Index Register Y 06
Low-Order Byte of Index Register Y 07
High-Order Byte of User Stack Pointer U 08
Low-Order Byte of User Stack Pointer U 09
High-Order Byte of Program Counter OA
Low-Order Byte of Program Counter OB

Table 15-3. Indexed Offsets for Limited Processor State

Indexed Offset
Register (Hexadecimal)

Condition Code 00
High-Order Byte of Program Counter 01
Low-Order Byte of Program Counter 02

Table 15-2 contains the indexed offsets required to access the registers in the case
in which the processor has saved the entire state. Table 15-3 contains the indexed
offsets required in the case (in response to FIRQ) in which the processor has saved only
the program counter and the condition code register. Typical routines using the offsets
in Table 15-2 are:

1. Changing the return address to EEXIT (an error exit routine):

LOX HEX IT RETURN ADDRESS � ERROR EXIT


STX SOA,S

2. Decrementing the return address by 1 (used in the event that an interrupt or


SWI instruction has been used to replace an actual program instruction for
debugging or testing purposes):

TST SOB,S ARE LSB'S OF RETURN ADDRESS ZERO?


BNE DECLSB YES, REDUCE MSB'S BY 1
DEC SOA,S
DECLSB DEC SOI:l,S REDUCE LSB'S OF RETURN ADDRESS BY 1

Only if the LSB's of the return address are zero is it necessary to decrement
the MSB's in order to produce a correct 16-bit decrement.
3. Disabling the regular interrupt by setting the regular interrupt mask bit (bit
4 of the Condition Code Register):

LOA ,S
ORA #%00010000 DISABLE REGULAR INTERRUPT
STA , S
Interrupts 15-1 5

4. Disabling the fast interrupt by setting the fast interrupt mask bit (bit 6 of the
Condition Code Register):

LDA ,S
ORA #%01000000 DISABLE FAST INTERRUPT
STA ,S

Obviously, the programmer must be extremely careful when altering stack values,
since these changes could have unforeseen side effects in the main program.

INTERRUPT OVERHEAD

Responding to an interrupt always involves some overhead cycles, since the CPU
may have to fetch a new program counter value from memory and save registers in the
Hardware Stack. Of course, the restoring of registers from the Hardware Stack, if
necessary, also uses processor time. You can determine the amount of overhead
involved in servicing interrupts from the time requirements in Table 15-4.

Table 15·4. Time Kcquirements for Interrupt-Related Operations

Number of
Operation
Clock Cycles

Normal response to IRQ or NMI 21


Normal response to FIRU 12
Response to any interrupt while executing CWAI 9
Escape from SYNC state if interrupts disabled 1
Execution of CWAI 20
Execution of RTI with E flag set (Entire state) 15
Execution of RTI with E flag cleared (Limited state) 6
Execution of SWI 19
Execution of SWI2 or SWI3 20
Execution of SYNC 2

PROGRAM EXAMPLES

15-1. A STARTUP INTERRUPT

Purpose: The computer waits for a PIA interrupt to occur before starting actual opera­
tions.
Often a system remains inactive until the operator actually starts it or until a
DATA READY signal is received. On RESET, such a system must initialize the Stack
Pointer, enable the startup interrupt, and execute a halt (CWAI) or an endless loop or
jump-to-self instruction. Remember that RESET disables the processor interrupt (by
setting I and F both to I) as well as all the PIA interrupts (by clearing all the PIA inter­
rupt enable bits). In the flowchart, the decision as to whether startup is active is made in
hardware (by the CPU examining the interrupt input internally) rather than in software.
15-16 6809 Assembly Language Programming

Program 1 5-1 :

Main Program:
8001 PIACA EQU $8001
8000 PI ADA EQU $8000
0100 INTRP EQU $0100

0000 ORG $0000


0000 10CE 0100 LDS #$100 START STACK AT MEMORY LOCATION

OOFF
0004 86 05 LDA t%00000101 ENABLE INTERRUPT FROM
0006 B7 8001 STA PIACA STARTUP PIA
0009 3C EF CWAI ll%11101111 ENABLE REGULAR INTERRUPT
*
AND WAIT
OOOB 3F SWI DUMMY CONTINUATION

Interrupt Service Routine:

0100 ORG INTRP


0100 B6 8000 LDA PI ADA CLEAR STARTUP INTERRUPT
0103 3B RTI RETURN AND PROCEED

Flowchart:

Initialize Stack
Pointer
Enable startup
interrupt on PIA
Enable CPU interrupt

The exact location (INTRP) of the interrupt service routine varies with the
microcomputer. If your microcomputer has no monitor, you can simply place whatever
address you want in memory locations FFF8 and FFF9 (or whatever locations respond
to those addresses). You must then start the interrupt service routine at the address you
chose. Of course, you should locate the routine so it does not interfere with fixed
addresses or with other programs.

Interrupt Handling by Monitors

If your microcomputer has a monitor, the monitor will reserve addresses FFFS
and FFF9. Those addresses will either contain the starting address at which you must
place your interrupt service routine, or will contain the starting address of a routine
that allows you to choose the starting address of the interrupt service routine. A typi­
cal monitor routine would be:

MONINT ,JMP [USRINT] JUMP TO USER-SUPPLIED SERVICE ADDRESS


Interrupts 15-17

You must then place the starting address of your service routine in memory loca­
tions USRINT and USRINT + l. Remember that MONINT is an address in the moni­
tor program and its value is in addresses FFF8 and FFF9.
You can include the loading of memory locations USRINT and USRINT + 1 in
your mam program:

LDX #INTRP GET STARTING •"lilURC:S�' OP SEI<VICI' ROUTIN£


STX USRINT STORE IT AT A0rR�SS MONfTOR USES

These instructions must precede the enabling of the interrupts.

Program Operation

The main program's only action is to enable the interrupt from the startup PIA.
The program enables that interrupt by setting bit 0 of the PIA Control Register before
enabling the CPU interrupt. Note that we must set the PIA interrupt enable and clear
the CPU interrupt mask bit.
The CWAI instruction logically ANDs the Condition Code Register with the
following byte of immediate data before halting instruction execution. Logically AND­
ing the Condition Code Register with 111011112 clears bit 4 of the Condition Code
Register, thus enabling the regular interrupt. Similarly, logically ANDing with
101111112 would clear bit 6 of the Condition Code Register, thus enabling the fast inter­
rupt. Logically ANDing with 101011112 would enable both maskable interrupts.
CW AI causes the 6809 CPU to save all its registers in the Hardware Stack and wait
for an interrupt to occur.
In response to an interrupt (IRQ), the CPU disables IRQ and transfers control to
the address in memory locations FFF8 and FFF9. (Remember that all the registers have
already been saved in the Hardware Stack.)
The service routine clears the startup interrupt by reading the appropriate PIA
Data Register. This operation is necessary, even though no data transfer is required.
Otherwise, the startup interrupt would remain active and would interrupt again as soon
as the CPU interrupt was reenabled.
RTI restores all the user registers from the Hardware Stack, thus reenabling the
CPU interrupt (since the old flag is restored) and transferring control to the instruction
immediately following CWAI. Note that transferring control to the service routine does
not change the contents of the user registers, but RTI does. The LOA instruction in the
service routine affects Accumulator A and the Condition Code Register, but those
effects are lost when RTI is executed.

15-2. A KEYBOARD INTERRUPT

Purpose: The main program clears a flag in memory location 0040 and waits for a
keyboard interrupt. The interrupt service routine sets the flag in memory
location 0040 to 1 and places the data from the keyboard in memory location
0041.

Sam ple Problem:

Keyboard data 43

Result: (0040) 01 Flag indicating new keyboard data


(0041) 43 Keyboard data
15-18 6809 Assembly Language Programming

Program 15-2a:

Main Program:
8001 PIACA EQU $8001
8000 PIADDA EQU $8000
8000 PIADA EQU $8000
0100 INTRP EQU $0100
*

0000 ORG $0000


0000 10CE 0100 LDS .$100 START STACK AT MEMORY LOCATION
*
OOFF
0004 OF 40 CLR $4 0 CLEAR DATA READY FLAG
0006 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTER
0009 7F 8000 CLR PIADDA MAKE ALL DATA LINES INPUTS
oooc 86 05 LOA 1%00000101 ENABLE KEYBOARD INTERRUPT
OOOE B7 8001 STA PIACA ON PIA
0011 1C EF ANDCC t%11101111 ENABLE CPU INTERRUPT
0013 OD 40 WTRDY TST $40 IS THERE DATA FROM THE KEYBOARD?
0015 27 FC BEQ WTRDY NO, WAIT
001 7 3F SWI YES, PROCEED

Interrupt Service Routine:

0100 ORG INTRP


0100 oc 40 INC $4 0 SET DATA READY FLAG
0102 86 8000 LDA PI ADA FETCH DATA FROM KEYBOARD
0105 97 41 STA $41 SAVF. DATA IN MEMORY
0107 38 RTI

Flowchart:

Main Program:

Initialize Stack
Pointer
Data Ready Flag = 0
Enable keyboard
interrupt on PIA
Enable CPU interrupt

Interrupt Service Routine:

Data Ready Flag


=1
(0041)
= Keyboard Data
Interrupts 15-19

You must initialize the PIA completely before enabling interrupts. This includes
establishing the directions of ports and control lines and determining the transitions to
be recognized on input strobes.
The main program clears the Data Ready Flag (memory location 0040) and then
simply waits for the interrupt service routine to set it. The main program and the service
routine communicate through two fixed memory addresses:
0040 is a flag that indicates whether new data has been received from the
keyboard.
0041 is a single-location data buffer used to hold the value received from the
keyboard.
Note the similarity between the Data Ready Flag in memory and the status bit in
the control register of the keyboard PIA. The program does not have to test bit 7 of the
PIA control register because there is a direct hardware (interrupt) connection between
that bit and the CPU. Of course, we have also assumed that the keyboard is the only
source of interrupts.
The RTI instruction at the end of the service routine transfers control back to the
main program. If you want to transfer control somewhere else (perhaps an error
routine), you can change the Program Counter in the Hardware Stack using the
methods outlined earlier. If the entire state of the processor has been saved, the return
address will be at offsets OA16 and 0816 from the Hardware Stack Pointer.
We do not use the registers to pass parameters and results. In the first place,
the 6809 automatically restores the old register values when it executes RTI. Sec­
ondly, if we were to change the register values in the stack, we could interfere with
the execution of the main program. In most applications, the main program is using
the registers and random changes will cause havoc. At the very least, changing the
registers lacks generality, since modifications to the main program surely could
result in the use of registers that are currently available.
The service routine does not have to explicitly re-enable the interrupts. The
reason is that RTI automatically restores the old Condition Code Register with the
Interrupt Mask bit in its original (cleared) state. In fact, you will have to change the
Interrupt Mask bit in the Stack (bit 4 of the top location) if you do not want the inter­
rupts to be re-enabled.
You can save and restore other data (such as the contents of a memory location)
by using the Hardware Stack. This method can be expanded indefinitely (as long as
there is RAM available for the Stack), since nested service routines will not destroy the
data saved by earlier routines.

Filling a Buffer via Interrupts

An alternative approach would be for the interrupt service routine to set


memory location 0040 only after receiving an entire line of text (such as a string of
characters ending with a carriage return). Here we use memory location 0040 as an end­
of-line flag and memory locations 0041 and 0042 as a buffer pointer. We will assume
that the buffer starts in memory location 0050.
15-20 6809 /\sscmhly Language Programming

Program 15-2b:

Main Program:
8001 PIACA EQU $8001
8000 PIADDA EQU $8000
8000 PIADA EQU $8000
0100 INTRP EQU $0100
OOOD CR EQU SOD
*

0000 ORG $0000


0000 10CE 0100 LOS #$100 START STACK AT MEMORY L OCATION
*
OOFF
0004 OF 40 CLR $40 CLEAR END OF LINE FLAG
0006 BE 0050 LOX #$50 INITIALIZE BUFFER POINTER TO
0009 9F 41 STX $41 START OF BUFFER
OOOB 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTER
OOOE 7F 8000 CLR PIADDA MAKE ALL DATA LINES INPUTS
0011 86 05 LDA Jl%00000101 ENABLE KEYBOARD INTERRUPT
0013 B7 8001 STA PIACA FROM PIA
0016 1C EF ANDCC #%11101111 ENABLE CPU INTERRUPT
0018 00 40 WTEOL TST $40 HAS A LINE BEEN RECEIVED FROM
*
THE KEYBOARD?
001A 27 FC BEQ WTEOL NO, WAIT
001C 3F SWI

Interrupt Service Routine:

0100 ORG INTRP


0100 9E 41 LOX $41 GET BUFFER POINTER
0102 B6 8000 LOA PIADA FETCH DATA FROM THE KEYBOARD
0105 A7 80 STA ,X+ SAVE DATA IN BUFFER AND
* INCREMENT POINTER
0107 9F 41 STX $41 STORE ADJUSTED BUFFER POINTER
0109 81 OD CMPA *CR IS DATA A CARRIAGE RETURN?
010B 26 02 BNE DONE
0100 oc 40 INC $40 YES, SET END OF LINE FLAG
010F 3B DONE RTI

This program fills a buffer starting at memory location 0050 until it receives a car­
riage return character (CR). Memory locations 0041 and 0042 hold the current buffer
pointer. The interrupt service routine increments that pointer (with autoincrementing)
after each use.
In a real application, the CPU could perform other tasks between interrupts. It
could, for example, edit, move, or transmit a line from one buffer while the interrupt
was filling another buffer. This is the double buffering approach. The main program only
has to ensure that no buffers ever overflow.
An alternative approach would be for memory location 0040 to contain a
counter rather than a flag. The contents of that location would then indicate to the
main program how many bytes of data had been received. The main program could then
deal with the buffer whenever a certain number of new data bytes were in it. The service
routine would simply increment the counter as well as the buffer pointer as part of each
input operation.

15-3. A PRINTER INTERRUPT

Purpose: The main program clears a flag in memory location 0040 and waits for a printer
interrupt. This interrupt service routine sets the flag in memory location 0040
to 1 and sends the contents of memory location 0041 to the printer.
Interrupts 15-21

Sample Problem:

(004 1) 51

Result: (0040) 01 Flag indicating last data item has been sent

Printer receives a 51 16 (ASCII Q) when it is ready.

Program 15-3a:

Main Program:

8003 PIACB EQU $8003


8002 PIADDB EQU $8002
8002 PIADB EQU $8002
0100 INTRP EQU $0100

0000 ORG $0000


0000 10CE 0100 LDS J$100 START STACK AT MEMORY LOCATION
• OOFF
0004 OF 40 CLR $40 CLEAR DATA ACCEPTED FLAG
0006 7F 8003 CLR PIACB ADDRESS DATA DIRECTION REGISTER
0009 86 FF LOA J$FF MAKE ALL DATA LINES OUTPUTS
0008 87 8002 STA PIADD8
OOOE 86 OS LOA #%00000101 ENABLE PRINTER INTERRUPT
0010 8 7 8003 STA PIACB ON PIA
0013 1C EF AN DCC #%11101111 ENABLE CPU INTERRUPT
0015 OD 40 WTACK TST $40 HAS THE PRINTER ACCEPTED THE
• DATA?
0017 27 FC BEQ WTACK NO, WAIT
0019 3F SWI YES, PROCEED

Interrupt Service Routine:

0100 ORG INTRP


0100 oc 40 INC $40 SET DATA ACCEPTED FLAG
0102 96 41 LOA $41 GET DATA FOR PRINTER
0104 87 800/ STA PIADB SEND DATA TO PRINTER
0107 8 6 8002 LDA PIADB CLEAR PRINTER INTERRUPT
010A 3B RTI

Flowchart:

Main Program:

Initialize Hardware
Stack Pointer
Data Accepted Flag
=0
Enable printer
interrupt on PIA
Data = (0041)
Enable CPU interrupt
15-22 6809 Assembly Language Programming

Interrupt Service Routine:

Data Accepted Flag


= 1
Send Data to printer

The only differences from the keyboard interrupt routines are the meaning of the
flag, the direction of the data transfer, and the need for the dummy instruction LOA
PIAOB to clear bit 7 of the PIA Control Register. Remember that an input operation au­
tomatically clears that bit, but an output operation does not.
Here the flag in memory location 0040 indicates that the CPU has data available
that has not yet been sent to the printer. When the interrupt service routine sets the flag,
the main program knows the data has been sent. The flag acts as an acknowledgement
from the printer or a Data Accepted indicator.

Remember that you may find it necessary to place a dummy read at the start of the
main program to clear stray interrupts. LOA PIA DB or TST PIA DB will do the job, as
long as you place it after the instruction that addresses the data register but before the
instruction that enables CPU interrupts.

Emptying a Buffer with Interrupts

As in the keyboard example, we could have the interrupt service routine set the
Data Accepted flag after it sends the printer an entire line of data ending with a car­
riage return. Here again we use memory location 0040 as an end-of-line flag and
memory locations 0041 and 0042 as a buffer pointer. We will assume that the buffer
starts in memory location 0050.

Program 15-3b:

Main Program:

8003 PIACB EQU $8003


8002 PIADDB EQU $8002
8002 PIA DB EQU $8002
0100 INTRP EQU $0100
OOOD CR EQU $00
*

0000 ORG $0000


0000 10CE 0100 LDS J$100 START STACK AT MEMORY L OCATION
*
OOFF
0004 OF 40 CLR $40 CLEAR END OF LINE FLAG
0006 BE 0050 LDX i$50 INITIALIZE BUFFER POINTER TO
0009 9F 41 STX $41 START OF BUFFER
0008 7F 8003 CLR PIACB ADDRESS DATA DIRECTION REGISTER
OOOE 86 FF LDA J$FF MAKE ALL DATA LINES OUTPUTS
0010 87 8002 STA PIADDB
0013 86 05 LOA U00000101 ENABLE PRINTER INTERRUPT
0015 87 8003 STA PIACB FROM PIA
0018 1C EF ANDCC i%11101111 ENABLE CPU INTERRUPT
001A OD 40 WTEOL TST $40 HAS A LINE BEEN PRINTED?
001C 2 7 FC BEQ WTEOL NO, WAIT
001E 3F SWI
Interrupts 15-23

Interrupt Service Routine:

0100 ORG INTRP


0100 9E 41 LDX $41 GET BUFFER POINTER
0102 A6 80 LDA ,X+ GET DATA FROM BUFFER AND
* INCREMENT POINTER
0104 B7 8002 STA PIADB SEND DATA TO PRINTER
0107 7D 8002 TST PIA DB CLEAR PRINTER INTERRUPT
010A 9F 41 STX $41 STORE ADJUSTED BUFFER POINTER
010C 81 OD CMPA #CR IS DATA A CARRIAGE RETURN?
010E 2 6 02 BNE DONE
0110 oc 40 INC $40 YES, SET END OF LINE FLAG
0112 3B DONE RTI

We could use double buffering to allow 1/0 and processing to occur independently
without ever halting the CPU.

Fixed-Length Buffer

Still another approach uses memory location 0040 as a buffer counter. For
example, the following program waits for 20 characters to be sent to the printer.

Program 15-3c:

Main Program:

8003 PIACB EQU $8003


8002 PIADDB EQU $8002
8002 PIA DB EQU $8002
0100 INTRP EQU $0100
*

0000 ORG $0000


0000 10CE 0100 LDS #$100 START STACK AT MEMORY LOCATION
*
OOFF
0004 OF 40 CLR $40 CLEAR BUFFER COUNTER
0006 BE 0050 LDX 11$50 INITIALIZE B�FFER POINTER TO
0009 9F 41 STX $41 START OF BUFFER
OOOB 7F 8003 CLR PIACB ADDRESS DATA DIRECTION REGISTER
OOOE 86 FF LDA #SFF MAKE ALL DATA LINES OUTPUTS
0010 B7 8002 STA PIADDB
0013 86 05 LDA #%00000101 ENABLE PRINTER INTERRUPT
0015 87 8003 STA PIACB FROM PIA
0018 1C EF ANDCC #%11101111 ENABLE CPU INTERRUPT
001A 8C 14 LDA #20 TARGET COUNT = 20
001C 91 40 WTCNT CMPA $40 HAS TARGET COUNT BEEN REACHED?
001E 26 FC BNE WTCNT NO, WAIT
0020 3F SWI YES, PROCEED

Interrupt Service Routine:

0100 ORG INTRP


0100 9E 41 LDX $41 GET BUFFER POINTER
0102 A6 80 LDA ,X + GET DATA FROM BUFFER AND
*
INCREMENT POINTER
0104 B7 8002 STA PIADB SEND DATA TO PRINTER
0107 7D 8002 TST PIADB CLEAR PRINTER INTERRUPT
OlOA 9F 41 STX $41 STORE ADJUSTED BUFFER POINTER
010C oc 40 INC $40 INCREMENT BUFFER COUNTER
010E 3B RTI

15-4. A REAL-TIME CLOCK INTERRUPT

Purpose: The computer waits for an interrupt from a real-time clock.


15-24 6809 Assembly Language Programming

Real-Time Clock

A real-time clock simply provides a regular series of pulses. The interval be­
tween the pulses can be used as a time reference. Real-time clock interrupts can be
counted to give any multiple of the basic time interval. A real-time clock can be pro­
duced by dividing down the CPU clock, by using a timer like the 6840device or the one
included in the 6846 multifunction support device, or by using external sources such as
the AC line frequency.
Note the tradeoffs involved in determining the frequency of the real-time clock.
A high frequency (say 10kHz) allows the creation of a wide range of time intervals of
high accuracy. On the other hand, the overhead involved in counting real-time clock
interrupts may be considerable, and the counts will quickly exceed the capacity of a
single 8-bit register or memory location. The choice of frequency depends on the preci­
sion and timing requirements of your application. The clock may, of course, consist
partly of hardware; a counter may count high frequency pulses and interrupt the pro­
cessor only occasionally. A program will have to read the counter to measure time to
high accuracy.
One problem is synchronizing operations with the real-time clock.Ci early, there
will be some effect on the precision of the timing interval if the CPU starts the measure­
ment randomly during a clock period, rather than exactly at the.beginning. Some ways
to synchronize operations are:

1. Start the CPU and clock together. RESET or a startup interrupt can start the
clock as well as the CPU.
2. Allow the CPU to start and stop the clock under program control.
3. Use a high-frequency clock so that an error of less than one clock period will
be small.
4. Line up the clock (by waiting for an edge or interrupt) before starting the
measurement.

A real-time clock interrupt should have very high priority, since the precision of
the timing intervals will be affected by any delay in servicing the interrupt. The usual
practice is to make the real-time clock the highest priority interrupt except for power
failure. The clock interrupt service routine is generally kept extremely short so that it
does not interfere with other CPU activities.

15-4a. Wait for Real- Time Clock

Program 1 5-4a:

Main Program:
8001 PIACA EQU $8001
8000 PIADA EQU $8000
0100 INTRP EQU $0100
*

0000 ORG $0000


0000 10CE 0100 LDS #$100 START STACK AT MEMORY LOCATION
* OOFF
0004 OF 40 CLR $40 CLEAR CLOCK COUNTER TO START
0006 86 05 LDA t%00000101 ENABLE REAL-TIME CLOCK
0008 B7 8001 STA PIACA INTERRUPT
OOOB 1C EF ANDCC #%11101111 ENABLE CPU INTERRUPT
OOOD OD 40 WTCLK TST $40 HAS CLOCK B EEN INCREMENTED?
OOOF 27 FC BEQ WTCLK NO, WAIT
0011 3F SWI YES, PROCEED
Interrupts 15-25

Interrupt Service Routine:

0100 ORG INTRP


0100 86 8000 LDA PIADA CLEAR CLOCK INTERRUPT
0103 oc 40 INC $40 INCREMENT CLOCK COUNTER
0105 38 RTI

Memory location 0040 contains the clock counter.

If bit 1 of the PIA Control Register is 0, the interrupt will occur on the high-to-low
(falling) edge of the clock. If that bit is 1, the interrupt will occur on the low-to-high (ris­
ing) edge of the clock.
The interrupt service routine must explicitly clear bit 7 of the PIA Control
Register since no data transfer is necessary.
You could still use the PIA data port as long as you did not accidentally clear the
status bit from the real-time clock before it was recognized. This would be no problem if
the port were used for output to a simple peripheral (such as a set of LEOs), since out­
put operations do not affect the status bits anyway.
Clearly, we can easily extend this routine to handle more counts and provide
greater precision by using more memory locations for the clock counter and a different
test in the main program.

15-4b. Wait for 10 Clock Interrupts

Program 15-4b:

Main Program:
8001 PIACA EQU $8001
8000 PI ADA EQU $8000
0100 INTRP EQU $0100
*

0000 ORG $0000


0000 10 CE 0100 LDS 11$100 START STACK AT MEMORY LOCATION
*
DOFF
0004 OF 40 CLR $40 CLEAR CLOCK COUNTER TO START
0006 86 05 LDA U00000101 ENABLE REAL-TIME CLOCK
0008 87 8001 STA PIACA INTERRUPT
OOOB 1C EF ANDCC #%11101111 ENABLE CPU INTERRUPT
OOOD 86 OA LDA uo TARGET COUNT 10 =

OOOF 91 40 WTCNT CMPA $40 HAS CLOCK COUNTER REACHED TARGET


*
COUNT?
0011 26 FC BNE WTCNT NO, WAIT
0013 3F SWI

Interrupt Service Routine:


0100 ORG INTRP
0100 86 8000 LDA PIADA CLEAR CLOCK INTERRUPT
0103 oc 40 INC $4 0 INCREMENT CLOCK COUNTER
0!.05 38 RTI

15-4c. Maintaining Real Time

A more realistic real-time clock interrupt routine could keep track of the
passage of time using several memory locations. For example, the following routine
uses addresses 0040 through 0043 to maintain clock (calendar) time as follows:

0040 - hundredths of seconds


004 1 - seconds
0042 minutes
-

0043 hours
-
15-26 6809 Assembly Language Programming

We assume that a 100Hz input clock provides the regular source of interrupts.

Flowchart:

Clear clock interrupt


Hundredths =

Hundredths+ 1

Hundredths 0 =

Seconds =

Seconds+ 1

Seconds 0 =

Minutes =

Minutes+ 1

Minutes 0 =

Hours =

Hours+ 1
Interrupts 15-27

Program 15-4c:

Interrupt Service Routine:

8000 PIADA EQU $8000


0100 INTRP EQU $0100
*

0100 ORG INTRP


0100 B6 8000 LDA PIADJI. CLEAR CLOCK INTERRUPT
0103 8E 0040 LDX fl$40
0106 6C 84 INC ,X UPDATE HUNDREDTHS OF SECONDS
0108 86 64 LDA uoo IS THERE A CARRY TO SECONDS?
010A A1 84 CMPA ,X
010C 26 16 BNE END INT NO, DONE
010E 6F 84 CLR ,X YES, MAKE HUNDREDTHS ZERO
0110 f;C 01 INC 1,X UPDATE SECONDS
0112 86 3C LDA J60 IS THERE A CARRY T O MINUTES?
0114 A1 01 CMPA 1,X
0116 26 oc BNE ENDINT NO, DONE
0118 6F Ol CLR 1,X YES, MAKE SECONDS ZERO
OllA 6C 02 INC 2,X UPDATE MINUTES
OllC A1 02 CMPA 2,X IS THERE A CARRY TO HOURS?
011E 26 04 BNE ENDINT NO, DONE
0120 6F 02 CLR 2,X YES, MAKE MINUTES ZERO
0122 6C 03 INC 3,X UPDATE HOURS
0124 3B END INT RTI

Now we could produce a delay of 300 ms in the main program with the routine:

LDA S40 0FT CURRENT TIME


ADDA #30 DESIRED TI"'lE IS 30 C OU N TS LATF:R
CMPA ffl 00 "'' OD 100
BCS ltJTCNT
SUBA Ul 00
lii:TCNT CMPll $40 HAS DESIRF.D TIME BEEN REACHF.D?
BNE WTCNT NO, WAIT

This approach is the same one you would take if you had to let something cook for
20 minutes. You must determine the current time by reading your watch (the counter),
calculate the target time by adding 20 (mod 60, so 20 minutes past 6:50 is 7:10), and wait
for your watch to reach the target time. Change the program so it produces a 20 minute
delay (an obvious requirement for a microprocessor-controlled microwave oven).
Of course, the program could perform other tasks and only check the elapsed time
occasionally. How would you produce a delay of seven seconds? Of three minutes?
Many applications do not require long delays to be highly accurate; for example, the
operator of a microwave oven does not care if the time intervals are off by a few seconds.
Sometimes you may want to keep time either as BCD digits or as ASCII charac­
ters. How would you revise the last interrupt service routine to handle these alterna­
tives?

Service Time for the Real- Time Clock

The complete service routine for a real-time clock may seem long, but it
actually uses very little processor time. The execution times are as follows:

Number of clock cycles

Condition Frequency required

No additional updating Every 10 ms 59


Update seconds Every second 82
Update minutes Every minute 104
Update hours Every hour 118
15-28 6809 Assembly Language Programming

Much of the execution time (see Table 15-4) goes to the interrupt response (21
clock cycles) and to the RTI instruction (15 clock cycles), since these require the
transfer of many registers to and from the Hardware Stack. Thus the largest number of
clock cycles ever used by the real-time clock service routine is 118 during a total period
of 10 milliseconds. This is 1.18rVcJ of the available processor time if the clock frequency is
1 MHz. The average requirement is half the maximum, since the service routine
requires its minimum execution time 99 times out of 100 and only requires its max­
imum execution time once every 360,000 times (once per hour). Thus a real-time clock
generally does not burden the processor very much, unless its frequency is high.

High-Frequency Clock

Even a high-frequency real-time clock can be handled without much processor


intervention. The usual method is to have the clock increment a set of counters which
then interrupt the processor at a much lower frequency. For example, the input fre­
quency could be 1 MHz; that input frequency would then be passed through 3 decimal
counters and the output of the last one would be tied to the PIA. The PIA would receive
a single clock pulse for every 1000 input pulses (that is, when the 3 decimal counters
overnow). The processor can determine the time to greater precision than 1 ms by read­
ing the counters, since they contain the less significant digits. As usual, some additional
hardware (counters and input ports) is necessary to reduce the burden on the CPU. This
is a typical tradeoff; the additional hardware is worthwhile only if the application
requires precise timing.

15-5. A TELETYPEWRITER INTERRUPT

15-5a. ACIA Interrupt Routine

Purpose: The main program clears a flag in memory location 0040 and waits for an
interrupt from a 6850 ACIA. The interrupt service routine sets the nag in
memory location 0040 to 1 and places the data from the ACIA in memory
location 0041. The characters are 7-bits in length with odd parity and two stop
bits.

Program 15-5a:

Main Program:

8010 ACIACR EQU $8010


8011 ACIADR EQU $8011
0100 INTRP EQU $0100
*

0000 ORG $0000


0000 10CE 0100 LOS S$100 START STACK AT MEMORY LOCATION
*
OOFF
0004 OF 40 CLR $40 CLEAR DATA READY FLAG
0006 86 03 LDA t%00000011 MASTER RESET ACIA
0008 B7 8010 STA ACIACR
OOOB 86 cs LOA #%11000101 ENABLE ACIA RECEIVER
OOOD B7 8010 STA ACIACR INTERRUPT
0010 1C EF ANDCC #%11101111 ENABLE CPU INTERRUPT
0012 OD 40 WTRDY TST $40 IS THERE DATA FROM THE ACIA?
0014 27 FC BEQ WTRDY NO, WAIT
0016 3F SWI YES, PROCEED
Interrupts 15-29

Interrupt Service Routine:

0100 ORG INTRP


0100 B6 8011 LOA ACIADR GET DATA FROM ACIA
0103 97 41 STA $41 SAVE DATA IN MEMORY
0105 DC 40 INC $40 SET DATA READY FLAG
0107 3B RTI

Since the 6850 ACIA has no RESET input, a MASTER RESET (setting Control
register bits 0 and 1 to one simultaneously) is necessary before the ACIA is initialized.
We then initialize the bits in the ACIA control register as follows:

Bit 7 = 1 to enable the receiver interrupt

Bit 6 = 1 and Bit 5 = 0 to disable the transmitter interrupt

Bit 4 = 0, Bit 3 = 0. and Bit 2 = 1 to select 7-bit data with


odd parity and two stop bits

Bit 1 = 0 and Bit 0 1 to select the divide by 1 6 clock mode


=

(a 1 7 60 Hz clock must be supplied for a 110 Baud data rate).

To determine if a particular 6850 ACIA is the source of an interrupt, the program


must examine the interrupt request bit (bit 7 of the Status Register). To differentiate
between receiver and transmitter interrupts, the program must examine the Receive
Data Register Full bit (bit 0 of the Status Register). Either reading the Receive Data
Register or writing into the Transmit Data Register clears the ACIA's interrupt request
bit.

15-5b. PIA Start Bit Interrupt

Received data is tied to both data bit 7 and control line 1 of the PIA.

Purpose: The main program clears a flag in memory location 0040 and waits for a
teletypewriter interrupt. The interrupt service routine sets the flag in memory
location 0040 to 1 and places the data from the teletypewriter in memory loca­
tion 004 1 .

Program 15-5b:

Main Program:

8001 PIACA EQU $8001


8000 PIADDA EQU $8000
8000 PI ADA EQU $8000
0100 INTRP EQU $0100
0030 TTYRCV EQU $0030
*

0000 ORG $0000


0000 10CE 0100 LOS H100 START STACK AT MEMORY LOCATION
*
DOFF
0004 OF 40 CLR $40 CLEAR DATA READY FLAG
0006 7F 8001 CLR PIACA ADDRESS DATA DIRECTION REGISTER
0009 7F 8000 CLR PIADDA MAKE ALL DATA LINES INPUTS
oooc 86 05 LOA #%00000101 E N ABLE START BIT INTERRUPT
OOOE B7 8001 STA PIACA FROM PIA
0011 1C EF AN DCC #%11101111 E NABLE CPU INTERR UPT
0013 OD 40 WTSTB TST $40 HAS START BIT BEEN RECEIVED?
0015 27 FC BEQ WTSTB NO, WAIT
0017 90 30 JSR TTYRCV YES, FETCH DATA FROM TTY
0019 97 41 STA $41 SAVE DATA IN MEMORY
001B 3F SWI
15-30 6809 Assembly Language Programming

Interrupt Service Routine:

0100 ORG INTRP


0100 86 8000 LOA PIADA CLEAR START BIT INTERRUPT
0103 oc 40 INC $40 SET DATA READY FLAG
0105 86 04 LOA #%00000100 DISABLE START BIT INTERRUPT
0107 B7 8001 STA PIACA
OlOA 3B RTI

Subroutine TTYRCV is the teletypewriter receive routine shown in Chapter 13,


except that we have assumed a version that leaves the data in Accumulator A. The edge
used to cause the interrupt is very important here. The transition from the normal 'I'
(MARK) state to the '0' (SPACE) state must cause the interrupt, since this transition
signifies the start of the transmission. No '0' to' I' transition will occur until a non-zero
data bit is received.
The service routine must disable the PIA interrupt, since otherwise each 'l' to '0'
transition in the character will cause an interrupt. Note that reading the data bits will
clear any status flags set by the ignored transitions. Of course, the program must reena­
ble the PIA interrupt (by selling bit 0 of the control register) to aiiow receipt of the next
character, but this should be done after the current character has been read.
As we mentioned earlier in this chapter, we can also disable PIA interrupts by
using logical functions or the INC and DEC instructions. The following programs are
independent of the contents of the PIA Control Register.

1. Disabling the PIA interrupt from control line l.

LOA PIACR
ANDA #%11111110 DISABLE PIA INTERRUPT
STA PIACR

or DEC PIACR DISABLE PIA INTI:RRUPT

2. Enabling the PIA interrupt from control line 1.

LOA PIACR
ORA #%00000001 ENABLE PIA INT�RHUPT
STA PIACR

or INC PIACR ENABLE PIA INTPPPUPT

The DEC instruction only works correctly if you know that the interrupt is
enabled, while the INC instruction only works correctly if you know that the interrupt is
disabled. If the interrupt is already in the desired state, INC or DEC can have curious
effects (try it!), whereas the logical functions have no effect in that case.

MORE GENERAL SERVICE ROUTINES8

More general interrupt service routines that are part of a complete interrupt­
driven system must handle the following tasks:

1. Saving any needed data in the Stack so the interrupted program can be
resumed correctly. The 6809 microprocessor saves all the user registers auto­
matically in response to IRQ or NMI and as part of the execution of CWAI
and the Software Interrupt instructions. An interrupt service routine for
Interrupts 15-31

FIRQ will have to save and restore any registers it uses besides the Program
Counter and the Condition Code Register.
2. Restoring data and registers (if not automatically saved) before executing
RTI and returning control to the interrupted program.
3. Establishing the priority of the interrupt, perhaps by writing that priority
into an external register.

The program can then reenable the rest of the interrupt system. Remember,
however, that to restore the old priority correctly, you must save it in the
stack along with the other status. The program must save a copy of the current
priority in RAM if the external priority register is write-only.

4. Restoring the old priority before returning control to the interrupted pro­
gram.

5. Enabling and disabling interrupts appropriately. Remember that the CPU


automatically disables IRQ after accepting an interrupt on that line and auto­
matically disables IRQ and FIRQ after accepting an interrupt on FIRQ or
NML

The service routines should be transparent as far as the interrupted program is


concerned; that is, they should have no incidental effects.
Any standard subroutines that an interrupt service routine uses must be
reentrant. If some subroutines cannot be made reentrant, the interrupt service routine
must have separate versions to use.

PROBLEMS

15-1. A TEST INTERRUPT

Purpose: The computer waits for a PIA interrupt to occur, then executes the endless
loop instruction:

HERE RRA HERE

until the next interrupt occurs.

15-2. A KEYBOARD INTERRUPT

Purpose: The computer waits for a 4-digit entry from a keyboard and places the digits
into memory locations 0050 through 0053 (first one received in 0050). Each
digit entry causes an interrupt. The fourth entry should also result in the dis­
abling of the keyboard interrupt.

Sample Problem:

Keyboard data = 04. 06. 01. 07

Result: (0050) 04
(0051) 06
10052) 01
(0053) 07
15-32 6809 Assembly Language Programming

15-3. A PRINTER INTERRUPT

Purpose: The computer sends four characters from memory locations 0050 through
0053 (starting with 0050) to the printer. Each character is requested by an
interrupt. The fourth transfer also disables the printer interrupt.

15-4. A REAL- TIME CLOCK INTERRUPT

Purpose: The computer clears memory location 0040 initially and then complements
that location each time the real-time clock interrupt occurs. How would you
change the program so that it complements memory location 0040 after every
ten interrupts? How would you change the program so it leaves 0040 at zero
for ten clock periods, FF 16 for five clock periods, and so on continuously? You
may want to use a display rather than memory location 0041 to make it easier
to see.

15-5. A TELETYPEWRITER INTERRUPT

Purpose: The computer receives TTY data from an interrupting 6850 ACIA and stores
the characters in a buffer starting in memory location 0050. The process con­
tinues until the computer receives a carriage return (0016 ) . Assume that the
characters are 7-bit ASCII with odd parity. How would you change your pro­
gram to use a PIA? Assume that subroutine TTYRCV is available, as in the
example. Include the carriage return as the final character in the buffer.

REFERENCES

1. A. Osborne. An Introduction to Microcomputers: Volume I -Basic Concepts,


Osborne/McGraw-Hill, Berkeley, Calif., 1980, Chapter 5.
2. R. L. Baldridge. "Interrupts Add Power, Complexity to Microcomputer Software
Design," EDN, August 5, 1977, pp. 67-73.
3. R. Morris. "6800 Routine Supervises Service Requests," EDN, October 5, 1979,
pp. 73-81.
4. l. P. Breikss. "Nonmaskable Interrupt Saves Processor Register Contents,"
Electronics, July 21, 1977, p. 104.

5. A. Osborne. An Introduction to Microcomputers: Volume 2 -Some Real


Microprocessors, Osborne/McGraw-Hill, Berkeley, Calif., pp. 9-71 through 9-77.
6. R. Grappel. "Technique A voids Interrupt Dangers," EDN, May 5, 1979, p. 88.
7. G. Horner. "Online Control of a Laboratory Instrument by a Timesharing Com­
puter," Computer Design, February 1980, pp. 90-106.
8. For further discussion and some real-life examples of designing 6800-based systems
with interrupts, see the following:
S.C. Baunach. "An Example of an M6800-based GPIB Interface", EDN, Septem­
ber 20, 1977, pp. 125-28.
Interrupts 15-33

L. E. Cannon and P. S. Kreager. "Using a Microprocessor: a Real-Life Application,


Part 2 - Software," Computer Design, October 1975, pp. 81-89.
D. Fullager, et al. "Interfacing Data Converters and Microprocessors," Electronics,
December 8, 1976, pp. 81-89.
S. A. Hill. "Multiprocess Control Interface Makes Remote 1-1- P Command Possi­
ble," EDN, February 5, 1976, pp. 87-89.
W. S. Holderby. "Designing a Microprocessor-based Terminal for Factory Data
Collection," Computer Design, March 1977, pp. 81-88.
A. Lange. "OPTACON Interface permits the Blind to 'Read' Digital Instruments,"
EDN, February 5, 1976, pp. 84-86.

J. D. Logan and P. S. Kreager. "Using a Microprocessor: a Real-Life Application,


Part 1- Hardware," Computer Design, September 1975, pp. 69-77.
A. Moore and M. Eidson. "Printer Control," Application Note available from
Motorola Semiconductor Products, Phoenix, Ariz.
M. C. Mulder and P. P. Fasang. "A Microprocessor Controlled Substation Alarm
Logger," IECI '78 Proceedings - Industrial Applications of Microprocessors,
March 20-22, 1978, pp. 2-6.
P. J. Zsombar-Murray et al. "Microprocessor Based Frequency Response
Analyzer," IECI '78 Proceedings - Industrial Applications of Microprocessors,
March 20-22, 1978, pp. 36-44.

The Proceedings of the IEEE's Industrial Electronics and Control Instrumentation


Group's Annual Meeting on "Industrial Applications of Microprocessors" contain
many interesting articles. Volumes (starting with 1975) are available from IEEE Service
Center, CP Department, 445 Hoes Lane, Piscataway, N. J. 08854.
IV
Software Development

The previous chapters have described how to write short assembly language pro­
grams. While this is an important topic, it is only a small part of software development.
Although writing assembly language programs is a major task for the beginner, it soon
becomes simple. By now you should be familiar with standard methods for program­
ming in assembly language on the 6809 microprocessor. The next six chapters will de­
scribe how to formulate tasks as programs and how to combine short programs to
form a working system.

THE STAGES OF SOFTWARE DEVELOPMENT

Software development consists of many stages. Figure IV -1 is a flowchart of the


software development process. Its stages are:

• Problem definition

• Program design

• Coding
• Debugging

• Testing
• Documentation
• Maintenance and redesign

Each of these stages is important in the construction of a working system. Coding,


the writing of programs in a form that the computer understands, is only one stage in a
long process.
IV-2. 6809 Assembly Language Programming

Problem definition Coding and


and documentation documentation

Program design
Debugging
and documentation

Design
evaluation

Testing

No

Yes

No Final
documentation

Maintenance
and redesign

Figure IV-1. Flowchart of Soft ware Development


Software Development IV-3

RELATIVE IMPORTANCE OF CODING

Coding is usually the easiest stage to define and perform. The rules for writing
computer programs are easy to learn. They vary somewhat from computer to computer,
but the basic techniques remain the same. Few software projects run into trouble
because of coding; indeed, coding is not the most time-consuming part of software
development. Experts estimate that a programmer can write one to ten fully debugged
and documented statements per day. Clearly, the mere coding of one to ten statements
is hardly a full day's effort. On most software projects, coding occupies less than 25°/(J of
the programmer's time.

MEASURING PROGRESS IN OTHER STAGES

Measuring progress in other stages is difficult. You can say that half of the pro­
gram has been written, but you can hardly say that half of the errors have been removed
or half of the problem has been defined. Timetables for such stages as program design,
debugging, and testing are difficult to produce. Many days or weeks of effort may result
in no clear progress. Furthermore, an incomplete job in one stage may result in tremen­
dous problems later. For example, poor problem definition or program design can make
debugging and testing very difficult. Time saved in one stage may be spent many times
over in later stages.

DEFINITION OF THE STAGES

Problem Definition

Problem definition is the formulation of the requirements that the task places
on the computer. For example, what is necessary to make a computer control a tool, run
a series of electrical tests, or handle communications between a central controller and a
remote instrument? Problem definition requires that you determine the forms and rates
of inputs and outputs, the amount and speed of processing that is needed, and the types
of possible errors and their handling. Problem definition takes a vague idea of building a
computer-controlled system and defines the tasks and requirements for the computer.

Program Design

Program design is the outline of the computer program that will meet the
requirements. In the design stage, the tasks are described in a way that can easily be
converted into a program. Among the useful techniques in this stage are flowcharting,
structured programming, modular programming, and top-down design.

Coding

Coding is the writing of the program in a form that the computer can either
directly understand or translate_ The form may be machine language, assembly
language, or a high-level language.
IV-4. 6809 Assembly Language Programming

Debugging

Debugging, also called program verification, is making the program perform


according to the design. In this stage, you use such tools as breakpoints, traces, simula­
tors, logic analyzers, and in-circuit emulators. The end of the debugging stage is hard to
define, since you never know when you have found the last error.

Testing

Testing, also referred to as program validation, is ensuring that the program per­
forms the overall system tasks correctly. The designer uses simulators, exercisers, and
statistical techniques to measure the program's performance. This stage is like quality
control for hardware.

Documentation

Documentation is the description of the program in the proper form for users
and maintenance personnel. Documentation also allows the designer to develop a pro­
gram library so that subsequent tasks will be far simpler. Flowcharts, comments,
memory maps, and library forms are some of the tools used in documentation.

Maintenance and Redesign

Maintenance and redesign are the servicing, improvement, and extension of


the program. Clearly, the designer must be ready to handle field problems in computer­
based equipment. Special diagnostic modes or programs and other maintenance tools
may be required. Upgrading or extension of the program may be necessary to meet new
requirements or handle new tasks.
16
Problem Definition

Typical microprocessor tasks require a lot of definition. For example, what


must a program do to control a scale, a cash register, or a signal generator? Clearly,
we have a long way to go just to define the tasks involved.

INPUTS

How do we start the definition? The obvious place to begin is with the inputs. We
should begin by listing all the inputs that the computer may receive in this applica­
tion.
Examples of inputs are:

Data blocks from transmission lines

Status words from peripherals

Data from AID converters

Then we may ask the following questions about each input:

1. What is its form; that is, what signals will the computer actually receive?

2. When is the input available and how does the processor know it is available?
Does the processor have to request the input with a strobe signal? Does the
input provide its own clock?

3. How long is it available?


16-2 6809 Assembly Language Programming

4. How often does it change, and how does the processor know that it has
changed?

5. Does the input consist of a sequence or block of data? Is the order important?

6. What should be done if the data contains errors? These may include transmis­
sion errors, incorrect data, sequencing errors, extra data, etc.

7. Is the input related to other inputs or outputs?

OUTPUTS

The next step to define is the output. We must list all the outputs that the com-
puter must produce. Examples of outputs include:

Data blocks to transmission lines

Control words to peripherals

Data to D/ A converters

Then we may ask the following questions about each output:

I. What is its form; that is, what signals must the computer produce?
2. When must it be available, and how does the peripheral know it is available?

3. How long must it be available?

4. How often must it change, and how does the peripheral know that it has
changed?

5. Is there a sequence of outputs?

6. What should be done to avoid transmission errors or to sense and recover


from peripheral failures?

7. How is the output related to other inputs and outputs?

PROCESSING SECTION

Between the reading of input data and the sending of output results is the process­
ing section. Here we must determine exactly how the computer must process the input
data. The questions are:

I. What is the basic procedure (algorithm ) for transforming input data into out­
put results?

2. What time constraints exist? These may include data rates.

3. What memory constraints exist? Do we have limits on the amount of program


memory or data memory, or on the size of buffers?
4. What standard programs or tables must be used? What are their require-
ments?

5. What special cases exist, and how should the program handle them?

6. How accurate must the results be?


7. How should the program handle processing errors or special conditions such
as overflow, underflow, or loss of significance?
Problem Definition 16-3

ERROR HANDLING

An important factor in many applications is the handling of errors. Clearly, the


designer must make provisions for recovering from common errors and for diagnosing
malfunctions. Among the questions that the designer must ask at the definition stage
are:

1. What errors could occur?


2. Which errors are most likely? If a person operates the system, human error is
the most common. Following human errors, communications or transmission
errors are more common than mechanical, electrical, mathematical, or pro­
cessor errors.

3. Which errors will not be immediately obvious to the system? A special prob­
lem is the occurrence of errors that the system or operator may not recognize
as incorrect.

4. How can the system recover from errors with a minimum loss of time and
data and yet be aware that an error has occurred?

5. Which errors or malfunctions cause the same system behavior? How can
these errors or malfunctions be distinguished for diagnostic purposes?

6. Which errors involve special system procedures? For example, do parity


errors require retransmission of data?

Another question is: How can the field technician systematically find the source of
malfunctions without being an expert? Built-in test programs, special diagnostics, or sig­
nature analysis can help. I

HUMAN FACTORS/OPERATOR INTERACTION

Many microprocessor-based systems involve human interaction. Human factors


must be considered throughout the development process for such systems. Among the
questions that the designer must ask are:
1. What input procedures are most natural for the human operator?

2. Can the operator easily determine how to begin, continue and end the input
operations?

3. How is the operator informed of procedural errors and equipment malfunc-


tions?

4. What errors is the operator most likely to make?

5. How does the operator know that data has been entered correctly?

6. Are displays in a form that the operator can easily read and understand?
7. Is the response of the system adequate for the operator?

8. Is the system easy for the operator to use?

9. Are there guiding features for an inexperienced operator?

10. Are there shortcuts and reasonable options for the experienced operator?

11. Can the operator always determine or reset the state of the system after
interruptions or distractions?
16-4 6809 Assembly Language Programming

Building a system for people to use is difficult. The microprocessor can make the
system more powerful, more flexible, and more responsive. However, the designer still
must add the human touches that can greatly increase the usefulness and attractive­
ness of the system and the productivity of the human operator.2

The processor, of course, has no intrinsic preference in situations involving


human characteristics or cultural choices. The processor does not prefer left-to-right
over right-to-left, forward over backward, increasing order over decreasing order, or
decimal numbers over other number systems. Nor does the processor recognize the
operator's preference for simplicity, consistency, compatibility with previous
experience, and "logical" order of operations. The processor never gets distracted, dis­
oriented, confused, or bored. The designer must allow for aJI these considerations in the
design and development of interactive systems.

EXAMPLES

DEFINING A SWITCH AND LIGHT SYSTEM

Figure 16-1 shows a simple system in which the input is from a single SPST
switch and the output is to a single LED display. In response to a switch closure, the
processor turns the display on for one second. This system should be easy to define.

Switch Input

Let us first examine the input and answer each of the questions previously pre­
sented:

1. The input is a single bit, which may be either '0' (switch closed ) or' 1' (switch
open ) .
2. The input is always available and need not be requested.
3. The input is available for at least several milliseconds after the closure.
4. The input will seldom change more than once every few seconds. The pro­
cessor has to handle only the bounce in the switch. The processor must moni­
tor the switch to determine when it is closed.
5. There is no sequence of inputs.
6. The obvious input errors are switch failure, failure in the input circuitry, and
the operator attempting to close the switch again before a sufficient amount of
time has elapsed. We will discusss the handling of these errors later.
7. The input does not depend on any other inputs or outputs.
Problem Definition 16-5

Input
Port

+5V
CPU

Output
Port

The switch input is a '1' if the switch is open.0 if the switch is closed.
' '

The CPU applies the output to the cathode of the LED: a ·o· lights the display.

Figure 16-1. The Switch and Light System

Light Output

The next requirement in defining the system is to examine the output. The
answers to our questions are:

1. The output is a single bit, which is '0' to turn the display on, '1' to turn it off.
2. There are no time constraints on the output. The peripheral does not need to
be informed of the availability of data.
3. lf the display is an LED, the data need be available for only a few milliseconds
at a pulse rate of about 100 times per second. The observer will see a con­
tinuously lit display.
4. The data must change (go off) after one second.
5. There is no sequence of outputs.
6. The possible output errors are display failure and failure in the output circui­
try.
7. The output depends only on the switch input and time.

Processing

The processing section is extremely simple. As soon as the switch input


becomes a logic '0', the CPU turns the light on (a logic '0') for one second. No time or
memory constraints exist.

Error Handling

Let us now look at the possible errors and malfunctions. These are:

Another switch closure before one second has elapsed


Switch failure
Display failure
Computer failure
16-6 6809 Assembly Language Programming

Surely the first error is the most likely. The simplest solution is for the processor
to ignore switch closures until one second has elapsed. This brief unresponsive period
will hardly be noticeable to the human operator. Furthermore, ignoring the switch dur­
ing this period means that no debouncing circuitry or software is necessary, since the
system will not react to the bounce anyway.
Clearly, the last three failures can produce unpredictable results. The display may
stay on, stay off, or change state randomly. Some possible ways to isolate the failures
would be:

Lamp-test hardware to check the display; i.e., a button that turns the light on
independently of the processor
A direct connection to the switch to check its operation
A diagnostic program that exercises the input and output circuits

If both the display and switch are working, the computer is at fault. A field techni­
cian with proper equipment can determine the cause of the failure.

DEFINING A SWITCH-BASED MEMORY LOADER

Figure 16-2 shows a system that allows the user to enter data into any memory
location in a microcomputer. One input port, DPORT, reads data from eight toggle
switches. The other input port, CPORT, is used to read control information. There
are three momentary switches: High Address, Low Address and Data. The output is
the value of the last completed entry from the data switches; eight LEDs are used for
the display.
The system will also, of course, require resistors, buffers, and drivers.

Inputs

The characteristics of the switches are the same as in the previous example. To
simplify the debouncing procedure and force the operator to release the buttons, we
have the system respond only after a button is released; this is a common technique
that reduces wear on the switches as well, since the operator is less tempted to press a
button repeatedly. In this system there is a distinct sequence of inputs, as follows:

1. The operator must set the data switches according to the eight most significant
bits of an address, then
2. press and release the High Address button. The high address bits will appear
on the lights, and the program will interpret the data as the high byte of the
address.
3. Then the operator must set the data switches with the value of the least sig­
nificant byte of the address and
4. press and release the low Address button. The low address bits will appear on
the lights, and the program will consider the data to be the low byte of the
address.
5. Finally, the operator must set the desired data into the data switches and
6. press and release the Data button. The display will now show the data, and the
program stores the data in memory at the previously entered address.
Problem Definition 16-7

Input
Port
DPORT

Data
Bus

-
-

.,_ ..L. High Address


__ __u

Input
..L Low Address
CPU Port
CPORT

..L. Data
t-----o

+5V

Output
Port

Figure 16-2. The Switch-Based Memory Loader


16-8 6809 Assembly Language Programming

The operator may repeat the process to enter an entire program. Clearly, even in
this simplified situation, we will have many possible sequences to consider. How do we
cope with erroneous sequences and make the system easy to use?

Output

Output is no problem. After each input, the program sends to the displays the
complement (since the displays are active-low) of the input bits. The output data
remains the same until the next input operation.

Processing

The processing section remains quite simple. There are no time or memory con­
straints. The program can debounce the switches by waiting for a few milliseconds, and
must provide complemented data to the displays.

Error Handling

The most likely errors are operator mistakes. These include:

Incorrect entries
Incorrect order

Incomplete entries; for example, forgetting the data

The system must be able to handle these problems in a reasonable way, since they
are certain to occur in actual operation.

The designer must also consider the effects of equipment failure. Just as before,
the possible difficulties are:

Switch failure

Display failure

Computer failure

In this system, however, we must pay more attention to how these failures affect
the system. A computer failure will cause a complete system breakdown that will be easy
to detect. A display failure may not be immediately noticeable; here a Lamp Test feature
will allow the operator to check the operation. Note that we would like to test each LED
separately, in order to diagnose the case in which output lines are shorted together. In
addition, the operator may not immediately detect switch failure; however, the operator
should soon notice it and establish which switch is faulty by a process of elimination.

Operator Error Correction

Let us look at some of the possible operator errors. Typical errors will be:

Erroneous data

Wrong order of entries or switches

Trying to go on to the next entry without completing the current one


Problem Definition 16-9

The operator will presumably notice erroneous data as soon as it appears on the
displays. What is a viable recovery procedure? Some options are:

1. The operator must complete the entry procedure; i.e., enter Low Address and
Data if the error occurs in the High Address. Clearly, this procedure is waste­
ful and annoying.

2. The operator may restart the entry process by returning to the high address
entry steps. This solution is useful if the error was in the High Address, but
forces the operator to re-enter earlier data if the error was in the Low Address
or Data stage.

3. The operator may enter any part of the sequence at any time simply by setting
the Data switches with the desired data and pressing the corresponding but­
ton. This procedure allows the operator to make corrections at any point in the
sequence.

This type of procedure should always be preferred over one that does not allow
immediate error correction, has a variety of concluding steps, or enters data into the
system without allowing the operator a final check. Any added complication in hard­
ware or software will be justified in increased operator efficiency. You should always
prefer to let the microcomputer do the tedious work and recognize arbitrary sequences;
it never gets tired and never forgets the operating procedures.
A further helpful feature would be status lights that would define the meaning
of the display. Three status lights, marked "High Address," "Low Address," and
"Data," would let the operator know what had been entered without having to remem­
ber which button was pressed. The processor would have to monitor the sequence, but
the added complication in software would simplify the operator's task. Clearly, three
separate sets of displays plus the ability to examine a memory location would be even
more helpful to the operator.
We should note that, although we have emphasized human interaction,
machine or system interaction has many of the same characteristics. The
microprocessor should do the work. If complicating the microprocessor's task makes
error recovery simple and the causes of failure obvious, the entire system will work
better and be easier to maintain. Note that you should not wait until after the software
has been completed to consider system use and maintenance; instead, you should
include these factors in the problem definition stage.

DEFINING A VERIFICATION TERMINAL

Figure 16-3 is a block diagram of a simple credit-verification terminal. One


input port derives data from a keyboard (see Figure 16-4); the other input port
accepts verification data from a transmission line. One output port sends data to a set
of displays (see Figure 16-5); another sends the credit card number to the central
computer. A third output port turns on one light whenever the terminal is ready to
accept an inquiry, and another light when the operator sends the information. The
"busy" light is turned off when the terminal receives a response. Clearly, the input
and output of data will be more complex than in the previous case, although the process­
ing is still simple.
16-10 6809 Assembly Language Programming

--
- Keyboard Strobe
,...--- Keyboard
r-- Input Port
J Keyboard Data

...


Display
Display
Output Portis)

- Peripheral Ready Strobe


!------" X MIT
CPU
f----. Output Port
,.
To Central Computer
r

--
- Data Strobe
.....___ RCV
r-- Input Port
] From Central Computer


BUSY Display
Status Light
Output Port
. READY Display

Figure 16-3. Block Diagram of a Verification Terminal

The digit keys allow digit entries.


CLEAR deletes the entire entry.
SEND transmits the entry to the central computer.

Figure 16-4. Verification Terminal Keyboard

Additional displays may be useful to emphasize the meaning of the response.


Many terminals use a green light for "Yes," a red light for "No," and a yellow light for
"Consult Store Manager." Note that these lights will still have to be clearly marked with
their meanings to allow for a color-blind operator.
Problem Definition 16-11

READY BUSY

D D

The display consists of ten 7 -segment displays. which may be multiplexed. controlled by a shift
register. or addressed separately. Two additional lights. READY and BUSY. are also present.

Figure 16-5. Verilication Terminal Display

Inputs

Let us first look at the keyboard input. This is, of course, different from the
switch input, since the CPU must have some way of distinguishing new data. We will
assume that each key closure provides a unique hexadecimal code (we can code each
of the 12 keys into one digit) and a strobe. The program will have to recognize the
strobe and fetch the hexadecimal number that identifies the key. There is a time con­
straint, since the program cannot miss any data or strobes. The constraint is not serious,
since keyboard entries will be at least several milliseconds apart.
The transmission input similarly consists of a series of characters, each iden­
tified by a strobe (perhaps from a UART). The program will have to recognize each
strobe and fetch the character. The data being sent across the transmission lines is
usually organized into messages. A possible message format is:

Introductory characters, or header


Terminal destination address
Coded yes or no
Ending characters, or trailer

The terminal will check the header, read the destination address, and see if the
message is intended for it. If the message is for the terminal, the terminal accepts the
data. The address could be (and often is) hard-wired into the terminal so that the ter­
minal receives only messages intended for it. This approach simplifies the software at
the cost of some flexibility.

Outputs

The output is also more comolex than in the earlier examples. If the displays are
multiplexed, the processor must not only send the data to the display port but must
also direct the data to a particular display. We will need either a separate control port
or a counter and decoder to handle this. Note that hardware blanking controls can blank
leading zeros as long as the first digit in a multi-digit number is never zero. Software can
also handle this task. Time constraints include the pulse length and frequency required
to produce a continuous display for the operator.
16-12 6809 Assembly Language Programming

The communications output will consist of a series of characters with a particu­


lar format. The program will also have to consider the time required between charac­
ters. A possible format for the output message is:

Header

Terminal address

Credit card number

Trailer

A central communication computer may poll the terminals, checking for data
ready to be sent.

Processing

The processing in this system involves many new tasks, such as:

Identifying the control keys by number and performing the proper actions

Adding the header, terminal address, and trailer to the outgoing message

Recognizing the header and trailer in the returning message

Checking the incoming terminal address

Note that none of the tasks involves any complex arithmetic or any serious time
or memory constraints.

Error Handling

The number of possible errors in this system is, of course, much larger than in
the earlier examples. Let us first consider the possible operator errors. These include:

Entering the credit card number incorrectly

Trying to send an incomplete credit card number

Trying to send another number while the central computer is processing one

Clearing nonexistent entries

Some of these errors can be handled easily by organizing the program correctly.
For example, the program should not accept the Send key until the credit card number
has been completely entered, and it should ignore any additional keyboard entries until
the response comes back from the central computer. Note that the operator will know
that the entry has not been sent, since the Busy light will not go on. The operator will
also know when the keyboard has been locked out (the program is ignoring keyboard
entries), since entries will not appear on the display and the Ready light will be off.

Correcting Keyboard Errors

Incorrect entries are an obvious problem. If the operator recognizes an error, he


or she can use the Clear key to make corrections. The operator would probably find it
more convenient to have two Clear keys, one that cleared the most recent key and one
that cleared the entire entry. This would allow both for the situation in which the
operator recognizes the error immediately and for the situation in which the operator
Problem Definition 16-13

recognizes the error late in the procedure. The operator should be able to correct errors
immediately and have to repeat as few keys as possible. The operator will, however,
make a certain number of errors without recognizing them. Most credit card numbers
include a self-checking digit; the terminal could check the number before permitting
it to be sent to the central computer. This step would save the central computer from
wasting processing time checking the number.
This requires, however, that the terminal have some way of informing the
operator of the error, perhaps by flashing one of the displays or by providing some other
special indicator that the operator is sure to notice.
Still another problem is how the operator knows that an entry has been lost or
processed incorrectly. Some terminals simply unlock after a maximum time delay. The
operator notes that the Busy light has gone off without an answer being received. The
operator is then expected to try the entry again. After one or two further attempts, the
operator should report the failure to supervisory personnel.
Many equipment failures are also possible. Besides the displays, keyboard, and
processor, there now exist the problems of communications errors or failures and
central computer failures.

Correcting Transmission Errors

The data transmission will probably have to include error checking and correct­
ing procedures. Some possibilities are:

1. Parity provides an error detection facility but no correction mechanism. The


receiver will need some way of requesting retransmission, and the sender will
have to save a copy of the data until proper reception is acknowledged. Parity
is, however, very simple to implement.

2. Short messages may use more elaborate schemes. For example, the yes/no
response to the terminal could be coded to provide error detection and correc­
tion capability.

3. An acknowledgement and a limited number of retries could trigger an indica­


tor that would inform the operator of a communications failure (inability to
transfer a message without errors) or central computer failure (no response
within a certain period of time). Such a scheme, along with the Lamp Test,
would allow simple failure diagnosis.

A communications or central computer failure indicator should also "unlock"


the terminal, that is, allow it to accept another entry. This is necessary if the terminal
will not accept entries while a verification is in progress. The terminal may also unlock
after a certain maximum time delay. Certain entries could be reserved for diag­
nostics; i.e., certain credit card numbers could be used to check the internal operation
of the terminal and test the displays.
16-14 6809 Assembly Language Programming

REVIEW

Problem definition is as important a part of software development as it is of any


other engineering task. Note that it does not require any programming or knowledge of
the computer; rather, it is based on an understanding of the system and sound engineer­
ing judgment. Microprocessors offer flexibility and local intelligence that the designer
can use to provide a wide range of features.
Problem definition is independent of any particular computer, computer
language, or development system. It should, however, provide guidelines as to what
type or speed of computer the application will require and what kind of hardware/
software tradeoffs the designer can make. The problem definition stage should not
even depend on whether a computer is used, although a knowledge of the capabilities
of the computer can help the designer in suggesting possible implementations of pro­
cedures.

REFERENCES

1. D. R. Ballard. "Designing Fail-Safe Microprocessor Systems," Electronics, January


4, 1979, pp. 139-43.
"A Designer's Guide to Signature Analysis," Hewlett-Packard Application Note
222, Hewlett-Packard, Inc, Palo Alto, CA, 1977.
Donn, E. S. and M. D. Lippman. "Efficient and Effective Microcomputer Testing
Requires Careful Preplanning," EDN, February 20, 1979, pp. 97-107 (includes self­
test examples for 6502).
Gordon, G. and H. Nadig. "Hexadecimal Signatures Identify Troublespots in
Microprocessor Systems," Electronics, March 3, 1977, pp. 89-96.
Neil, M. and R. Goodner. "Designing a Serviceman's Needs into Microprocessor­
Based Systems," Electronics, March 1, 1979, pp. 122-28.
Schweber, W. and L. Pearce. "Software Signature Analysis Identifies and Checks
PROMs," EDN, November 5, 1978, pp. 79-81.
Srini, V. P. "Fault Diagnosis of Microprocessor Systems," Computer, January 1977,
pp. 60-65.
2. For a brief discussion of human factors considerations, see G. Morris. "Make Your
Next Instrument Design Emphasize User Needs and Wants," EDN, October 20,
1978, pp. 100-05.
17
Program Design

Program design is the stage in which the problem definition is formulated as a


program. If the program is small and simple, this stage may involve little more than
the writing of a one-page flowchart. If the program is larger or more complex, the
designer should consider more elaborate methods.
We will discuss flowcharting, modular programming, structured programming,
and top-down design. We will try to indicate the reasoning behind these methods, and
their advantages and disadvantages. We will not, however, advocate any particular
method since there is no evidence that one method is always superior to all others. You
should remember that the goal is to produce a good working system, not to follow
religiously the tenets of one methodology or another.

BASIC PRINCIPLES

All the methodologies are based on common principles, many of which apply to
any kind of design. Among these principles are:

1. Proceed in small steps. Do not try to do too much at one time.


2. Divide large j obs into small, logically separate tasks. Make the sub-tasks
as independent of one another as possible, so that they can be tested sepa­
rately and so that changes can be made in one without affecting the others.
3. Keep the flow of control simple to make programs easy to follow and errors
easy to locate and correct.

4. Use pictorial or graphic design descriptions as much as possible. They are


easier to visualize than word descriptions. This is the great advantage of
flowcharts.
17-2 6809 Assembly Language Programming

5. Emphasize clarity and simplicity at first. You can improve performance (if
necessary) once the system is working.
6. Proceed in a thorough and systematic manner. Use checklists and standard
procedures.
7. Do not tempt fate. Either do not use methods that you are not sure of, or
use them very carefully. Watch for situations that might cause confusion,
and clarify them as soon as possible.
8. Keep in mind that the system must be debugged, tested and maintained.
Plan for these later stages.
9. Use simple and consistent terminology and methods. Repetitiveness is no
fault in program design, nor is complexity a virtue.
10. Have your design completely formulated before you start coding. Resist
the temptation to start writing down instructions: it makes no more sense
than making parts lists or laying out circuit boards before you know exactly
what will be in the system.
11. Be particularly careful of factors that may change. Make the implementa­
tion of likely changes as simple as possible.
12. Keep the overall task in mind. Build a total framework in which individual
pieces can be defined and tested. Do not leave the entire system integration
to the end.
13. If the data is complex or there are numerous relationships between data
items, you must organize your data just as carefully as you organize your
program. We will briefly discuss the design of data structures at the end of
this chapter.

FLOWCHARTING

Flowcharting is certainly the best-known of all program design methods. Program­


ming textbooks describe how programmers first write complete flowcharts and then
start writing the actual program. In fact, few programmers have ever worked this way,
and flowcharting has often been more of a joke or a nuisance to programmers than a
design method. We will try to describe both the advantages and disadvantages of
flowcharts, and show the place of this technique in program design.

ADVANTAGES OF FLOWCHARTING

The basic advantage of the flowchart is that it is a pictorial representation. Peo­


ple find such representations much more meaningful than written descriptions. The
designer can visualize the whole system and see the relationships of the various parts.
Logical errors and inconsistencies often stand out instead of being hidden in a printed
page. At its best, the flowchart is a picture of the entire system.

Some specific advantages of flowcharts are:

l. Standard symbols exist (see Figure 17-l} so that flowcharting forms are
widely recognized.
Program Design 17-3

��
L__j Processing operation
(Arithmetic. Logic. Data movement)

0 Connector point

(..._
____ _.,.) Terminal point (Beginning or Ending)

Figure 17-1. Standard Flowchart Symbols

2. Flowcharts can be understood by someone without a programming


background.

3. Flowcharts can be used to divide the entire project into sub-tasks. The
flowchart can then be examined to measure overall progress.

4. Flowcharts show the sequence of operations and can therefore aid in locating
the source of errors.

5. Flowcharting is widely used in other areas besides programming.

6. There are many tools available to aid in flowcharting, including programmer's


templates and automated drawing packages.

DISADVANTAGES OF FLOWCHARTING

These advantages are all important. There is no question that flowcharting will
continue to be widely used. But we should note some disadvantages of flowcharting as
a program design method:

1. Flowcharts are difficult to design, draw, or change in all except the simplest
situations.
17-4 6809 Assembly Language Programming

2. There is no easy way to debug or test a flowchart.


3. Flowcharts tend to become cluttered. Designers find it difficult to balance be­
tween the amount of detail needed to make the flowchart useful and the
amount that makes the flowchart little better that a program listing.
4. Flowcharts show only the program organization. They do not show the
organization of the data or the structure of the input/output modules.
5. Flowcharts do not help with hardware or timing problems or give hints as to
where these problems might occur.
6. Flowcharts allow unstructured design. There are no rules governing the num­
bers of entries and exits, the number or type of interconnections, or the logic
that may be employed.
7. There is no obvious way to represent the simple repetition of a loop.

MAKING FLOWCHARTS USEFUL

The most useful flowcharts may ignore program variables and ask questions
directly. Of course, compromises are often necessary here. Two versions of the
flowchart are sometimes helpful - one general version in layman's language, which
will be useful to non-programmers, and one programmer's version in terms of the
program variables, which will be useful to other programmers.
A third type of flowchart, a data flowchart, may also be helpful. This flowchart
serves as a cross-reference for the other flowcharts, since it shows how the program han­
dles a particular type of data. Ordinary flowcharts show how the program proceeds, han­
dling different types of data at different points. Data flowcharts, on the other hand,
show how particular types of data move through the system, passing from one part of
the program to another. Such flowcharts are very useful in debugging and maintenance,
since errors most often show up as a particular type of data being handled incorrectly.
Thus flowcharting is a helpful technique that you should not try to extend too
far. Flowcharts are useful as program documentation, since they have standard
forms and are comprehensible to non-programmers. As a design tool, however,
flowcharts cannot provide much more than a starting outline; the programmer cannot
debug a detailed flowchart and the flowchart is often more difficult to design than the
program itself.

EXAMPLES

Flowcharting the Switch and Light System

This simple task, in which a single switch turns on a light for one second, is
easy to flowchart. In fact, such tasks are typical examples for flowcharting books,
although they form a small part of most systems. The data structure here is so simple
that it can be safely ignored.
Figure 17-2 is the flowchart. There is little difficulty in deciding on the amount of
detail required. The flowchart gives a straightforward picture of the procedure, which
anyone could understand.
Program Design 17-5

Turn light on

Turn light off

Figure 17-2. Flowchart of One-Second Response to a Switch

Flowcharting the Switch-Based Memory Loader

This system (see Figure 16-2) is considerably more complex than the previous
example, and involves many more decisions. The flowchart (see Figure 17-3) is more
difficult to draw and is not as straightforward as the previous example. In this exam­
ple, we face the problem that there is no way to debug or test the flowchart.
The flowchart in Figure 17-3 includes the improvements we suggested as part of
the problem definition. Clearly, this flowchart is beginning to get cluttered and lose its
advantages over a written description. Adding other features that define the meaning of
the entry with status lights and allow the operator to check entries after completion
would make the flowchart even more complex. Drawing the complete flowchart from
scratch could quickly become a formidable task. However, once the program has been
written, the flowchart is useful as documentation.

Flowcharting the Verification Terminal

In this application (see Figures 16-3 through 16-5) the flowchart will be even
more complex than in the switch-based memory loader case. Here, the best idea is to
flowchart sections separately so that the flowcharts remain manageable. However,
the presence of data structures (as in the multi-digit display and the messages) will make
the gap between flowchart and program much wider.
17-6 6809 Assembly Language Programming

Wait Wait Wait


debounce debounce debounce
time time time

High byte of Low byte of


Data=
Address= Address =
Switches
Switches Switches

Lights= Lights = Lights =


Switches Switches Switches

Store Data
in Address

Wait
debounce time

Figure 17-3. Flowchart of Switch-Based Memory Loader

Let us look at some of the sections. Figure 17-4 shows the keyboard entry pro­
cess for the digit keys. The program must fetch the data after each strobe and place the
digit into the display array if there is room for it. If there are already ten digits in the
array, the program simply ignores the entry.
The actual program will have to handle the displays at the same time. Note that
either software or hardware must de-activate the keyboard strobe after the processor
reads a digit.
Program Design 17-7

Clear Entry Array


Key Pointer = Start
of Entry Array
Key Counter = 0

Yes

Key = Keyboard End


Input Data
(Key Pointer) = Key

Key Pointer =

Key Pointer + 1
Key Counter =

Key Counter + 1

Figure 17-4. Flowchart of Keyboard Entry Process

Figure 17-5 adds the Send key. This key, of course, is optional. The terminal
could just send the data as soon as the operator enters a complete number. However,
that procedure would not give the operator a chance to check the entire entry. The
flowchart with the Send key is more complex because there are two alternatives.

1. If the operator has not entered ten digits, the program must ignore the Send
key and place any other key into the entry._
2. If the operator has entered ten digits, the program must respond to the Send
key by transferring control to the Send routine; and ignore all other keys.

Note that the flowchart has become much more difficult to organize and to follow.
There is also no obvious way to check the flowchart.
Figure 17-6 shows the flowchart of the keyboard entry process with all the func­
tion keys. In this example, the flow of control is not simple. Clearly, some written
description is necessary. The organization and layout of complex flowcharts requires
careful planning. We have followed the process of adding features to the flowchart one
at a time, but this still results in a large amount of redrawing. Again we should remem­
ber that throughout the keyboard entry process, the program must also refresh the dis­
plays if they are multiplexed and not controlled by shift registers or other hardware.
17-8 6809 Assembly Language Programming

Clear Display Array


Key Pointer = Start
of Display Array
Key Counter = 0

Key = Keyboard
Input Data

(Key Pointer) = Key


Key Pointer =
Key Pointer + 1
Key Counter =
Key Counter + 1

Figure 17-5. Flowchart of Keyboard Entry Process with Send Key

Figure 17-7 is the flowchart of a receive routine. We assume that the serial/
parallel conversion and error checking are done in hardware (e.g., by a UART). The
processor must:

1. Look for the header. (We assume that it is a single character.)


2. Read the destination address (we assume that it is three characters long) and
see if the message is meant for this terminal; i.e., if the three characters agree
with the terminal address.
3. Wait for the trailer character.
4. If the message is meant for the terminal, turn off the Busy light and go to Dis­
play Answer routine.
5. In the event of any errors, request retransmission by going to the appropriate
RTRANS routine.
Program Design 17-9

Clear Display Array


Key Pointer = Start
of Display Array
Key Counter = 0

Key = Keyboard
Input Data

(Key Pointer) = Key


Key Pointer =

Key Pointer + 1

Figure 17-6. Flowchart of Keyboard Entry Process with Function Keys

This routine involves a large number of decisions, and the flowchart is neither
simple nor obvious.
Clearly, we have come a long way from the simple flowchart (Figure 17-2) of
the first example. A complete set of flowcharts for the transaction terminal would be
a major task. It would consist of several interrelated charts with complex logic, and
would require a large amount of effort. Such an effort would be just as difficult as writing
a preliminary program, and not as useful, since you could not check the flowcharts on
the computer.
17-10 6809 Assembly Language Programming

Header flag = 0
Parity Error fla;J =
Address Match
flag= 0
Address Pointer =
Start of terminal
address
Address Counter= 0
Nmess = 0

Messg (Nmess)
Parity Error
Character
flag = 1
Nmess = Nmess +1

Address Match
Header flag
flag = 1

Address Counter =

Address Counter + 1 Turn off Busy


Address Pointer =
light
Address Pointer + 1

Retransmission

Figure 17-7. Flowchart of Receive Routine


Program Design 17-11

MODULAR PROGRAMMING

Once programs become large and complex, flowcharting is no longer a satisfactory


design tool. However, the problem definition and the flowchart can help you divide the
program into reasonable sub-tasks. The division of the entire program into sub-tasks
or modules is called "modular programming." Clearly, most of the programs we pre­
sented in earlier chapters would typically be modules in a large program. The problems
that the designer faces in modular programming are how to divide the program into
modules and how to put the modules together.

ADVANTAGES OF MODULAR PROGRAMMING

The advantages of modular programming are obvious:

l. A single module is easier to write, debug, and test than an entire program.
2. A module is likely to be useful in many places and in other programs, particu­
larly if it is reasonably general and performs a common task. You can build a
library of standard modules.

3. Modular programming allows the programmer to divide tasks and use pre­
viously written programs.

4. Changes can be incorporated into one module rather than into the entire
system.

5. Errors can often be isolated and then attributed to a single module.

6. Modular programming helps with project management, since it results in


obvious goals and milestones.

DISADVANTAGES OF MODULAR PROGRAMMING

The idea of modular programming is so simple that its disadvantages are often
ignored. These include:

1. Fitting the modules together can be a major problem, particularly if different


people write the modules.

2. Modules require very careful documentation, since they may affect other
parts of the program, such as data structures used by all the modules.

3. Testing and debugging modules separately is difficult, since other modules


may produce the data used by the module being debugged and still other
modules may use the results. You may have to write special programs (called
"drivers") just to produce sample data and test the programs. These drivers
require extra programming effort that adds nothing to the system.

4. Programs may be very difficult to modularize. If you modularize the program


poorly, integration will be very difficult, since almost all errors and changes
will involve several modules.

5. Modular programs often require extra time and memory, since the separate
modules may repeat functions.
17-12 6809 Assembly Language Programming

Therefore, while modular programming is certainly an improvement over trying


to write the entire program from scratch, it does have some disadvantages as well.
Important considerations include restricting the amount of information shared
by modules, limiting design decisions that are subject to change to a single module,
and restricting the access of one module to another. t

PRINCIPLES OF MODULARIZATION

An obvious problem is that there are no proven, systematic methods for


modularizing programs. We should mention the following principles ;2

1. Modules that reference common data should be parts of the same overall
module.

2. Two modules in which the first uses or depends on the second, but not the
reverse, should be separate.

3. A module that is used by more than one other module should be part of a
different overall module than the others.
4. Two modules in which the first is used by many other modules and the second
is used by only a few other modules should be separate.

5. Two modules whose frequencies of usage are significantly different should be


part of different modules.

6. The structure or organization of related data should be hidden within a single


module.

If a program is difficult to modularize, you may need to redefine the tasks that
are involved. Too many special cases or too many V?riables that require special han­
dling are typical signs of inadequate problem definition.

EXAMPLES

Modularizing the Switch and Light System

This simple program can be divided into two modules:


Module 1 waits for the switch to be turned on and turns the light on in
response.
Module 2 provides the one-second delay.
Module 1 is likely to be specific to the system, since it will depend on how the
switch and light are attached. Module 2 will be generally useful, since many tasks
require delays. Clearly, it would be advantageous to have a standard delay module that
could provide delays of varying lengths. The module will require careful documentation
so that you will know how to specify the length of the delay, how to call the module, and
what registers and memory locations the module affects.
A general version of Module 1 would be far less usefuL since it would have to deal
with different types and connections of switches and lights.
You would probably find it simpler to write a module for a particular configuration
of switches and lights rather than try to use a standard routine. Note the difference be­
tween this situation and Module 2.
Program Design 17-13

Modularizing the Switch-Based Memory Loader

The switch-based memory loader is difficult to modularize, since all the pro­
gramming tasks depend on the hardware configuration and the tasks are so simple
that modules hardly seem worthwhile. The flowchart in Figure 17-3 suggests that one
module might be the one that waits for the operator to press one of the three pushbut­
tons.
Some other modules might be:

A delay module that provides the delay required to debounce the switches
A switch and display module that reads the data from the switches and sends it
to the displays

A Lamp Test module

Highly system-dependent modules such as the last two are unlikely to be generally use­
ful. This example is not one in which modular programming offers great advantages.

Modularizing the Verification Terminal

The verification terminal, on the other hand, lends itself very well to modular
programming. The entire system can easily be divided into three main modules:

Keyboard and display module

Data transmission module

Data reception module

A general keyboard and display module could handle many keyboard- and dis­
play-based systems. The sub-modules would perform such tasks as:

Recognizing a new keyboard entry and fetching the data

Clearing the array in response to a Clear Key

Entering digits into storage

Looking for the terminator or Send key

Displaying the digits

Although the key interpretations and the number of digits will vary, the basic
entry, data storage, and data display processes will be the same for many programs. Such
function keys as Clear would also be standard. Clearly, the designer must consider
which modules will be useful in other applications, and pay careful attention to those
modules.
The data transmission module could also be divided into such sub-modules as:

1. Adding the header character.

2. Transmitting characters as the output line can handle them.


3. Generating delay times between bits or characters.

4. Adding the trailer character.

5. Checking for transmission failures� i.e., no acknowledgement, or inability to


transmit without errors.
17-14 6809 Assembly Language Programming

The data reception module could include sub-modules which:

1. Look for the header character.


2. Check the message destination address against the terminal address.
3. Store and interpret the message.
4. Look for the trailer character.
5. Generate bit or character delays.

INFORMATION HIDING PRINCIPLE

Note here how important it is that each design decision (such as the bit rate,
message format, or error-checking procedure) be implemented in only one module. A
change in any of these decisions will then require changes only to that single module.
The other modules should be written so that they are totally unaware of the values
chosen or the methods used in the implementing module. An important concept here i s
the "information-hiding principle,"J whereby modules share only information that
is absolutely essential to getting the task done. Other information is hidden within a
single module.
Error handling is a typical situation in which information should be hidden.
When a module detects a lethal error, it should not try to recover; instead, it should
inform the calling module of the error status and allow that module to decide how to
proceed. The reason is that the lower level module often lacks sufficient information to
establish recovery procedures. For example, suppose that the lower level module is one
that accepts numeric input from a user. This module expects a string of numeric digits
terminated by a carriage return. Entry of a non-numeric character causes the module to
terminate abnormally. Since the module does not know the context (i.e. is the numeric
string an operand, a lone number, an 1/0 unit number, or the length of a file?), it can­
not decide how to handle an error. If the module always followed a single error recovery
procedure, it would lose its generality and only be usable in those situations where that
procedure was required.

REVIEW OF MODULAR PROGRAMMING

Modular programming can be very helpful if you abide by the following rules:

1. Use modules of 20 to 50 lines. Shorter modules are usually a waste of time,


while longer modules are seldom general and may be difficult to integrate.
2. Make modules reasonably general. Differentiate between common features
like ASCII code or asynchronous transmission formats, which will be the
same for many applications, and key identifications, number of displays, or
number of characters in a message, which are likely to be unique to a particu­
lar application. Make the changing of the latter parameters simple. Major
changes like different character codes should be handled by separate modules.
3. Take extra time on modules like delays, display handlers, keyboard handlers,
etc. that will be useful in other projects or in many different places in the
present program.
4. Make modules independent of each other. Restrict the flow of information
between modules and implement each design in a single module.
5. Do not modularize simple tasks that are already easy to implement.
Program Design 17-15

c B

Figure 17-8. Flowchart of an Unstructured Program

STRUCTURED PROGRAMMING

How do you keep modules distinct and stop them from interacting? How do you
write a program that has a clear sequence of operations so that you can isolate and
correct errors? One answer is to use the methods known as "structured program­
ming," whereby each part of the program consists of elements from a limited set of
structures and each structure has a single entry and a single exit.
Figure 17-8 shows a flowchart of an unstructured program. If an error occurs in
Module 8, we have five possible sources for that error. Not only must we check each
sequence, but we also have to make sure that corrections do not affect any sequences.
The usual result is that debugging becomes like wrestling an octopus. Every time you
think the situation is under control, there is another loose tentacle somewhere.

BASIC STRUCTURES

The solution is to establish a clear sequence of operations so that you can isolate
errors. Such a sequence uses single-entry, single-exit structures. A program consists
of a sequence of structures; it may be a single statement or it may consist of structures
that are nested within each other to any level of complexity. Th(_ required structures
are listed below.
17-16 6809 Assembly Language Programming

1. An ordinary sequence; that is, a linear structure in which programs are


executed consecutively. If the sequence is:
P1
P2
P3

the computer executes P1 first, P2 second, and P3 third. P1, P2, and P3 may
be single statements or complex programs.
2. A conditional structure in which the execution of a program depends on a
condition.
There are many possible conditional structures, but a common one is "if C
then P1 else P2 " whe:-e C is a condition and Pl and P2 are programs. The
computer executes P1 if Cis true, and P2 if Cis false. Figure 17-9 shows the
logic of this structure. Note that it has a single entry and a single exit; the
computer cannot enter or leave P1 or P2 other than through the structure.
3. A loop structure in which a program is repeated until (or as long as) a con­
dition holds.

There are many possible loop structures. A common one (called a "do­
while " structure) is "while C do P," where C is a condition and P is a pro­
gram. The computer continually checks C and then executes Pas long as Cis
true.
An obvious alternative is ''until C do P" in which the computer continually
checks C and then executes P as long as C is false. Figures 17-10 and 1 7-11
show the logic of these alternatives. Both have a single entry and a single exit.
The computer will not execute Pat all if Cis originally in the exit state; thus P
is not executed at least once automatically as it is in a FORTRAN DO loop.
Alternative structures like "do P while C" or "repeat P until C" produce the
FORTRAN implementation in which the computer checks the condition after
executing the program (remember Figures 5-l and 5-2). This approach is
often more efficient, but we will use only the form in Figure 17-10 to simplify

No

P1 P2

Figure 17-9. Flowchart of the If-Then-Else Structure


Program Design 17-17

No

End

Figure 17-10. Flowchart of the Do-While Structure

Yes

Figure 17-11. Flowchart of the Do-Until Structure

the discussion. Most high-level structured languages allow all four alterna­
tives to provide flexibility. In most cases, the program P must eventually force
C into the exit state; if it does not, the computer will execute P endlessly (the
so-called DO FOREVER structure) as it must if P is the overall control pro­
gram for an instrument, computer peripheral, test system, or electronic game.
4. A case structure. Although it is not a primitive structure like our first three,
the case structure is so common that it merits a special description. The case
structure is "case I of PO, Pl, ... , Pn," where I is an index and PO, Pl, ... , Pn
are programs. The computer executes program PO if I is 0, Pl if I is 1, and so
on; it executes only one of the n programs. Ifl is greater than n (the number
of programs in the case statement) or after execution of one of the programs,
17-18 6809 Assembly Language Programming

No

No
PO

P1 ----,
I
I

P2

Pn

End

Figure 17-12. Flowchart of the Case Structure

the computer then executes the next sequential statement as shown in Figure
17-12. Obviously, we could implement a case structure as a series of condi­
tional structures, much as we could implement a jump table as a series of con­
ditional branches. However, the alternative implementations are long, awk­
ward, and difficult to expand.

FEATURES AND EXAMPLES OF STRUCTURES

Note the following features of structured programming:

1. Only the three basic structures, and possibly a small number of auxiliary
structures, are permitted. Variations of the conditional and loop structures
may be allowed.
Program Design 17-19

2. Structures may be nested to any level of complexity since any structure can,
in turn, contain any of the structures.

3. Each structure has a single entry and a single exit.

Some examples of the conditional structure illustrated in Figure 17-9 are:

1. P2 included:
if X > 0 then NPOS NPOS +
= l
else NNEG = NNEG + 1

Both Pl and P2 are single statements.

2. P2 omitted:
if X t 0 then Y = l/X

Here no action is taken if C (X f 0) is false. P2 and "else" can be omitted in this case.
Some examples of the loop structure illustrated in Figure 17-10 are:

1. Form the sum of integers from 1 to N.


I = 0
SUM = 0
do whi 1 e I < N
I = I + l
SUM = SUM + I
end

The computer executes the loop as long as I< N. lfN=O, the program within the "do­
while" is not executed at all.

2. Count characters in an array SENTENCE until you find an ASCII period.


NCHAR = 0
do while SENTFNCE(NCHAR) I PERIOD
NCHAR =NCHAR + 1
end

The computer executes the loop as long as the character in SENTENCE is not an ASCII
period. The count is zero if the first character is a period.

ADVANTAGES OF STRUCTURED PROGRAMMING

The advantages of structured programming are:

1. The sequence of operations is simple to trace. This allows you to test and
debug programs easily.

2. The number of structures is limited and the terminology is standardized.

3. The structures can easily be made into modules.

4. Theoreticians have proved that the given set of structures is complete; that is,
all programs can be written in terms of the three structures.

5. The structured version of a program is partly self-documenting and fairly easy


to read.

6. Structured programs are easy to describe with program outlines.

7. Structured programming has been shown in practice to increase programmer


productivity.

Structured programming basically forces much more discipline on the pro­


grammer than does modular programming. The result is more systematic and better
organized programs.
17-20 6809 Assembly Language Programming

DISADVANTAGES OF STRUCTURED PROGRAMMING

The disadvantages of structured programming are:

l. Only a few high-level languages (e.g., PLIM, PASCAL ) will directly accept the
structures. The programmer therefore has to go through an extra translation
stage to convert the structures to assembly language code. The structured ver­
sion of the program, however, is often useful as documentation.
2. Structured programs often execute more slowly and use more memory than
unstructured programs.

3. Limiting the structures to the three basic forms makes some tasks very awk­
ward to perform. The completeness of the structures only means that all pro­
grams can be implemented with them; it does not mean that a given program
can be implemented efficiently or conveniently.

4. The standard structures are often quite confusing: e.g., nested "if-then-else"
structures may be very difficult to read, since there may be no clear indication
of where the inner structures end. A series of nested "do-while" loops can
also be difficult to read.

5. Structured programs consider only the sequence of program operations, not


the flow of data. Therefore, the structures may handle data awkwardly.

6. Few programmers are accustomed to structured programming. Many find the


standard structures awkward and restrictive.

WHEN TO USE STRUCTURED PROGRAMMING

We are neither advocating nor discouraging the use of structured programming.


It is one way of systematizing program design. In general, structured programming is
most useful in the following situations:

Larger programs, perhaps exceeding 1000 instructions.

Applications in which memory usage is not critical.

Low-volume applications where software development costs, particularly test­


ing and debugging, are important factors.

Applications involving string manipulation, process control, or other


algorithms rather than simple bit manipulations.

In the future, we expect the cost of memory to decrease, the average size of
microprocessor programs to increase, and the cost of software development to
increase. Therefore, methods like structured programming, which decrease software
development costs for larger programs but use more memory, will become more
valuable.
Just because structured programming concepts are usually expressed in high-level
languages does not mean that structured programming is not applicable to assembly
language programming. On the contrary, the assembly language programmer, with the
total freedom of expression that assembly level programming allows, needs the struc­
turing concept provided by structured programming. Creating modules with single
entry and exit points, using simple control structures and keeping the complexity of
each module minimal increases the productivity of the assembly language pro­
grammer.
Program Design 17-21

EXAMPLES

Structured Program for the Switch and Light System

The structured version of this example is:

SWITCH = OFF
do while SWITCH OFF
READ SWITCH
end
LIGHT ON
DELAY 1
LIGHT = OFF

ON and OFF must have the proper definitions for the switch and light. We assume
that DELAY is a module that provides a delay given by its parameter in seconds.
A statement in a structured program may actually be a subroutine. However, in
order to conform to the rules of structured programming, the subroutine cannot have
any exits other than the one that returns control to the main program.
Since "do-while" checks the condition before executing the loop, we set the
variable SWITCH to OFF before starting. The structured program is straightforward,
readable, and easy to check by hand. However, it would probably require somewhat
more memory than an unstructured program, which would not have to initialize
SWITCH and could combine the reading and checking procedures.

Structured Program for the Switch-Based Memory Loader

The switch-based memory loader is a more complex structured programming


problem. We may implement the flowchart of Figure 17-3 as follows (a "' indicates a
comment, and we use "begin" and "end" around a conditionally executed program
that consists of more than one line):

*
*CLEAR ADDRESS INITIALLY SO ITS STARTING VALUE IS ZERO
*

HIADDRESS = 0
LOADDRESS = 0
*
* CONTINUOUSLY EXAMINE THE SWITCHES AND LOAD DATA I NTO MEMORY
* NOTE THAT "DO FOREVER" IS JUST "DO WHILE" WITH NO CONDITION
*
do forever
*
*TEST HIGH ADDRESS BUTTON. IF IT IS BEING PRESSED, DEBOUNCE IT
* AND WAIT FOR THE OPERATOR TO RELEASE IT. THEN E N T E R HIGH
* ADDRF.SS FROM THE SWITCHES AND SHOW IT ON THE LIGHTS
*

if HIADDRDUTTON = 0 then
beg in
do while HIADDRBUTTON = 0
DELAY (DFBOUNCE TIME)
end
HIADDRESS = SWITCHES
LIGHTS = SWITCHES
end
*
*TEST LOW ADDRESS BUTTON. IF IT IS BEING PRESSED, DEBOUNCE IT AND
* WAIT FOR THE OPERATOR TO RELEASE IT. THEN ENTER LOW ADDRESS
* FROM THE SWITCHES AND SHOW IT ON THE LIGHTS
*

if LOADDRBUTTON = 0 then
beg in
do while LOADDRBUTTON 0
17-22 6809 Assembly Language Programming

DELAY (DEBOUNCE TIME)


end
LOADDRESS = SWITCHES
LIGHTS = SWITCHES
end
*
*TEST DATA BUTTON. IF IT IS BEING PRESSED, DEBOUNCE IT AND WAIT
* FOR THE OPERATOR TO RELEASE IT. THEN ENTER DATA FROM THE
* SWITCHES, SHOW IT ON THE LIGHTS, AND STORE IT IN MEMORY AT
* (HIGH ADDRESS, LOW ADDRESS)
*
if DATAAUTTON = 0 then
beg in
do while DATABUTTO� = 0
DELAY (DEBOUNCE TIME)
end
DATil = SWITCHES
LIGHTS = SWITCHI'S
(HIADDRESS, LOADORESS) = D'TI\
end

*WAIT THE DEBOUNCING TIME BEFORE EXAMINING THE BUTTONS AGAIN.


* THIS DELAY DEBOUNCES THE RELF.ASE FOR SURE
*
DELAY (DEBOUNCE TIME)
end
*

*THE LAST END ABOVE TERMINATES THE


* DO fOREVER LOOP
*

Structured programs are not easy to write, but they can give a great deal of insight
into the overall program logic. You can check the logic of the structured program by
hand before writing any actual code.

Structured Program for the Verification Terminal

Let us look at the keyboard entry for the transaction terminal. We will assume
that the display array is ENTRY, the keyboard strobe is KEYSTROBE, and the
keyboard data is KEY IN. The structured program without the function keys is:

NKEYS = 10
*
*CLEAR ENTRY TO START
*

do while NKEYS > 0


NKEYS = NKEYS - 1
ENTRY(NKEYS) = 0
end
*
*FETCH A COMPLETE ENTRY FROM KEYBOARD
*

do while NKEYS < 10


if KEYSTROBE = ACTIVE then
beg in
KEYSTROBE = INACTIVE
ENTRY(NKEYS) = KEYIN
NKEYS = NKEYS + 1
end
end

Adding the SEND key means that the program must ignore extra digits after it
has a complete entry, and must ignore the SEND key until it has a complete entry.
The structured program is:
NKEYS = 10
*
*CLEAR ENTRY TO START
*

do while NKEYS > 0


NKEYS = NKEYS - 1
Program Design 17-23

ENTRY(NKEYS) = 0
end
*
*WAIT FOR COMPLETE ENTRY FOLLOWED BY SEND KEY
*
do while KEY I SEND or NKEYS I 10
if KEYSTROBE = A�1IVE then
beg in
KEYSTROBE = INACTIVE
KEY = KEYIN
if NKEYS I 10 and KEY I SEND then
beg in
ENTRY(NKEYS) = KEY
NKEYS = NKEYS + l
end
end
end

Note the following features of this structured program.

1. The second if-then is nested within the first one, since the keys are only
entered after a strobe is recognized. If the second if-then were on the same
level as the first, a single key could fill the entry, since its value would be
entered into the array during each iteration of the do-while loop.
2. KEY need not be defined initially, since NKEYS is set to zero as part of the
clearing of the entry.

Adding the CLEAR key allows the program to clear the entry originally by
simulating the pressing of CLEAR; i.e., by setting NKEYS to 10 and KEY to CLEAR
before starting. The structured program must also only clear digits that have previously
been filled. The new structured program is:
*
* SIMULATE COMPLETE CLEARING
*
NKEYS = 10
KEY '" CLEAR
*
*WAIT FOR COMPLETE ENTRY AND SEND KEY
*
do while KEY I SEND or NKEYS I 10
*
*CLEAR WHOLE ENTRY IF CLEAR KEY STRUCK
*
if KEY '" CLEAR then
beg in
KEY = 0
do while NKEYS > 0
NKEYS = NKEYS - l
ENTRY(NKEYS) = 0
end
end
*
*GET DIGIT IF ENTRY INCOMPLETE

if KEYSTROBE = ACTIVE then


b�'J in
KEYSTROBE = INACTIVE
KEY '" KEYIN
if KEY < ln and NKEYS I 10 then
begin
ENTRY(NKEYS) = KEY
NKEYS = NKEYS + l
end
end
end

Note that the program resets KEY to zero after clearing the array, so that the operation
is not repeated.
17-24 6809 Assembly Language Programming

We can similarly build a structured program for the receive routine. An initial
program could just look for the header and trailer characters. We will assume that RSTB
is the indicator that a character is ready. The structured program is:
*
*CLEAR HEADER FLAG TO START
*

HFLAG = 0
*
* WAIT FOR HEADER AND TRAILER
*
do wh i 1e HFLAG 0 or CHAR I TRAILER
*
*GET CHARACTER IF READY. LOOK FOR HEADER
*

if RSTB = ACTIVE then


begin
RSTB = INACTIVE
CHAR = INPUT
if CHAR = HEADER then HFLAG 1
end
end

Now we can add the section that checks the message address against the three
digits in TERMINAL ADDRESS (TERMADDR). If any of the corresponding digits
are not equal, the ADDRESS MATCH flag (ADDRMATCH) is set to 1.
*
*CLEAR HEADER FLAG, ADDRESS MATCH FLAG, ADDRESS COUNTER TO START
*

HFLAG 0 =

ADDRMATCH = 0
ADDRCTR = 0
*
* WAIT FOR HEADER, DESTINATION ADDRESS, AND TRAILER
*

do while HFLAG = 0 or CHAR I TRAILER or ADDRCTR I 3


*
*GET CHARACTER IF READY
*

if RSTB =
ACTIVE then
beg in
RSTB INACTIVE
CHAR =
INPUT
end
*

* CHECK FOR TERMINAL ADDRESS AND HEADER


*
if HFLAG = 1 and ADDRCTR I 3 then
beg in
if CHAR I TERMADDR(ADDRCTR) then ADDRMATCH 1
ADDRCTR = ADDRCTR + 1
end
if CHAR = HEADER then HFLAG = l
end

The program must now wait for a header, a three-digit identification code, and a
trailer. You must be careful of what happens during the iteration when the program
finds the header, and of what happens if an erroneous identification code character is the
same as the trailer.
A further addition can store the message in MESSG. NMESS is the number of
characters in the message; if it is not zero at the end, the program knows that the ter­
minal has received a valid message. We have not tried to minimize the logic expres­
sions in this program.
*
*CLEAR FLAGS, COUNTERS TO START
*

HFLAG = 0
ADDRMATCH = 0
Program Design 17-25

ADDRCTR = 0
NMESS = 0
*
*WAIT FOR HEADER, DESTINATION ADDRESS, AND TRAILER
*
do while HFLAG = 0 or CHAR � TRAILER or ADDRCTR � 3
*
*GET CHARACTER IF READY
*
if RSTB = ACTIVE then
beg in
RSTB INACTIVE
CHAR = INPUT
end
*
*READ MESSAGE IF DESTINATION ADDRESS = TERMINAL ADDRESS
*

if HFLAG = l and ADDRCTR = 3 then


if ADDRMATCH = 0 and CHAR� TRAILER then
beg in
MESSG(NMESS) = CHAR
NMESS = NMESS + l
end
*
* CHECK FOR TERMINAL ADDRESS
*
if HFLAG = l an d ADDRCTR � 3 then
begin
if CHAR� TERMADDR(ADDRCTR) then ADDRMATCH 1
ADDRCTR ADDRCTR + l
end
*
*LOOK FOR HEADER
*

if CHAR = HEADER then HFLAG = l


end

The program checks for the identification code only if it found a header during a
previous iteration. It accepts the message only if it has previously found a header and a
complete, matching destination address. The program must work properly during the
iterations when it finds the header, the trailer and the last digit of the destination
address. It must not try to match the header with the terminal address or place the trailer
or the final digit of the destination address in the message. You might try adding the
rest of the logic from the flowchart (Figure 17-7) to the structured program. Note that
the order of operations is often critical. You must be sure that the program does not
complete one phase and start the next one during the same iteration.

REVIEW OF STRUCTURED PROGRAMMING

Structured programming brings discipline to program design. It forces you to


limit the types of structures you use and the sequence of operations. It provides
single-entry, single-exit structures, which you can check for logical accuracy. Struc ·

tured programming often makes the designer aware of inconsistencies or possible


combinations of inputs. Structured programming is not a cure-all, but it does bring
some order into a process that can be chaotic. The structured program should also aid
in debugging, testing, and documentation.
Structured programming is not simple. The programmer must not only define
the problem adequately, but must also work through the logic carefully. This is
tedious and difficult, but it results in a clearly written, working program.
17-26 6809 Assembly Language Programming

Terminators

The particular structures we have presented are not ideal and are often awk­
ward. In addition, it can be difficult to determine where one structure ends and
another begins, particularly if they are nested. Theorists may provide better struc­
tures in the future, or designers may wish to add some of their own. A terminator for
each structure seems necessary, since indenting does not always clarify the situation.
"End" is a logical terminator for the "do-while" loop. There is no obvious terminator,
however, for the "if-then-else" statement; some theorists have suggested "endif' or
"fi" ("if' backwards), but these are both awkward and detract from the readability of
the program.

RULES FOR STRUCTURED PROGRAMMING

We suggest the following rules for applying structured programming:

1. Begin by writing a basic flowchart to help define the logic of the program.
2. Start with the "sequential," "if-then-else," and "do-while" structures.
They are known to be a complete set, i.e., any program can be written in
terms of these structures.

3. Indent each level a few spaces from the previous level, so that you will know
which statements belong where.

4. Use terminators for each structure: e.g., "end" for the "do-while" and
"endif' or "fi" for the "if-then-else." The terminators plus the indentation
should make the program reasonably clear.

5. Emphasize simplicity and readability. Leave lots of spaces, use meaningful


names, and make expressions as clear as possible. Do not try to minimize the
logic at the cost of clarity.
6. Comment the program in an organized manner.

7. Check the logic. Try all the extreme cases or special conditions and a few
sample cases. Any logical errors you find at this level will not plague you later.

TOP-DOWN DESIGN

The remaining problem is how to check and integrate modules or structures.


Certainly we want to divide a large task into sub-tasks. But how do we check the sub­
tasks in isolation and put them together? The standard procedure, called "bottom-up
design," requires extra work in testing and debugging and leaves the entire integra­
tion task to the end. What we need is a method that allows testing and debugging in
.: . .:a . . u«i _p ..... �ram cnvironmc;.� �11d moduL.: :Lcs system it�tegration.
This method is "top-down design." Here we start by writing the overall super­
visor program. We replace the undefined sub-programs by program "stubs," tempor­
---Y prv,., ... , ..• s tha: ... . _:::.n ;-,·.-::r,rd th( �nt..-;, •. ·r. ide���- .::r.:,wrr to a .,t:�·ctt.: test
problem, or do nothing. We then test the supervisor program to see that its logic is
correct.
Program Design 17-27

We proceed by expanding the stubs. Each stub will often contain sub-tasks,
which we will temporarily represent as stubs. This process of expansion, debugging,
and testing continues until all the stubs are replaced by working programs. Note that
testing and integration occur at each level, rather than all at the end. No special driver or
data generation programs are necessary. We get a clear idea of exactly where we are in
the design. Top-down design assumes modular programming, and is compatible with
structured programming as well.

DISADVANTAGES OF TOP-DOWN DESIGN

The disadvantages of top-down design are:

1. The overall design may not mesh well with system hardware.

2. It may not take good advantage of existing software.

3. Stubs may be difficult to write, particularly if they must work correctly in


several different places.

4. Top-down design may not result in generally useful modules.

5. Errors at the top level can have catastrophic effects, whereas errors in bottom­
up design are usually limited to a particular module.

In large programming projects, top-down design has been shown to greatly


improve programmer productivity. However, almost all of these projects have used
some bottom-up design in cases where the top-down method would have resulted in a
large amount of extra work.
Top-down design is a useful tool that should not be followed to extremes. It pro­
vides the same discipline for system testing and integration that structured program­
ming provides for module design. The method, however, has more general
applicability, since it does not assume the use of programmed logic. However, top­
down design may not result in the most efficient implementation.

EXAMPLES

Top-Down Design of Switch and Light System

The first structured programming example actually demonstrates top-down


design as well. The program was:
SWITCH = OFF
do while SWITCH OFF
READ SWITCH
end
LIGHT ON
DELAY l
LIGHT = OFF

These statements are really stubs, since none of them is fully defined. For example,
what does READ SWITCH mean? If the switch were one bit of input port SPORT, it
really means:
SWITCH = SPORT and SMASK

where SMASK has a 'I' bit in the appropriate position. The masking may, of course, be
implemented with a Bit Test instruction.
17-28 6809 Assembly Language Programming

Similarly, DELAY 1 actually means (if the processor itself provides the delay):
REG = COUNT
do while REG � 0
REG = REG - l
end

COUNT is the appropriate number to provide a one-second delay. The expanded ver­
sion of the program is:
SWITCH = 0
do while SWITCH = 0
SWITCH = SPORT and MASK
end
LIGHT = ON
REF = COUNT
do while REG � 0
REG REG - l
end
LIGHT = not (LIGHT)

Certainly this program is more explicit, and could more easily be translated into
actual instructions or statements.

Top-Down Design of the Switch-Based Memory Loader

This example is more complex than the first example, so we must proceed
systematically. Here again, the structured program contains stubs.
For example, if the HIGH ADDRESS button is one bit of input port CPORT, "if
HIADDRBUTTON = 0 " really means:

1. Input from CPORT


2. Logical AND with HAMASK

where HAMASK has a '1' in the appropriate bit position and ' 0 's elsewhere. Similarly
the condition "if OAT ABUTTON = 0 " really means:

1. Input from CPORT


2. Logical AND with DAMASK

So, the initial stubs could just assume that no buttons are being pressed:
HIADDRBUTTON l
LOADDRBUTTON = l
DATABUTTON = 1

A run of the supervisor program should show that it takes the implied "else" path
through the "if-then-else" structures, and never reads the switches. Similarly, if the
stub were:
HIADDRBUTTON = 0

the supervisor program should stay in the "do while HIADDRBUTTON = 0" loop
waiting for the button to be released. These simple runs check the overall logic.
Now we can expand each stub and see if the expansion produces a reasonable
overall result. Note how debugging and testing proceed in a straightforward and
modular manner. We expand the HIADDRBUTTON =0 stub to:

READ CPORT
HIADDRBUTTON = (CPORT) and HAMASK

The program should wait for the HIGH ADDRESS button to be released. The
program should then display the values of the switches on the lights. This run checks for
the proper response to the HIGH ADDRESS button.
Program Design 17-29

Keyboard

ACK = 0

No

Transmit
Display
Receive

Figure 17-13. Initial Flowchart of Transaction Terminal

We then expand the LOW ADDRESS button module to:


READ CPORT
LOADDR�UTTON = (CPORT) and LAMASK

When the LOW ADDRESS button is released, the program should display the
values of the switches on the lights. This run checks for the proper response to the LOW
ADDRESS button.
Similarly, we can expand the DATA button module and check for the proper
response to that button. The entire program will then have )een tested.
When all the stubs have been expanded, the coding, debugging, and testing
stages will all be complete. Of course, we must know exactly what results each stub
should produce. However, many logical errors will become obvious at each level with­
out any further expansion.

Top-Down Design of Verification Terminal

This example, of course, will have more levels of detail. We could start with the
following program (see Figure 17-13 for a flowchart):
KEYBOARD
ACK =0
do while ACK = 0
TRANSMIT
RECEIVE
end
DISPLAY
17-30 6809 Assembly Language Programming

Here, KEYBOARD, TRANSMIT, RECEIVE, and DISPLAY are program stubs


that will be expanded later. KEYBOARD, for example, could simply place a ten-digit
verified number into the appropriate buffer.
The next stage of expansion could produce the following program for
KEYBOARD (see Figure 17-14):
VER 0 =

do while VER 0 =

COMPLETE 0=

do while COMPLETE 0
KEY IN
KEYDS
end
VERIFY
end

Here VER=O means that an entry has not been verified; COMPLETE=O means
that the entry is incomplete. KEYIN and KEYDS are the keyboard input and display
routines respectively. VERIFY checks the entry. A stub for KEYIN would simply place
a random entry (from a random number table or generator) into the buffer and set
COMPLETE to 1.

VER = 0

No

End
Complete= 0

Yes

KEVIN
Verify
KEYDS

Figure 17-14. Flowchart for Expanded KEYBOARD Routine


Program Design 17-31

We would continue by similarly expanding, debugging, and testing


TRANSMIT, RECEIVE, and DISPLAY. Note that you should expand each program
by one level so that you do not perform the integration of an entire program at any one
time. You must use your judgment in defining levels. Too small a step wastes time,
while too large a step gets you back to the problems of system integration that top­
down design is supposed to solve.

REVIEW OF TOP-DOWN DESIGN

Top-down design brings discipline to the testing and integration stages of pro­
gram design. It provides a systematic method for expanding a flowchart or problem
definition to the level required to actually write a program. Together with structured
programming, it forms a complete set of design techniques.
Like structured programming, top-down design is not simple. The designer
must have defined the problem carefully and must work systematically through each
level. Here again, the methodology may seem tedious, but the payoff can be substan­
tial if you follow the rules.
We recommend the following approach to top-down design:

1. Start with a basic flowchart.


2. Make the stubs as complete and as separate as possible.
3. Define precisely all the possible outcomes from each stub and select a test set.
4. Check each level carefully and systematically.
5. Use the structures from structured programming.
6. Expand each stub by one level. Do not try to do too much in one step.
7. Watch carefully for common tasks and data structures.
8. Test and debug after each stub expansion. Do not try to do an entire level at a
time.

9. Be aware of what the hardware can do. Do not hesitate to stop and do a little
bottom-up design where that seems necessary.

DESIGNING DATA STRUCTURES

Beginning programmers seldom think about data structures. They generally


assume that the data will be stored somewhere in the computer's memory, much as
records are piled into a cabinet or books into a bookcase. Designing data structures
seems as far-fetched as establishing a complete card catalog for one's books or records;
few people take organization to such lengths.
But the fact is that most computer-based systems involve a surprisingly large
amount of data processing. Numerical algorithms assume that the processor can easily
find the element in the next row or next column of an array. Editor programs assume
that the processor can easily find the next character, the previous line, a particular string
of characters, or the starting point of an entire paragraph or page. An operator interface
for a piece of test equipment may assume that the processor can easily find a particular
command or data entry and move it from one place to another. Imagine how difficult
17-32 6809 Assembly Language Programming

the following tasks would be to implement if the data is simply scattered through
memory or organized in a long, linear array:

1. The operator of a machine tool wants to insert two extra cutting steps between
steps 14 and 15 of a 40-step pattern.
2. The operator of a chemical processing plant wants to see the last ten values of
the temperature at the inlet to tank #5.
3. An accounting clerk wants to enter a new account into an alphabetical list.

The processor may spend most of its time finding the data, moving from one
data item to the next, and organizing the data.

SELECTING DATA STRUCTURES

Obviously, we cannot provide a complete description of data structures here.4.5


Just as clearly, the design of data structures has great influence on the design of pro­
grams if the data is complex. We will briefly mention the following considerations in
selecting data structures:

1. How are the data items related? Closely related items should be accessible
from each other, since such accesses will be frequent.
2. What kind of operations will be performed on the data? Simple linear struc­
tures are adequate if the data is always handled in a single, fixed order.
However, more complex structures are essential if the tasks involve opera­
tions such as searching, editing, or sorting.
3. Can standard structures be used? Methods are readily available for handling
structures such as queues, stacks, and linked lists. Other arrangements will
require special programming.
4. What kind of access is necessary? Clearly we need more structure if we must
find elements that are identified by a number or a relative position, rather
than just the first or last entries. We must organize the data to make the
accesses as rapid as possible.

REVIEW OF PROBLEM DEFINITION AND


PROGRAM DESIGN

You should note that we have spent two entire chapters without mentioning any
specific microprocessor or assembly language, and without writing a single line of actual
code. However, you should now know a lot more about the examples than you would if
we had just asked you to write the programs at the start. Although we often think of the
writing of computer instructions as a key part of software development, it is actually
one of the easiest stages.
Once you have written a few programs, coding will become simple. You will
soon learn the instruction set, recognize which instructions are really useful, and
remember the common sequences that make up the largest part of most programs. You
Program Design 17-33

will then find that many of the other stages of software development remain difficult
and have few clear rules.
We have suggested some ways to systematize the important early stages. In the
problem definition stage, you must define all the characteristics of the system - its
inputs, outputs, processing, time and memory constraints, and error handling. You
must particularly consider how the system will interact with the larger system of
which it is a part, and whether that larger system includes electrical equipment,
mechanical equipment, or a human operator. You must start at this stage to make
the system easy to use and maintain.
In the program design stage, several techniques can help you to systematically
specify and document the logic of your program. Modular programming forces you to
divide the total program into small, distinct modules. Structured programming pro­
vides a systematic way of defining the logic of those modules, while top-down design
is a systematic method for �ntegrating and testing them. Of course, no one can compel
you to follow all of these techniques; they are, in fact, guidelines more than anything
else. But they do provide a unified aproach to design, and you should consider them a
basis on which to develop your own approach.

REFERENCES

1. D. L. Parnas (see the references below) has been a leader in the area of modular
programming.
2. Collected by B. W. Unger (see reference below).
3. Formulated by D. L. Parnas.
4. K. J. Thurber. and P. C. Patton. Data Structures and Computer Architecture, Lex­
ington Books, Lexington, Mass., 1977.
5. K. S. Shankar...Data Structures, Types, and Abstractions,'' Computer, April 1980,
pp. 67-77.

The following references provide additional information on problem definition and pro­
gram design:
Chapin, N. Flowcharts, Auerbach, Princeton, N.J., 1971.
Dalton, W. F. "Design Microcomputer Software like Other Systems -
Systematically," Electronics, January 19, 1978, pp. 97-101.
Dijkstra, E. W. A Discipline of Programming, Prentice-Hall, Englewood Cliffs, N.J.,
1976.
Halstead, M. H. Elements ojSoftwareScience, American Elsevier, New York, 1977.
Hughes, J. K. and J. I. Michtom. A Structured Approach to Programming, Prentice­
Hall, Englewood Cliffs, N.J., 1977.
Morgan, D. E. and D.J. Taylor." A Survey of Methods for Achieving Reliable Soft­
ware," Computer, February 1977, pp. 44-52.
Myers, W. "The Need for Software Engineering," Computer, February 1978, pp.
12-25.
Parnas, D. L. "On the Criteria to be Used in Decomposing Systems into Modules,"
Communications of the ACM, December 1972, pp. 1053-58.
17-34 6809 Assembly Language Programming

Parnas, D. L. "A Technique for the Specification of Software Modules with Exam­
ples," Communications of the ACM, May 1973, pp. 330-336.
Phister, M.Jr. Data Processing Technology and Economics, Santa Monica Publishing
Co., Santa Monica, Ca., 1976.
Schneider, V. "Prediction of Software Effort and Project Duration - Four New
Formulas," SJGPLAN Notices, June 1978, pp. 49-59.
Schneiderman, B. et al. "Experimental Investigations of the Utility of Detailed
Flowcharts in Programming," Communications of the ACM, June 1977, pp. 373-
381.
Tausworthe, R. C. Standardized Development of Computer Software, Prentice-Hall,
Englewood Cliffs, N.J., 1977 (Part 1); 1979 (Part 2).
Unger, B. W. "Programming Languages for Computer System Simulation,"
Simulation, April 1978, pp. 101-10.
Wirth, N. Algorithms + Data Structures = Programs, Prentice-Hall, Englewood
Cliffs, N.J., 1976.
Wirth, N. Systematic Programming: an Introduction, Prentice-Hall, Englewood Cliffs,
N.J., 1973.
Yourdon, E. U. Techniques of Program Structure and Design, Prentice-Hall,
Englewood Cliffs, N.J., 1975.
18
Documentation

Software development must yield more than just a working program. A soft­
ware product must also include the documentation that allows it to be used, main­
tained, and extended. Adequate documentation is helpful during program debugging
and testing, and essential in the later stages of the program's life cycle.

SELF-DOCUMENTING PROGRAMS

Although no program is ever completely self-documenting, some of the rules


that we mentioned earlier can help. These include:

Clear, simple, structure with as few transfers of control (jumps) as possible


Use of meaningful names and labels
Use of names for 110 devices, parameters, numerical factors, subroutines,
branch destinations, etc.
Emphasis on simplicity rather than on minor savings in memory usage, execu­
tion time, or typing

For example, the following program sends a string of characters to a


teletypewriter:
LDB $40
LDX #$1000
w LDA ,X+
STA $8008
JSR XXX
DECB
BNE w
SWI
18-2 6809 Assem hly Language Programming

CHOOSING USEFUL NAMES

Even without comments we can improve the program as follows:

COUNT EQU $40


MESSG EQU $1000
TTY PIA EQU $8008
L DB COUNT
LDX #MESSG
OUTCH LDA ,X+
STA TTY PIA
JSR BITDLY
DECB
BNE OUTCH
SWI

This program is undoubtedly easier to understand than the earlier version. Even
without further documentation, you could probably guess at the function of the pro­
gram and the meanings of most of the variables. Other documentation techniques can­
not substitute for self-documentation.
Some further notes on choosing names:

1. Use the obvious name when it is available, like TTY or CRT for output
devices, START or RESET for addresses, DELAY or SORT for subroutines,
COUNT or LENGTH for data.

2. Avoid acronyms like S 16BA for SORT 16-BIT ARRAY. These seldom
mean anything to anybody.

3. Use full words or close to full words when possible, like DONE, PRINT,
SEND, etc.

4. Keep the names as distinct as possible. Avoid names that look alike, such as
TEMPI and TEMP I, or resemble operation codes or other built-in names.

COMMENTS

Comments are a simple form in which to provide additional documentation.


However, few programs (even those used as examples in books) have effective com­
ments. You should consider the following guidelines for good comments:

1. Don't explain the internal effects of the instruction. Instead, explain the
purpose of the instruction in the program. Comments like
DECB B = B - 1

do not help the reader understand the program. A more useful comment is
DECB LINE NUMBER = LINE NUMBER - l

Remember that the standard manuals contain descriptions of how the pro­
cessor executes its instructions. The comments should explain what tasks
the program is performing and what methods it is using.

2. Make the comments as clear as possible. Do not use abbreviations or


acronyms unless they are well-known (like ASCII, PIA, or UART) or stan­
dard (like no for number, ms for millisecond, etc.) Avoid comments like

DECB LN = LN - l
or
DECB DEC. LN BY 1

The extra typing is certainly worthwhile.


Documentation 18-3

3. Comment every important or obscure point. Be particularly careful to mark


operations that may not have obvious functions, such as

ANDA �%00100000 TURN OFF TAPE READER

or
LDA li,X GET SEVEN-SEGMENT CODE FROM TABLE

Clearly, 1/0 operations often require extensive comments. If you're not


exactly sure what an instruction does, or if you have to think about it, add a
clarifying comment. The comment will save you time later and will be help­
ful in documentation.

4. Don't comment the obvious- A comment on each line makes it difficult


to find the important points. Standard sequences like
DECB
BNE SEARCH

need not be marked unless you're doing something special. One comment
will often suffice for several lines, as in

LSRA GET MOST SIGNIFICANT DIGIT


LSRA
LSRA
LSRA

LOA $40 EXCHANGE MOST SIGNIFICANT, LEAST


LOB $41 SIGNIFICANT BYTES
STA $41
STB $40

5. Place comments on the lines to which they refer or at the start of a


sequence.
6. Keep your comments up-to-date. If you change the program, change the
comments.

7. Use standard forms and terms in commenting. Don't worry about


repetitiveness. Varied names for the same things are confusing, even if the
variations are just COUNT and COUNTER, START and BEGIN, DIS­
PLAY and LEOS, or PANEL and SWITCHES. You gain nothing from
inconsistency. Minor variations may be obvious to you now, but may not be
clear later; others will get confused immediately.

8. Make comments mingled with instructions brief. Leave a complete


explanation to header comments and other documentation. Otherwise the
program gets lost in the comments and you may have a hard time even find­
ing the actual instructions.

9. Keep improving your comments. If you come to one that you cannot read or
understand, take the time to change it. If you find that the listing is getting
crowded, add some blank lines. The comments won't improve themselves;
in fact, they will just become worse as you leave the task behind and forget
exactly what you did.

10. Use comments to place a heading in front of every maj or section, subsec­
tion, or subroutine. The heading should describe the functions of the code
that follows it; it should include information about the algorithm employed,
the inputs and outputs, and any incidental effects that may be produced.

11. If you modify a working program, use comments to describe the modifica­
tions that you made and identify the date and author of the revision. This
18-4 6809 Assembly Language Programming

information should go both at the front of the program (so a user can easily
tell one version from another) and at the points where changes were actually
made.

Remember, comments are important. Good ones will save you time and effort.
Put some work into comments and try to make them effective.

EXAMPLES

18-1. COMMENTING A MULTIPLE-PRECISION ADDITION


ROUTINE

The basic program is:


LOB $40
LOX #$41
LOY #$51
ANDCC Ull111110
ADBYTE LOA ,X
ADCA , Y+
STA ,X+
DECB
BNE ADBYTE
SWI

Important Points

First, comment the important points. These are typically intializations, data
fetches, and processing operations. Don't bother with standard sequences like updat­
ing pointers and counters. Remember that names are clearer than numbers, so use
them freely.
The new version of the program is:

*
*THE FOLLOWING PROGRAM PERFORMS MULTI-BYTE BINARY ADDITION
*
* INPUTS: LOCATION 0040 CONTAINS LENGTH OF NUMBERS IN BYTES
* LOCATIONS 0041 ON CONTAIN ONE OPERAND STARTING WITH LSB'S
* LOCATIONS 0051 ON CONTAIN ONE OPERAND STARTING WITH LSB'S
*
* OUTPUTS: LOCATIONS 0041 ON CONTAIN SUM STARTING WITH LSB'S
*
LENGTH EQU $40
OPER1 EQU $41
OPER2 EQU $51
LOB LENGTH COUNT LENGTH OF NUMBERS IN BYTES
=

LOX #0PER1 POINT TO LSB'S OF FIRST OPERAND, SUM


LOY #0PER2 POINT TO LSB'S OF SECOND OPERAND
ANDCC #%11111110
ADBYTE LOA ,X GET A BYTE FROM FIRST OPERAND
AOCA ,Y+ ADD A BYTE FROM SECOND OPERAND
STA ,X+ STORE SUM OVER FIRST OPERAND
DECB
BNE ADBYTE
SWI

Obscure Functions

Second, look for instructions that may not have obvious functions and explain
their purposes with comments. Here, the purpose of ANDCC:#=%11111110 (the 6800
operation code CLC is surely easier to understand) is to clear the Carry flag before
adding the least significant bytes.
Documentation 18-5

Questions for Commenting

Third, ask yourself whether the comments tell you what you would need to
know to use the program; for example:

1. Where is the program entered? Are there alternative entry points?

2. What parameters are necessary? How and in what form must they be sup-
plied?

3. What operations does the program perform?

4. From where does it get the data?

5. Where does it store the results?

6. What special cases does it consider?

7. What does the program do about errors?

8. How does it exit?

Some questions may be irrelevant and some answers may be obvious. Make sure,
however, that you wouldn't have to dissect the program to answer the important
questions. Remember also that too much explanation may be an obstacle to using the
program. Are there any changes you would like to see in the listing? If so, make
them - you are the one who has to decide if the commenting is adequate and reasona­
ble.
*
*THE FOLLOWING PROGRAM PERFORMS MULTI-BYTE BINARY ADDITION
*
* INPUTS: LOCATION 0040 CONTAINS LENGTH OF NUMBERS IN BYTES
* LOCATIONS 0041 ON CONTAIN ONE OPERAND STARTING WITH LSB'S
* LOCATIONS 0051 ON CONTAIN ONE OPERAND STARTING WITH LSB'S
* OUTPUTS: LOCATIONS 0041 ON CONTAIN SUM STARTING WITH LSB'S
*
LENGTH EQU $40 LENGTH OF NUMBERS IN BYTES
OPERl EQU $41 LSB'S OF ONE OPERAND AND SUM
OPER2 EQU $51 LSB'S OF OTHER OPERAND
LOB LENGTH COUNT = LENGTH OF NUMBERS IN BYTES
LOX #OPERl POINT TO LSB'S OF
FIRST OPERAND, SUM
LOY #OPER2 POINT TO LSB'S OF SECOND OPERAND
ANDCC #%11111110 CLEAR CARRY FOR ADDITION OF LSB'S
ADBYTE LOA 'X GET A BYTE FROM FIRST OPERAND
ADCA ,Y+ ADD A BYTE FROM SECOND OPERAND
STA ,X+ STORE SUM OVER FIRST OPERAND
DECB
BNE ADBYTE CONTINUE UNTIL ALL BYTES ADDED
SWI

18-2. COMMENTING A TELETYPEWRITER OUTPUT


ROUTINE

The basic program is:

LOA $flO
ASLA
LOB #11
TBIT STA $8008
JSR BITDLY
RORA
ORCC fl%00000001
DECB
BNE TBIT
SWI
18-6 6809 Assembly Language Programming

Commenting the important points and adding names gives:


*
*TELETYPEWRITER OUTPUT PROGRAM
*
*THIS PROGRAM SENDS THE CONTENTS OF MEMORY LOCATION 00�0 TO THE
TELETYPEWRITER
*

* INPUTS: CHARACTER TO BE TRANSMITTED IN MEMORY LOCATION 0060


* OUTPUTS: NONE
*
NBITS EQU 11 NUMBER OF BITS PER CHARACTER
TDATA EQU $60 ADDRESS OF CHARACTER TO BE TRANSMITTED
TTYPIA EQU $8008 TELETYPEWRITER OUTPUT DATA PORT
LOA TDATA GET DATA
ASLA SHIFT DATA LEFT AND FORM START BIT
LOB INBITS COUNT = NUMBER OF BITS IN CHARACTER
TBIT STA TTYPIA SEND A BIT TO TELETYPEWRITER
JSR BITDLY WAIT 1 BIT T I ME
RORA GET NEXT BIT
ORCC #%00000001 SET CARRY TO FORM STOP BITS
DECB
BNE TBIT COUNT BITS
SWI

Changing the Program

Note how easily we could change this program so that it would transfer a whole
string of data, starting at the address in locations BUFPTR and BUFPTR +land ending
with an "03" character (ASCII ETX). Furthermore, let us make the terminal a 30
character per second device with one stop bit (we will have to change subroutine
BITDL Y). Try making the changes before looking at the listing.

*
* STRING OUTPUT PROGRAM
*
*TERMIN/\L
*TRANSMISSION CEASES WHEN AN ASCII ETX IS ENCOU�TERED

*INPUTS: MEMORY LOCATIONS 00�0 /\NO 00�1 CONTAIN STARTING ADDRESS


* OF STRING TO BE TRANSMITTED

* OUTPUTS: NONE
*
BUFPTR EQU $60 STARTING ADDRESS OF OUTPUT DATA BUFFER
ENOCH EQU $03 ENDING CHARACTER = ASCII ETX
NBITS EQU 10 NUMBER OF BITS PER CHARACTER
TRMPIA EQU $8008 TERMINAL OUTPUT DATA PORT
LDX BUFPTR GET STARTING ADDRESS OF OUTPUT BUFFER
TCHAR LOA ,X+ GET A CHARACTER ·FROM THE BUFFER
CMPA tENDCH IS IT THE ENDING CHARACTER?
BEQ DONE YES, DONE
ASLA NO, SHIFT IT LEFT TO FORM A START BIT
LOB tNBITS COUNT = NUMBER OF BITS IN CHARACTER
TBIT STA TRMPIA SEND A BIT TO THE TERMINAL
JSR BITDLY
RORA GET NEXT BIT
ORCC #%00000001 SET CARRY TO FORM STOP BIT
DECB
BNE TBIT COUNT BITS
BRA TCHAR
DONE SWI

Good comments will help you change a program to meet new requirements. For
example, try changing the last program so that it:

Starts each message with ASCJJ STX (02) followed by a three-digit identifica­
tion code stored in memory locations JDCODE through JDCODE + 2.
Documentation 18-7

Adds no start or stop bits

Waits 1 ms between bits

Transmits 40 characters, starting with the one located at the address in DPTR
and DPTR + 1.

Ends each message with two consecutive ASCII ETXs (03)

FLOWCHARTS AS DOCUMENTATION

We have already described the use of flowcharts as a design tool in Chapter 17.
Flowcharts are also useful in documentation, particularly if:

They are not cluttered or too detailed.

Their decision points are explained and marked clearly.


They include all branches.

They correspond to the actual program listings.

Flowcharts are helpful if they give you an overall picture of the program. They are not
helpful if they are just as difficult to read as the program listing.

STRUCTURED PROGRAMS AS DOCUMENTATION

A structured program can serve as documentation for an assembly language pro­


gram if:

You describe the purpose of each section in the comments.

You make it clear which statements are included in each conditional or loop
structure by using indentation and ending markers.

You make the total structure as simple as possible.

You use a consistent, well-defined language.

The structured program can help you check the logic or improve it. Further­
more, since the structured program is machine-independent, it can also help you
implement the same task on another computer.

MEMORY MAPS

A memory map is simply a list of all the memory assignments in a program.


The map allows you to determine the amount of memory needed, the locations of data
or subroutines, and the parts of memory not allocated. The map is a handy reference for
finding storage locations and entry points and for dividing memory between different
routines or programmers. The map will also give you easy access to data and subroutines
if you need them in later extensions or in maintenance. Sometimes a graphical map is
more helpful than a listing.
18-8 6809 Assembly Language Programming

A typical map is:

Program Memory

Add ress Routine Purpose

EOOO-E1 FF RDKBD Interrupt Service Routine for Keyboard


E200- E240 BRKPT Breakpoint Routine Entered Via Software Interrupt
E241 -E250 DELAY Generalized Delay Program
E251 -E270 DSPLY Control Program for Operator Displays
E271 - E3EF SUPER Main Supervisor Program
E3FO - E3FF Interrupt and Reset Vectors

Data Memory

Address Name Purpose

0000 NKEYS Number of Keys Pressed by Operator


0001 - 0002 KBPTR Keyboard Buffer Pointer
0003-0041 KBUFFR Keyboard Buffer
0042-0050 DBUFFR Display Buffer
0051 - 006F TEMP Miscellaneous Temporary Storage
0070- OOFF STACK Hardware Stack

The map may also list additional entry points and include a specific description
of the unused parts of memory.

PARAMETER AND DEFINITION LISTS

Parameter and definition lists at the start of the main program and each
subroutine make understanding and changing the program far simpler. The following
rules can help.

1. Separate RAM locations, 1/0 units, parameters, definitions, and fixed


memory addresses.

2. Arrange lists alphabetically when possible, with a description of each


entry.
3. Give each parameter that might change a name and include it in the lists.
Such parameters may include time constants, inputs or codes corresponding
to particular keys or functions, control or masking patterns, starting or ending
characters, thresholds, etc.
4. List fixed memory addresses separately. These may include Reset and inter­
rupt service addresses, the starting address of the program, RAM areas, Stack
areas, etc.
5. Give each port used by an 1/0 device a name, even though devices may
share ports in the current system. The separation will make it easier for you to
expand or change the J/0 section.
Documentation 18-9

A typical list of definitions is:


*
* MEMORY SYSTEM CONSTANTS
*

FRQSRV EQU $El00 SERVICE ADDRESS FOR FAST INTERRUPT


IRQSRV EQU $E200 SERVICE ADDRESS FOR REGULAR INTERRUPT
RAMST EQU 0 STARTING ADDRESS FOR TEMPORARY STORAGE
RESET EQU $ E300 RESET ADDRESS
STKPTR EQU $0180 STARTING ADDRESS FOR HARDWARE STACK
*
*I/0 UNITS
*
DSPLAY EQU $8006 OUTPUT PIA FOR DISPLAYS
KBDIN EQU $8004 INPUT PIA FOR K8YBOARD
KBDOUT EQU $8006 OUTPUT PIA FOR KEYBOARD
TTYPIA EQU $8008 DATA PORT FOR TTY
*
•RAM STOR.ll.Gf.
*

ORG RAMST TEMPORARY DATA STORAGE AREA


NKEYS RMB 1 NUMBER OF KEYS
KPTR RMB 2 KEYBOARD BUFFER POINTER
KBFR RMB $40 KEYBOARD INPUT BUFFER
DISBFR RMB $10 DISPLAY OUTPUT BUFFER
TEMP RMB $14 TEMPORARY DATA STORAGE
*
*PARAMETERS
*

BOUNCE EQU 2 DEBOUNCING TIME IN MS


GOKEY EQU 10 IDENTIFICATION NUMBER FOR 'GO' KEY
MSCNT EQU $7A COUNT FOR 1 MS DELAY
OPEN EQU $OF INPUT PATTERN WHEN NO KEYS ARE PRESSED
TPULS EQU 1 PULSE LENGTH FOR DISPLAYS IN MS
*
*DEFINITIONS
*
ALLHI EQU $FF ALL ONES INPUT
STCON EQU $80 OUTPUT FOR START OF CONVERSION PULSE

Of course, the RAM entries will usually not be in alphabetical order, since the
designer must order these to minimize the number of address changes required in the
program.

LIBRARY ROUTINES

Standard documentation of subroutines helps you build a library of programs


that are easy to use. If you describe each subroutine with a standard form, anyone can
see at a glance what the routines do and how to use them. You should organize the
forms carefully, dividing them, for example, by processor, language, and type of pro­
gram. Remember, without proper documentation and organization, using the library
may be more difficult than writing programs from scratch. If you are going to use
subroutines from a library or other outside source, you must know all their effects in
order to debug your overall program.

STANDARD PROGRAM LIBRARY FORMS

Among the information that you will need in the standard form is:

Purpose of the program


18-10 6809 Assembly Language Programming

Processor used
Language used
Parameters required and how they are passed to the subroutine
Results produced and how they are passed to the main program
Number of bytes of memory used
Number of clock cycles required. This number may be an average or a typical
figure, or it may vary widely. Actual execution time will, of course, depend on
the processor clock rate and the memory cycle time.
Registers affected
Flags affected
A typical example
Error handling
Special cases
Documented program listing

If the program is complex, the standard library form should also include a
general flowchart or a structured outline of the program. As we have mentioned
before, a library program is most likely to be useful if it performs a single function in
a general manner.

18-3. SUM OF DATA/LIBRARY ROUTINE

Purpose: The program SUM8 computes the sum of a set of 8-bit unsigned binary num­
bers.

language: 6809 Assembler

Initial Conditions: Starting address of set of numbers in Index Register X, length of


set in Accumulator B.

Final Conditions: Sum in Accumulator A.

Requirements:

Memory - 7 bytes
Time - 7 + 11 N clock cycles, where N is the length of the set of numbers.
Registers- A,B,X
All flags affected

Typical Case: (all data in hexadecimal)


Start:
(X) 0050 Starting address
(8) 03 Length of set
(0050) 27 Data items
(0051) 3E
(0052) 26
End:
(A) 88 Sum

Error Handling: Program ignores all carries. Carry flag reflects only the result of the last
operation. Initial contents of Accumulator B must be 1 or more.
Documentation 18-11

Listing:

* SUM OF A SET OF 8-BIT DATA TTEMS


*

SUM8 CLRA CLEAR SUM TO START


ADBYTE ADDA ,X+ ADD AN ELEMENT TO THE SUM
DECB
BNE ADBYTE
RTS

18-4: DECIMAL TO SEVEN SEGMENT


CONVERSION/LIBRARY ROUTINE

Purpose: The program SEVEN converts a binary-coded decimal number to a seven-seg­


ment display code.

Language: 6809 Assembler

Initial Conditions: Data in Accumulator A.

Final Conditions: Seven-segment code in Accumulator B.

Requirements:

Memory- 21 bytes, including the seven-segment code table (10 entries).


Time- 20 clock cycles if the data is valid, 12 if it is not.
Registers - A,B,X
All flags affected
Input data in Accumulator A is not changed.

Typical Case: (data in hexadecimal)

Start:
(A) 05 Decimal data

End:
(B) 60 Seven-segment representation of input data

Error Handling: Program returns zero in Accumulator B if the data is not a decimal digit.

Listing:
*
*DECIMAL TO SEVEN-SEGMENT CODE CONVERSION
*

SEVEN CLRB GET ERROR CODE


CMPA #9 IS DATA A DECIMAL DIGIT?
BHI DONE NO, KEEP ERROR CODE AS RESULT
LDX #SSEG YES, GET SEVEN-SP.GMENT CODE FROM TABLf
LOB A,X
DONE RTS
SSEG FCB $3F,S05,S5B,$4F,$66
FCB $6D,$7D,S07,$7F,$6F

18-5. DECIMAL SUM/LIBRARY ROUTINE

Purpose: The program DECSUM adds two multi-digit decimal (BCD) numbers with
digits packed two to a byte.

Language: 6809 Assembler


18-12 6809 Assembly Language Programming

Initial Conditions: Address of LSD's of one operand (and sum) in Index Register X,
address of LSD's of other operand in Index Register Y. Length of
numbers (in bytes) in Accumulator B. Numbers arranged starting
with LSD's at lowest address.

Final Conditions: Sum replaces number with starting address in Index Register X.

Requirements:

Memory - 13 bytes
Time - 8 + 23N clock cycles, where N is the number of bytes.

Registers - A,B,X, Y
All flags affected - Carry shows if sum produced a carry.

Typical Case: (all data in hexadecimal)

Start:

(X) 0060 Address of LSD's of one operand and sum


(Y) 0050 Address of LSD's of other operand

(B) 02 Length of operands in bytes

(0060)
(0061)
�:} 5534 is first operand

(0050)
(0051) =
�� } 1588 is second operand

}
End:

(0060) = 22
(0061) = 71 7122 is decimal sum
Carry = 0

Error Handling: Program does not check the validity of decimal inputs. The contents
of Accumulator B must be 1 or more.

Listing:
*

*MUL TI-DIGIT DECIMAL (BCD) ADDITION


*

DECSUM ANDCC #%11111110 CLEAR CARRY TO START


ADDIGS LDA ,X GET TWO DIGITS OF FIRST OPERAND
ADCA I Y+ ADD TWO DIGITS OF SECOND OPERAND
DAA DECIMAL CORRECTION
STA ,X+ STORE SUM OVER FIRST OPERAND
DECB
BNE ADDIGS
RTS

TOTAL DOCUMENTATION

Complete documentation of microprocessor software will include all or most of


the elements that we have mentioned.

DOCUMENTATION PACKAGE

The total documentation package may involve:


General flowcharts
Documentation 18-13

A written description of the program


A list of all parameters and definitions

A memory map

A documented listing of the program

A description of the test plan and test results

The documentation may also include:

Programmer's flowcharts
Data flowcharts

Structured programs

Even this package is sufficient only for non-production software. Production soft-
ware also requires the following documents:

Program Logic Manual

User's Guide

Maintenance Manual

Program Logic Manual

The program logic manual expands the written explanation provided with the
software. It should explain the system's design goals, algorithms, and tradeoffs, assum­
ing a reader who is competent technically but lacks detailed knowledge of the program.
It should provide a step-by-step guide to the operations of the program and it should
explain the data structures and their manipulation.

User's Guide

The User's Guide is the most important single piece of documentation. No mat­
ter how well-designed the system may be, it will not be useful if no one can understand
its operations or take advantage of its features. The User's Guide should explain
system features and their use, provide frequent examples that clarify the text, and
give tested step-by-step directions. The writing of User's Guides requires care and
objectivity, since the writer must be able to take an outsider's point of view.
One problem in writing User's Guides is the need to avoid overwhelming the
beginner or taxing the patience of the experienced user. Two separate versions can help
overcome this problem. A guide for the beginner can explain the most common
features of the program with the aid of simple examples and detailed discussions. A
guide for the experienced user can provide more extensive descriptions of features
and fewer details. Remember that the beginner needs help getting started, whereas the
experienced user wants organized reference material.

Maintenance Manual

The maintenance manual is designed for the programmer who has to modify the
system. It should explain the procedures for any �hangts or expansion that have been
designed into the program.

-· ----
-----
18-14 6809 Assembly Language Programming

IMPORTANCE OF DOCUMENTATION

Documentation should not be taken lightly or left to the last minute. Good docu­
mentation, combined with proper programming practices, is not only an important part
of the final product but can also make development simpler, faster, and more produc­
tive. The designer should make consistent and thorough documentation part of every
stage of software development.
19
Debugging

As we noted at the beginning of this section, debugging and testing are among the
most time-consuming stages of software development. Even though such methods as
modular programming, structured programming, and top-down design can simplify
programs and reduce the frequency of errors, debugging and testing are still difficult
because they are so poorly defined. The selection of an adequate set of test data is
seldom a clear or scientific process. Finding errors sometimes seems like a game of "pin
the tail on the donkey," except that the donkey is moving and the programmer must
position the tail by remote control. Surely, few tasks are as frustrating as debugging pro­
grams.
This chapter will first describe the tools available to aid in debugging. It will
then discuss basic debugging procedures, describe the common types of errors, and
present some examples of program debugging. The next chapter will describe how to
select test data and test programs.
We will describe only the purposes of most debugging tools. There is little stan­
dardization in this area and we cannot discuss all the available products. The examples
show the uses, advantages, and limitations of some common tools.
Debugging tools have two major functions. One is to pin the error down to a short
section of the program; the other is to provide more detailed information about what the
computer is doing than is provided by normal runs and so make the source of the error
obvious. Current debugging tools do not find and correct errors by themselves; you
must know enough about what is happening to recognize and correct the error when the
debugging tools zero in on it and show its effects in detail.
19-2 6809 Assembly Language Programming

SIMPLE DEBUGGING TOOLS

The most common simple debugging tools are:

A single-step facility
A breakpoint facility
A trace facility
A Register Dump Program (or utility)
A Memory Dump Program

SINGLE STEP

The single-step facility allows you to execute the program one instruction or
one memory cycle at a time. Only some 6809-based microcomputers have this
facility, since the circuitry is fairly complex. Of course, all that you can see when the
computer executes a single-step are the states of the output lines that you are
monitoring. The most important lines are:

Data Bus
Address Bus
Control Lines
BUSY and READ/WRITE

If you monitor these lines either in hardware or in software, you can see the
progression of addresses, instructions, and data as the program is executed. You can
determine what kinds of operations the CPU is performing. This information will be
sufficient for you to identify such errors as Jump or Branch instructions with incorrect
conditions or destinations, omitted or incorrect addresses, incorrect operation codes,
and incorrect data values. However, you cannot see the contents of registers, flags, or
memory locations without some additional debugging tool.
Furthermore, a single-step mode obviously slows the processor way below its
normal speed. You cannot check delay loops or 1/0 operations in real time. Nor can a
single-step mode help you find timing errors or errors in the interrupt or DMA systems.
In fact, the single-step mode typically operates at less than one millionth of normal pro­
cessor speed. To single-step through one second of real processor time would require
more than ten days. The single-step mode, therefore, is useful only to check the logic
of a short sequence of instructions.

BREAKPOINT

A breakpoint is a place at which the program will automatically halt or wait so


that the user can examine the current status of the system. The program will not con­
tinue until the user orders its resumption. Breakpoints allow you to check or pass
through an entire section of a program. Thus, to see if an initialization routine is correct,
you can place a breakpoint at the end of it and run the program. You can then check
memory locations and registers to see if the entire section is correct. However, note that
if the section is not correct, you still must pinpoint the error, either with earlier break­
points or with a single-step mode.
Debugging 19-3

Breakpoints complement the single-step mode. You can use breakpoints either
to localize the error or to pass through sections that you know are correct. You can
then do the detailed debugging in the single-step mode. In some cases, breakpoints do
not affect program timing. They can then be used to check input/output and interrupts.

Software and Hardware Interrupts

Breakpoints often use the microprocessor's interrupt system (see Chapter 15).
The 6809 has 3 Software Interrupt instructions (SWI, SWI2, and SWI3) that can act
as breakpoints. If you are not already using the interrupt inputs (IRQ, FIRQ, and
NMI), you can use those vectors as externally controlled breakpoints. Table 15-l lists
the addresses used by the various instructions and inputs. The breakpoint routine can
print the contents of registers and memory locations or just wait (by executing a condi­
tional jump dependent on a switch input) until the user allows the computer to proceed.
But remember that the interrupts and SWI instructions use the Hardware Stack to store
the return address and the contents of the registers. Figure 19-1 shows a service routine
in which SWI results in an endless loop. The program would have to clear this break­
point with a RESET or non-maskable interrupt (SWI disables the maskable interrupts).

Inserting Breakpoints

The simplest method for inserting breakpoints is to replace the first byte or
bytes of an instruction with a Software Interrupt instruction. Any Software Interrupt
instruction will automatically direct the processor to the breakpoint routine and save the
current values of all the registers (except the Hardware Stack Pointer) in the Hardware
Stack. Figure 15-2 shows the order in which the processor saves its registers. The break­
point routine can print all the register contents by starting at the address in the Hardware
Stack Pointer. The only problem is that the return program counter value will be the
address following the Software Interrupt. You may want to reduce that value by 1 or 2,
either to display the actual breakpoint address or to resume the program correctly after
restoring the original instruction. Typical programs to reduce the value are (using the
methods discussed in Chapter 15):

1. Decrement the return address by 1 (if you are using SWI)

LOX $0A,S GET RETURN ADDRESS


LEAX -l,X MOVE IT BACK l
STX $0A,S PUT ADJUSTED RETURN ADDRESS IN STACK

2. Decrement the return address by 2 (if you are using SW12 or SWI3)

LDX $0A,S GET RETURN ADDRESS


LEAX -2,X MOVE IT BACK 2 (SWI2 AND SWI3 USE
TWO BYTES EACH)
STX $0A,S PUT ADJUSTED RETURN ADDRESS IN STACK

onr. BPJ{PT RR�AKPOINT ROUTINE


BRKPT BRI\ BRKPT �-<A IT IN PLI\C:E

ow:; $FFFI\ SOFT\�1\RE INTCfHWPT BREI\'<POI'IT


FD!3 P.R!:PT ADDRESS OF BREAKPOINT ROUTI�E

Figure 19-1. A Sim pie Breakpoint Routine


19-4 6809 Assembly Lmguage Programming

Store all registers


in Stack.
Count = Number
of bytes in
registers = 1 4

Data Pointer =

Stack Pointer

Print (Data Pointer)


as two hex digits

Data Pointer =

Data Pointer + 1
Count = Count - 1

Res tore all registers


from Stack

Figure 19-2. Flowchart or Register Dump Program

Setting and Clearing Breakpoints

Many monitors have facilities for automatically inserting (setting} and remov­
ing (clearing) breakpoints based on one of the Software Interrupt instructions. Such
breakpoints do not affect the timing of the program until one of them is executed.
However, you obviously cannot replace instructions that are in ROM or PROM. Other
monitors implement breakpoints by actually checking the address lines or the Pro­
gram Counter in hardware or in software. This method allows the user to set break­
points on addresses in ROM or PROM, but it may affect system timing if the address
must be checked in software. A more powerful facility would allow the user to enter an
address to which the processor would transfer control. Another possibility would be a
return dependent on a switch as in the following example.
Debugging 19-5

BRKPT TST PIADRA WAIT FOR SWITCH IN BIT 7 TO CLOSE


BMI BRKPT
RTI

Of course, other PIA data or control lines could also be used. Remember that RTI
reenables the interrupts automatically. If a PIA interrupt is used, the service routine
must read the PIA data register to clear the interrupt status bit.

Precautions in Using Breakpoints

When you use breakpoints (whether manually or through monitor facilities),


remember the following precautions:

1. Only set breakpoints at addresses that contain operation codes. Replacing


data or parts of addresses with SWI instructions can result in chaos.
2. Interpret the results carefully. Remember that the computer has not yet
executed the instruction that was replaced.

3. Check all conditions before resuming the program. You may have to change
the program counter, correct the contents of registers or memory locations,
clear breakpoints that are no longer necessary, and set new breakpoints.
Methods for resuming programs vary greatly, so consult your microcom­
puter's User's Guide. Be particularly careful never to resume a program in the
middle of an instruction (that is, at an address that does not contain an opera­
tion code) or in the middle of an 1/0 or timing operation (e.g., sending data to
a teletypewriter) that cannot logically be resumed after a delay.

TRACE

The trace facility allows you to see intermediate results. A simple trace prints the
contents of all registers and other variables after each instruction is executed. This
obviously produces a large amount of information, most of which is irrelevant or repeti­
tive. Better trace facilities allow you to specify what you want traced and how often
you want the values printed. This results in less information, but means that you must
decide what you need before instituting the trace.
The following approach will help you use traces:

1. Decide what you need before executing the trace. Otherwise, you will not
know what to do with the results.

2. Start by tracing only one or two variables and printing the results infre­
quently. This will give you less information to analyze at one time.
3. Use breakpoints to limit the extent of the trace.
4. Use whatever facilities your computer has to mark the output. Otherwise,
you will end up with pages of unidentified numbers and you will spend most
of your time just figuring out what they are.

REGISTER DUMP

A Register Dump utility is a program that lists the contents of all the CPU
registers. This information is usually not directly obtainable. The following routine will
19-6 6809 Assembly Language Programming

Value Register

AO SH
68 SL
DC cc
27 A
E5 8
01 DP
86 XH
97 XL
80 YH
14 YL
05 UH
F3 UL
07 PCH
3C PCL

Figure 19-3. Results or a Typical 6809 Register Dump

print the contents of all the registers on the system printer, if we assume that
PRTHEX prints the contents of Accumulator A as two hexadecimal digits. Figure 19-
2 is a flowchart of the program and Figure 19-3 shows a typical result. We assume that
the routine is entered with a BSR or JSR instruction that stores the old Program Counter
at the top of the Hardware Stack. An interrupt or Software Interrupt instruction will
store all the registers (except the Hardware Stack Pointer) on the Hardware Stack.

*
*SAVE ALL CPU REGISTERS IN THE HARDWARE STACK (PC IS ALREADY
*THERE)
*
RDUMP PSHS U,Y,X,DP,B,A,CC SAVE USER REGISTERS
LEAU 12,S CALCULATE ORIGINAL STACK POINTER
PSHS U SAVE ORIGINAL STACK POINTER
*
*P�:NT CONTENTS OF REGISTERS
*ORDER IS S(HIGH) ,S(LOW) ,CC,A,B,DP,X{HIGH) ,X(LOW) ,Y(HIGH) ,Y(LOW),
* U(HIGH) , U (LOW) ,PC(HIGH) ,PC(LOW)
*
TFR S,U POINT TO START OF REGISTER STORAGE
LOB #14 NUMBER OF BYTES 14 =

PRNTl LDA ,U+ GET A BYTE FROM THE STACK


JSR PRTHEX AND PRINT IT
DECB
BNE PRNTl
*
*RESTORE REGISTERS FROM THE STACK, INCLUDING THE ORIGINAL STACK
* POINTER
*
PULS U RESTORE AND DISCARD STACK POINTER
PULS PC,U,Y,X,DP,B,A,CC RESTORE OTHER REGISTERS AND RETURN

MEMORY DUMP

A Memory Dump is a program that lists the contents of memory on an output


device (such as a printer). This is a much more efficient way to examine data arrays or
entire programs than just looking at single locations. However, large memory dumps are
not useful (except to supply scrap paper) because of the sheer mass of information that
Debugging 19-7

they produce. They may also take a long time to execute on a slow printer. Small dumps
may, however, provide the programmer with a reasonable amount of information that
can be examined as a unit. Relationships such as regular repetitions of data patterns
or offsets of entire arrays may become obvious.
A general dump can be difficult to write. The programmer should be careful of the
following situations:

1. The size of the memory area exceeds 256 bytes, so that an 8-bit counter will
not suffice.
2. The ending address is below the starting address. This can be treated as an
error, since the user would seldom want to print the contents of memory in an
unusual order.

Since the speed of the Memory Dump depends on the speed of the output device,
the efficiency of the routine seldom matters. The following program will ignore cases
where the ending address is below the starting address, and will handle areas of any
size. We assume that the starting address is in memory locations START and START +
1 and the ending address is in memory locations LAST and LAST + 1.
*
*PRINT CONTENTS OF MEMORY LOCATIONS BETWEEN START AND LAST
*
DUMP LDX START GET STARTING ADDRESS
CHKEND CMPX LAST ARE WE BEYOND ENDING ADDRESS?
BHI DONE YES, DUMP COMPLETED
LDA ,X+ NO, GET CONTENTS OF NEXT LOCATION
JSR PRNTl PRINT CONTENTS AS 2 HEX DIGITS
BRA CHKEND
DONE RTS

Figure 19-4 shows the output from a dump of memory locations 1000 through
101F.
This routine correctly handles the case in which the starting and ending addresses
are the same ( try it! ) . You must interpret the results carefully if the dump area includes
the stack, since the dump subroutine itself uses the stack. PRNT l may also change
memory and stack locations.
A memory dump can display the data in many different formats. Common alter­
natives are ASCII characters or pairs of hexadecimal digits for 8-bit values and four hex­
adecimal digits for 16-bit values. You should select a format based on how you plan to
use the dump. If the area of memory contains object code, a hexadecimal format will be
best, since you can look up the meanings of the operation codes in Appendix D or on a
standard summary card. The following example shows a common format for displaying
the output of a dump; since this approach provides both the hexadecimal and the ASCII
forms, you can use it to examine areas containing either obj ect code or ASCII text.

1000 54 68 �5 20 64 75 6D 70 The dump

23 1F 60 54 37 28 3E ()0
6E 42 38 17 59 44 98 3/
47 36 23 81 E1 FF FF SA
34 ED BC AF FE FF 27 02

figure 19-4. Results of a Typical Memory Dump


19-8 6809 Assembly Language Programming

Each line consists of three parts: a starting address (the address of the first byte
shown on the line), the contents of that address and the following seven or fifteen bytes
in hexadecimal form, and the ASCII representation of those contents. You might try
revising the memory dump program so it produces output in this format.

ADVANCED DEBUGGING TOOLS

Popular advanced debugging tools include:

Simulator programs that help in checking program logic.


Logic or microprocessor analyzers that help in checking timing and other
hardware-related factors.

Many variations of both these tools exist; we shall discuss only the standard
features.

SOFTWARE SIMULATOR

The simulator is the computerized equivalent of the pencil-and-paper computer.


It is a computer program that goes through the operating cycle of another computer,
keeping track of the contents of all the registers, flags, and memory locations. We
could, of course, do this by hand, but it would require a large amount of effort and close
attention to the exact effects of each instruction. The simulator program never gets tired
or confused, forgets an instruction or register, or runs out of paper.
Most simulators are large FORTRAN programs. They can be purchased or used
on the time-sharing service. The 6809 simulator is available in several versions from
different sources.

Typical Features

Typical simulator features are:

1. A breakpoint facility. Usually, breakpoints can be set after a particular num­


ber of cycles have been executed, when a memory location or one of a set of
memory locations is referenced, when the contents of a location or one of a
set of locations are altered, or on other conditions.
2. Register and memory dump facilities that can display the values of memory
locations, registers, and 1/0 ports.
3. A trace facility that will print the contents of particular registers or memory
locations whenever the program changes or uses them.
4. A load facility that allows you to set values initially or change them during
the simulation.

Some simulators can also simulate input/output, interrupts, and even DMA.
Debugging 19-9

Advantages

The simulator has many advantages:

1. It can provide a complete description of the status of the computer, since it is


not restricted by pin limitations or other characteristics of the underlying cir­
cuitry.
2. It can provide breakpoints, dumps, traces, and other facilities, without using
any of the processor's memory space or control system. These facilities will
therefore not interfere with the user program.

3. Programs, starting points, and other conditions are easy to change.

4. All the facilities of a large computer, including peripherals and software, are
available to the microprocessor designer.

Limitations

On the other hand, the simulator is limited by its software base and its separa­
tion from the real microcomputer. The major limitations are:

1. The simulator cannot help with timing problems, since it operates far more
slowly than real time and does not model actual hardware or interfaces.

2. The simulator cannot fully model the input/output section.


3. The simulator is usually quite slow. Reproducing one second of actual pro­
cessor time may require hours of computer time. Using the simulator can be
quite expensive.

The simulator represents the software side of debugging; it has the typical
advantages and limitations of a wholly software-based approach. The simulator can
provide insight into program logic and other software problems, but cannot help with
timing, 1/0, and other hardware problems.

LOGIC ANA LYZER

The logic or microprocessor analyzer is the hardware approach to debugging.


Basically, the analyzer is the parallel digital version of the standard oscilloscope. The
analyzer displays information in binary, hexadecimal, or mnemonic form on a CRT, and
has a variety of triggering events, thresholds, and inputs. Most analyzers also have a
memory so that they can display the past contents of the busses.
The standard procedure is to set a triggering event, such as the occurrence of a
particular address on the Address Bus or instruction on the Data Bus. For example, one
might trigger the analyzer if the microcomputer tries to store data in a particular area or
execute an input or output instruction. One may then look at the sequence of events
that preceded the breakpoint. Common problems you can find in this way include
short noise spikes (or glitches), incorrect signal sequences, overlapping waveforms,
and other timing or signaling errors. You could not diagnose those errors with a soft­
ware simulator any more than you could conveniently find errors in program logic with a
logic analyzer.
19-10 6809 Assembly Language Programming

Important Features

Logic analyzers vary in many respects. Some of these are:

1. Number of input lines. At least 24 are necessary to monitor an 8-bit Data


Bus and a 16-bit Address Bus. Still more are needed for control signals,
clocks, and other important inputs.

2. Amount of memory. Each previous state that is saved will occupy several
bytes.

3. Maximum frequency. It must be several MHz to handle the fastest pro­


cessors.

4. Minimum signal width (important for catching glitches).

5. Type and number of triggering events allowed. Important features are pre­
and post-trigger delays. These allow the user to display events occurring
before or after the trigger event.
6. Methods of connecting to the microcomputer. This may require a complex
interface.

7. Number of display channels.


8. Binary, hexadecimal, or mnemonic displays.

9. Display formats.
10. Signal-hold time requirements.

11. Probe capacitance.

12. Single or dual thresholds.

All these factors are important in comparing different logic and microprocessor
analyzers, since these instruments are new and unstandardized. A tremendous variety
of products is already available and this variety will become even greater in the future. I
Logic analyzers, of course, are necessary only for systems with complex timing.
Simple applications with low-speed peripherals have few hardware problems that a
designer cannot handle with a standard oscilloscope.

DEBUGGING WITH CHECKLISTS

The designer cannot possibly check an entire program by hand; however, there
are certain trouble spots that the designer can easily check. You can use systematic
hand checking to find many errors before you start using debugging tools. The ques­
tion is where to place the effort. The answer is on points that can be handled with
either a yes-no answer or with a simple arithmetic calculation. Do not try to do com­
plex arithmetic, follow all the flags, or try every conceivable case. Limit your hand
checking to matters that can be settled easily. Leave the complex problems to be solved
with the aid of debugging tools. But proceed systematically, build your checklist, and
make sure that the program performs the basic operations correctly.
Debugging 19-11

WHAT TO CHECK BY HAND

The first step is to compare the flowchart or other program documentation with
the actual code. Make sure that everything that appears in one also appears in the other.
A simple checklist will do the job. It is easy to completely omit a branch or processing
section.
Next concentrate on the program loops. Make sure that all registers and memory
locations used inside the loops are initialized correctly. This is a common source of
errors; once again, a simple checklist will suffice.
Now look at each conditional branch. Select a sample case that should produce a
branch and one that should not; try both of them. Is the branch correct or inverted? If
the branch involves checking whether a number is above or below a threshold, try the
equality case. Does the correct branch occur? Make sure that your choice is consistent
with the problem definition.
Look at the loops as a whole. Try the first and last iterations by hand; these are
often troublesome special cases. What happens if the number of iterations is zero, i.e.,
there is no data or the table has no elements? Does the program fall through correctly?
Programs will often perform one iteration unnecessarily, or even worse, decrement
counters past zero before checking them.
Check off everything down to the last statement. Don't hopefully assume that
the first error is the only one in the program. Hand checking will allow you to get the
maximum benefit from debugging runs, since you will get rid of many simple errors
ahead of time.
A quick review of hand checking questions:

I. Is every element of the program design in the program (and vice versa for
documentation purposes)?
2. Are all registers and memory locations used inside loops initialized before the
loops are entered?
3. Are all conditional branches logically correct?
4. Do all loops start and end properly?
5. Are equality cases handled correctly?
6. Are trivial cases handled correctly?

LOOKING FOR ERRORS

Of course, despite all these precautions (or if you skip over some of them), pro­
grams often still don't work. The designer is left with the problem of how to find the
mistakes. The hand checklist provides a starting place if you didn't use it earlier.

PROGRAMMER ERRORS

Here are some of the errors that you may not have eliminated using the
checklist:

1. Failure to initialize variables such as counters, pointers, sums, indexes,


etc. Do not assume that registers, memory locations, or flags necessarily
contain zero before they are used.
19-12 6809 Assembly Language Programming

2. Inverting the logic of a conditional jump, such as using Branch on Carry Set
when you should use Branch on Carry Clear. Remember the effects of com­
parison (CMP) and subtraction (SBC or SUB) instructions, since these are
the most common flag-setting operations. If A is the contents of Accumula­
tor A and M the contents of the effective address, CMPA (or SUBA) sets
the Carry and Zero flags as follows:

Zero flag = 1if A M


=

Zero flag = 0if A "I M


Carry flag 1 if A < M t
A ssuming unsigned operands
=

Carry flag = 0 if A ;::_ M f

Note that the Carry flag is cleared in the equality case (A M). So =

Branch on Carry Set causes a branch if A < M and Branch on Carry Clear
causes a branch if A > M. If you want to handle the equality case in the
opposite way, use Branch if Lower or Same (causes a branch if A < M) or
Branch if Higher (causes a branch if A > M). For example, if you want to
force a branch when A is greater than or equal to 10, use
CMPA #10
BCC ADDR

The mnemonic BHS (Branch if Higher or Same) would be clearer than


BCC in this case; both mnemonics represent the same instruction. On the
other hand, if you want to force a branch when A is strictly greater than 10,
use
CMPA no
BHI ADDR

3. Updating counters, pointers, and indexes in the wrong place or not at all.
Be sure that there are no paths through a loop that either skip or repeat
the updating instructions. Note the difference between the 6809's autoincre­
menting and autodecrementing:
In autoincrementing, the processor increments the index register or
stack pointer ajier using its contents.
In autodecrementing, the processor decrements the index register or
stack pointer before using its contents.
4. Failure to handle trivial cases correctly.
Such cases may involve no data in a buffer, no tests to be run, or no
entries in an array or table. Do not assume that such cases will never occur
unless the program eliminates them specifically. Trivial cases often cause
problems if you use FORTRAN-like loop structures (see Figure 5-2) which
execute a routine once before checking conditions.
5. Reversing order of operands.
Remember that TFR R I ,R2 moves the contents of R 1 to R2, not the
other way around.
6. Changing condition flags before you use them.
Almost all instructions affect the Negative and Zero flags. Remember
also that RTI and TFR R 1 ,CC change all the flags, while LEAX and LEA Y
change the Zero flag.
7. Confusing the index registers and the indexed memory address.
Remember that CLR ,X clears the memory location addressed by Index
Debugging 19-13

Register X, not Index Register X itself. Note the difference between INC ,X
and INX (or LEAX 1,X); the former adds 1 to the contents of an 8-bit
memory location (addressed by Index Register X) while the latter adds I to
the contents of a 16-bit index register.

8. Confusing data and addresses.


Remember that LOX :#:$1000 loads Index Register X with the number
100016, whereas LDX $1000 loads Index Register X with the contents of
memory locations 100016 and 100116• A similar distinction applies to LOA
COUNT and LOA :#:COUNT. This problem becomes more serious if you
are using the indirect addressing modes. Now you must remember that LDA
,X+ loads Accumulator A from the address in Index Register X and then
adds l to Index Register X, whereas LOA [,X++] loads Accumulator A
from the address contained in the two memory bytes starting at the address
in Index Register X and then adds 2 to Index Register X. Mathematical
descriptions of what is happening are shorter and more meaningful than
word descriptions, but either may be difficult to understand.
9. Accidentally reinitializing a register or memory location.
Make sure that no branches transfer control back into the initialization
routine. Calculating a result and then writing over it is a common error that
is difficult to trace.
10. Confusing numbers and characters.
Remember that the ASCII representation of a digit is not the same as
the binary or BCD representation. For example, the ASCII representation of
7 is 3716; 0716 is the ASCII BELL character which rings the bell on a
teletypewriter.
11. Confusing binary and decimal numbers.
In the BCD representation, each decimal digit is coded separately into
binary. This is not true in the binary representation, since ten is not an
integral power of 2. For example, the decimal number 54 is equal to 3616 in
the binary representation and 5416 in the standard BCD representation.
12. Reversing the order of the data in non-commutative operations like
subtraction and division.
Remember that SUB and CMP both subtract the contents of the effec­
tive address from the contents of the specified register.
13. Ignoring the effects of subroutines and macros.
Subroutine calls and references to macros typically result in the execu­
tion of many instructions. Those instructions will almost always change the
flags and may change registers or memory locations as well. Be sure that you
know the effects of any subroutine or macro you use. Note also the impor­
tance of documenting subroutines and macros so users can determine their
effect without examining a long listing.
14. Using the Shift instructions improperly.
Remember the precise effects of ASR, ASL, LSR, ROL, and ROR.
They are 1-bit shifts that affect all the flags. ASL and LSR both clear the
empty bit, whereas ASR preserves the sign bit. ROR and ROL are circular
shifts that include the Carry. Remember that shift instructions affect all the
flags, even if they are operating on the data in a memory location.
/
19-14 6809 Assembly Language Programming

15. Counting the length of an array incorrectly.


Remember that addresses 0300 through 0304 include five (not four)
memory locations.
16. Confusing 8- and 16-bit quantities.
The Accumulators, Condition Code register, and Direct Page register
are all 8 bits long, whereas the Index Registers, Stack Pointers, and Program
Counter are 16 bits long. You cannot move data between registers of
different lengths using the transfer (TFR) or exchange (EXG) instructions.
17. Forgetting that addresses or 16-bit data occupy two bytes of memory.
Extended or indirect addresses or 16-bit data occupy two memory loca­
tions. The 16-bit registers also occupy two memory locations when they are
stored in memory. For example, LOX $40 loads Index Register X from
memory locations 0040 and 0041. Similarly, STU $50 stores the User Stack
Pointer in locations 0050 and 0051. Note that CMPX, CMPU, CMPY,
CMPS, LOX, LOU, LOY, LOS, etc. can all use 8-bit direct page addresses,
even though they are 16-bit operations.
18. Confusing the Stacks and their pointers.
Instructions like LD, TFR, LEA, and EXG affect the Stack Pointers,
not the contents of the Stacks. PSH and PUL transfer data to and from the
Stacks. Remember that JSR, BSR, RTI, RTS, and SWI all use the Hardware
Stack. Remember also that you must initialize the Hardware Stack Pointer
before calling any subroutines or allowing any interrupts.
19. Changing a register or memory location before using it.
Remember that LD, ST, and TFR all change the contents of the
destination, but not the source. EXG, on the other hand, changes both of its
operands (assuming they are not the same).
20. Forgetting to transfer control past sections of the program that should not
be executed.
Remember that the computer will proceed sequentially through
memory unless specifically instructed to do otherwise. Thus you may need
some unconditional branches to avoid routines that should not be executed.
21. Changing registers that you are using for addressing.
Be particularly careful of instructions like LOA A,X which loads
Accumulator A using the index in Accumulator A. The index in Accumula­
tor A is destroyed, so you had better not need it again. Instructions that use a
register both for addressing and as a destination can be powerfui, but may
also be confusing.
22. Ignoring the effects of autoincrementing and autodecrementing. Instruc­
tions that use these modes change the specified index register or stack
pointer.
23. Ignoring the physical limitations of 1/0 devices and interface chips.
While we may address interface chips as if they were memory locations,
they may not behave like memories. Storing data in an input port seldom
makes sense, nor does loading data from an output port unless the port is
latched and buffered. In particular, be careful of instructions like shifts,
clear, complement, and test which both read and write a memory location.
They may have unpredictable effects on 1/0 ports and interface chips.
Debugging 19-15

24. Ignoring the limitations of read-only memory.


Clearly instructions that both read and write a memory location make
little sense when applied to a ROM address.
25. Forgetting that the Hardware Stack is used in subroutine linkages.
JSR or BSR saves the return address in the Hardware Stack on top of
any parameters you may have placed there. RTS simply transfers control to
the address at the top of the Hardware Stack; if you have not managed the
Stack properly, the computer could end up anywhere.
26. Using the single accumulators and the double accumulator inconsistently.
The double accumulator D is physically the same as Accumulator A
(MSB's) and Accumulator B (LSB's). Double accumulator instructions are
convenient, but you must be sure that they mesh with the single accumula­
tor instructions.
27. Forgetting that addressing modes operate differently on Jump instruc­
tions than on other instructions.
Jump instructions (JMP or JSR) are executed as if one level of indirec­
tion had been removed. For example, JMP $A000 loads the address A00016
into the Program Counter, whereas LOX $AOOO loads the contents of
addresses A00016 and A00116 into Index Register X. The equivalent JMP
instruction would be JMP [$AOOO]. A similar distinction applies to all the
indexed modes; JMP or JSR using an indirect mode has the same effect on
the Program Counter that LOX using the corresponding non-indirect mode
would have on Index Register X. This distinction makes instructions that
use indirect addressing even more confusing than they would normally be.

28. Using the wrong register.


A and B are close together in the alphabet and easy to confuse. So are
X and Y. Even D, DP, S, and U can get into the act if you are not a careful
typist. Although the register assignments will assemble properly, you may
reference the wrong one.

ASSEMBLER-RELATED ERRORS

The use of an assembler is the only practical way to convert source programs
into object code, but it does introduce a few annoying errors. In particular,

1. Be careful of what your assembler may use as defaults. For example, the
standard 6809 assembler assumes that unmarked numbers are decimal and
that instructions without designated addressing modes use direct addressing
(if on the direct page) or extended addressing (otherwise). You must specify
hexadecimal or binary numbers, ASCII characters, immediate addresses,
indexed addresses, or indirect addresses, if you want to use them.
2. Watch for simple typing errors that can produce legal instructions or that
can confuse the assembler completely. Many operation codes differ by a
single letter (e.g., ADCA, ADDA, and ADDD); you can easily make a typing
error and still have a legal program. Some assemblers get confused if you
insert too many spaces, too much punctuation, or meaningless characters like
1/2 or ¢; in fact, the assembler may object to a minor error, but accept a
totally illogical entry that its developer never considered.
19-16 6809 Assembly Language Programming

Remember, the assembler can print a reassuring message like "NO


ASSEMBLY ERRORS" even when the program is wrong. All the message
means is that the assembler found no errors according to its interpretation of
the rules of the language. This does not exclude errors that produce legal
instructions or that are beyond the assembler's comprehension. It certainly
does not mean that the program does what you intended.

INTERRUPT ·DRIVEN PROGRAMS

Interrupt-driven programs are particularly difficult to debug, since errors may


show up only when an interrupt occurs at a particular time. lf, for example, the pro­
gram enables the interrupts a few instructions too early, an error will appear only if an
interrupt occurs while the processor is executing those few intructions. In fact, you can
usually assume that sporadic or random errors are caused by the interrupt system, since
the rest of the system can be reproduced.2 Typical errors in interrupt-driven programs
are:

l. Forgetting to reenable interrupts after accepting one and clearing it.


The processor disables the interrupt system automatically on RESET or
on accepting an interrupt. Be sure that no possible sequences fail to reenable
the interrupt.
2. Forgetting that RTI automatically reenables the interrupt unless you
specifically set the Interrupt Masks in the Stack.
3. Enabling interrupts before initializing all system parameters, such as flags,
vectors, and priority registers.
A checklist can help here.

4. Leaving results in registers and then destroying them by executing RTI.


Remember that R TI restores all the registers from the stack. As we noted
in Chapter 15, you should not use the registers to pass parameters and results
between the main program and the interrupt service routine.

5. Forgetting that the interrupts (including SWI) save the registers in the
Stack whether you want them or not.
You may have to reinitialize or update the Hardware Stack Pointer.
6. Failing to clear the interrupt before exiting from the service routine.
lf the interrupt comes from a PIA, the service routine must read the data
register in order to clear the interrupt flag. The reading is necessary even if the
interrupt is from an output device or a real-time clock. Otherwise, the inter­
rupt will remain active and will be recognized again as soon as the processor
reenables it.

7. Not disabling the interrupt during multi-byte transfers.


Watch particularly for routines that update time, position, or other data
that the interrupt service routine uses. You must avoid situations in which
partial updating results in erroneous values.

8. Failing to reenable the interrupt after executing a routine that requires the
interrupts to be disabled.
Be especially careful of such routines if they may be entered with the
interrupts disabled or enabled. The routine must then save and restore the
Debugging 19-17

condition code register, so that it exits with the interrupt system in its original
state.

Other Approaches

These lists are far from complete, but they should suggest some places where you
can look for errors. Unfortunately, debugging computer programs is not an exact
science� even the most systematic approach can leave you with baffling problems)
Sometimes, your best bet may be to let the problem sit overnight or have someone
with a fresh viewpoint look at it.

PROGRAM EXAMPLES

19-1. DEBUGGING A CODE CONVERSION PROGRAM

The program converts a decimal number in memory location 0040 to a seven-seg­


ment code in memory location 0041. It blanks the display if memory location 0040 does
not contain a decimal number.

Initial Program (from Flowchart in Figure 19-5):

LOA $40 GET DATA


CMPA #9 IS DATA A DECIMAL DIGIT?
BCS DONE NO, DONE
LOX SSEG YES, GET BASE ADDRESS OF CODE TABLE
LOA ,X GET ELEMENT FROM TABLE
DONE STA $41 SAVE SEVEN-SEGMENT CODE
SWI
SSEG FCB $3F,$06,$5B,$4F,$66
FCB $6D,$7D,$07,$7D,$6F

Using the Checklist

Using a checklist as described earlier in this chapter, we were able to find the
following errors:

1. We have omitted the section that clears Result if the data is not a decimal
digit.
2. The conditional branch (BCS DONE) is incorrect.

For example, if the data is zero, CMP A:#= 9 clears the Carry flag and causes a
branch. The correct version is
CMPA j9 IS DATA GREATER THAN 9?
BHI DONE YES, DONE

If we had used the mnemonic BLO instead of BCS, the mistake might have been
more obvious (or perhaps never made in the first place) . You can clarify code by using
the mnemonics BLO and BHS after comparisons instead of BCS and BCC.
The 6809 has many conditional branches and you must be careful to choose the
right one.
19-18 6809 Assembly Language Programming

Data = (0040)

Yes

Result = (SSEG Result= 0


+ Data)

(004 1) = Result

Figure 19-5. Flowchart of Decimal to Seven-Segment Conversion

Second Program:

CLRB GET BLANK CODE FOR DISPLAY


LDA $4'0 GET DATA
CMPA #9 IS DATA A DECIMAL DIGIT?
BHI DONE NO, KEEP ERROR CODE
LDX SSEG YES, GET BASE ADDRESS OF CODE TABLE
LDA ,X GET ELEMENT FROM TABLE
DONE STA $41 SAVE SEVEN-SEGMENT CODE
SWI
SSEG FCB $3F,$06,$5B,S4F,$6�
FCB $6D,$7D,$07,$7D,$6F

The hand check did not uncover any errors in this version.

Single Step

Since the program is simple, the next stage is to single-step through it with real
data. We chose the following data for the trials:

0 The smallest decimal digit


9 The largest decimal digit
10 A boundary case
6816 A randomly selected case
Debugging 19-19

For the first trial, we placed zero in memory location 0040. The program pro­
ceeded with no apparent errors until it reached the LOA ,X instruction. At that point,
Index Register X contained 3F06, an address that did not even exist in our computer.
Clearly, something had gone wrong.

Hand Check

It was now time for more hand-checking. Since we knew that BHI DONE was cor­
rect, the error had to be further along in the program. The hand check showed that LOX
SSEG placed 3F06 in Index Register X, since it loaded the register with the contents of
the two bytes starting at address SSEG. What we want to place in Index Register X is the
address SSEG, not its contents; that is, we want immediate addressing, not direct
addressing. This change creates an awkward patching problem in the object code, since
LOX with immediate addressing occupies 3 bytes of memory, whereas LOX with direct
addressing occupies only 2 bytes.

Run Test

With this correction (LOX :#:SSEG instead of LOX SSEG), the program worked
correctly when the data was zero. However, when the data was 9, it produced the same
result as for 0 (3F16). A hand check of the LOA ,X instruction showed that the program
was not performing any indexing; it was just loading Accumulator A from the address in
Index Register X. What we want is the accumulator indexed mode in which the pro­
cessor adds the index in Accumulator A to the base address in Index Register X. So we
replaced LOA ,X with LOA A,X.

Third Program:

CLRB GET BLANK CODE FOR DISPLAY


LDA $40 GET DATA
CMPA #9 IS DATA A DECIMAL DIGIT?
BHI DONE NO, KEEP ERROR CODE
LDX #SSEG YES, GET BASE ADDRESS OF CODE TABLE
LOA A, X GET ELEMENT FROM TABLE
DONE STA S41 SAVE SEVEN-SEGMENT CODE
SWI
SSEG FCB $3F,S06,$5B,$4F,$66
FCB $60,$7D,$07,$7D,$6F

The results now were:

Data Result

00 3F
09 6F
OA OA
68 68

Another Run Test

The program was not clearing the result if the data was invalid (i.e., greater than
9). In fact, the program never used the blank code in Accumulator Bat all. The required
change is to load the seven-segment code into Accumulator Binstead of Accumulator A
(replace LOA A,X with LOBA,X) and store Acccumulator Binstead of Accumulator A
(replace STA $41 with STB $41). After we made these corrections, the program pro­
duced the correct results for all the test cases.
19-20 6809 Assembly Language Programming

Exhaustive Test

Since the program was simple, we could easily test it on each decimal digit. The
results were:

Data Result

0 3F
1 06
2 58
3 4F
4 66
5 60
6 70
7 07
8 70
9 6F

Note that the result for 8 is wrong- it should be 7F, not 70. Since the program
works for all other digits, the error is almost surely in the table. In fact, the eighth entry
in the table had been typed incorrectly.

Final Program:
*

*DECIMAL TO SEVEN-SEGMENT CONVERSION


*

CLRB GET BLANK CODE FOR DISPLAY


LDA $40 GET DATA
CMPA #9 IS DATA A DECIMAL DIGIT?
BHI DONE NO, KEEP ERROR CODE
LDX #SSEG YES, GET BASE ADDRESS OF CODE TABLE
LOB A, X GET ELEMENT FROM TABLE
DONE STB $41 SAVE SEVEN-SEGMENT CODE
SWI
SSEG FCB $3F,$06,$5B,$4F,S66
FCB $6D,$7D,$07,$7F,$6F

Summary of Errors Discovered

The errors that we found in this example are typical of the ones that 6809 as-
sembly language programmers should expect. They include:

1. Failing to initialize registers or memory locations.


2. Inverting the logic on conditional branches.
3. Branching incorrectly in boundary cases.
4. Confusing immediate and direct addressing (i.e., data and addresses).
5. Failing to keep track of the current contents of registers and therefore
using the wrong accumulator, index register, or stack pointer.
6. Using the indexed addressing modes incorrectly. The 6809 terminology can
be confusing, since the 16-bit index registers usually hold base addresses,
not indexes.
7. Copying lists of numbers (or instructions) incorrectly.

Note that straightforward instructions (like AND, DEC, or INC) and simple
addressing modes seldom cause any problems.
Deoogging 19-21

Start

Interchange flag = 1
Count = Length
of Array
Pointer = Start
of Array

Interchange
(Pointed.
(Pointer + 1 I
Interchange flag
= 0

Pointer =

Pointer + 1

Count = Count -

Figure 19-6. Flowchart of a Sort Program


19-22 6809 Assembly Language Programming

19-2. DEBUGGING A SORT PROGRAM

The program sorts an array of unsigned 8-bit binary numbers into decreasing
order. The array begins in memory location 0042 and its length is in memory location
0041.
Initial Program (from flowchart in Figure 19-6):
LOA #l INTERCHANGE FLAG =
l
STA $40
LOA $41 COUNT = LENGTH OF ARRAY
LDX #$42 POINT TO START OF ARRAY
PASS LOB ,X GET AN ELEMENT
CMPB l,X IS PAIR IN CORRECT ORDER?
BLO COUNT YES, NO INTERCHANGE
STB l,X NO, INTERCHANGE PAIR
COUNT DECA IS PASS THROUGH ARRAY COMPLETE?
BNE PASS NO, GO ON TO NEXT PAIR
TST $40 YES, WERE ANY INTERCHANGES PERFORMED?
BNE PASS YES, MAKE ANOTHER PASS
SWI

Initial Hand Check

A hand check shows that we have implemented all the blocks in the flowchart
and initialized all the registers and memory locations. We must examine the condi­
tional branches carefully. The instruction BLO COUNT must force a branch if the pair
is already in the correct order - that is, if the second element is less than or equal to the
first element. The program must not interchange equal elements, since such an
interchange would create an endless loop with each pass swapping elements.
Try an example:
(0042) = 30
(0043) =
37

The execution of CMPB 1 ,X causes the CPU to calculate 30 - 37. The Carry flag
is set since the subtraction requires a borrow. This example should result in an
interchange, but BLO COUNT branches around the interchange instructions. BHS
COUNT produces the proper branch in this case. If the two numbers are equal, the com­
parison will clear the Carry flag so BHS COUNT is again correct.
How about BNE PASS at the end of the program? If there are any elements out of
order, the program will clear the interchange flag and the contents of memory location
0040 will be zero. So the branch is inverted; it should be BEQ PASS.
Now let us check the first iteration by hand. The initialization (the first four
instructions) produces the following values:

(A) = COUNT Length of array


(X)= 0042 Starting address of array
(0040) = 1 Interchange flag

The effects of the instructions in the loop are:

LDB ,X (B) = ( 0042) .


CMPB l,X (004 2) - (0043)
BHS COUNT
STB l,X (004 3) =
(004 ?.)
DECA (A) =
COUNT - l

Note that we have already checked the conditional branch instructions.


Debugging 19-23

Clearly the logic is incorrect. If the first two numbers are out of order (as in our
example), the results after the first iteration should be:

(0042) = old (0043)


(0043) = old (0042)
(X) = 0043
(A) = COUNT - 1
Instead, they are:
(0042) = Unchan ged
(0043) = old (0042)
(X)= 0042
(A) = COUNT - 1

The error in Index Register X is easy to correct. We can use autoincrementing as


long as we remember to adjust the later indexed offsets. Thus we need LOB ,X+;
instead of LOB ,X; CMPB ,X instead of CMPB l ,X (the autoincrementing has increased
Index Register X by 1); and STB ,X instead of STB l,X. We must be careful to incre­
ment X in an instruction that will be executed regardless of the outcome of BHS
COUNT. The interchange requires a bit more care and the use of both Accumulators
(remembering to save the count in the Hardware Stack and restore it at the end):

PSHS A SAVE COUNT IN HARDWARE STACK


LOA ,X GET SECOND ELEMENT OF PAIR
STB ,X REPLACE SECOND ELEMENT WITH FIRST ELEMENT
STA -l,X REPLACE FIRST ELEMENT WITH SECOND ELEMENT
PULS A RESTORE COUNT FROM HARDWARE STACK

An interchange always requires a temporary storage place in which the program


can save one element while it is transferring the other one.4

Second Program:

LOA u SET INTERCHANGE FLAG


STA $40
LOA $41 COUNT = LENGTH OF ARRAY
LOX #$42 POINT TO START OF ARRAY
PASS LOB ,X+ IS PAIR OF ELEMENTS IN ORDER?
CMPB ,X
BHS COUNT
PSHS A NO, INTERCHANGE ELEMENTS
LOA ,X
STB ,X
STA -l,X
PULS A
COUNT DECA IS PASS THROUGH ARRAY COMPLETE?
BEQ PASS NO, GO ON TO NEXT PAIR
TST $40 WERE ANY INTERCHANGES PERFORMED?
BNE PASS YES, MAKE ANOTHER PASS
SWI

How about the last iteration? Let us assume that the array contains three elements:

(0041) = 03 Number of elements


(0042) = 02 First element
(0043) = 04 Second element
(0044) = 06 Third element

Each time through the loop, the program increments Index Register X by 1. So, at the
start of the third (last) iteration,

(X)= 0042 + 2 = 0044

The effects of the instructions in the loop are:


LOB ,X+ ( B) = (0044) , (X) 0045
CMPB ,X (0044) - (0045)
19-24 6809 Assembly Language Programming

This is incorrect; the program is working on data beyond the end of the array. In
fact, the previous iteration should have been the last one, since the number of pairs is
one less than the number of elements. The last element in the array has no successor for
comparison. The correction is to reduce the number of iterations by 1: i.e., place DECA
after LOA $41.

Checking Trivial Cases

What happens in the trivial cases - that is, if the array contains no elements or
only one element? The answer is that the program does not work correctly and could
change a large number of memory locations improperly and without any warning (try
it!). The changes that handle the trivial cases are simple but essential; the cost is only a
few bytes of memory to avoid problems that could be difficult to identify and correct.

Third Program:

LOA $41 GET LENGTH O F ARRAY


CMPA #1 IS THERE MORE THAN ONE ELEMENT?
BLS DONF NO, NO ACTION NECESSARY
LOA #1 SET INTERCHANGE FLAG
STA $40
LOA $41 GET LENGTH OF ARRAY
DECA NUMBER OF PAIRS = LENGTH - 1
LOX #$42 POINT TO START OF ARRAY
PASS LOB ,X+ IS PAIR OF ELEMENTS IN ORDER?
CMPB ,X
BHS COUNT
PSHS A NO, INTERCHANGE ELEMENTS
LOA ,X
STB ,X
STA -l,X
PULS A
COUNT DECA IS PASS THROUGH ARRAY COMPLETE?
BNE PASS NO, GO ON TO NEXT PAIR
TST $40 WERE ANY INTERCHANGES PERFORMED?
BEQ PASS YES, MAKE ANOTHER PASS
DONE SWI

Run Test With Breakpoints

Now we must check the program on the computer or on the simulator. A simple
set of data is:

(0041 I = 02 Length of array

(0042) = 00 } Array to be sorted


(0043) = 01

This set consists of two elements in the wrong order. The program should require
two passes. The first pass should exchange the elements, producing:

(0042) = 01 } Reordered array


(0043) = 00

(0040) = 00 Interchange flag

The second element should find the elements already in the proper (descending)
order and produce:
(0040) = 01 Interchange flag

This program is too long for single-stepping, so we will use breakpoints


Debugging 19-25

instead. Each breakpoint will halt the computer and print the contents of the key
registers. The breakpoints will come:

1. After LOX :#:$42 to check the initialization.


2. After CMPB ,X to check the comparison.
3. After PULS A to check the interchange.
4. After TST $40 to check the completion of a pass through the array.

The contents of the registers at the first breakpoint are:

Register Contents

cc FO
B 00
A 01
X 0042

These are all correct, so the program is performing the initialization properly in
this case.
The results at the second breakpoint are:

Register Contents

cc F9
B 00
A 01
X 0043

These results are also correct.


The results at the third breakpoint are:

Register Contents

cc F1
B 00
A 01
X 0043

Examining memory shows:

(0042) = 01
(0043) = 00

The program has interchanged the elements correctly.


The results at the fourth breakpoint are:
Register Contents

cc FO
B 00
A 00
X 0043

Examining memory shows:


(0040) = 01

The Zero flag (bit 2 of the Condition Code Register) is incorrect, since an
interchange occurred and the program should branch and go back through the array
again. Memory location 0040 (the interchange flag) should contain 0, rather than 1.
Examining the program shows that it never clears the interchange flag; the correction is
to insert the instruction CLR $40 after BHS COUNT. The program now clears the
interchange flag as soon as it determines that an interchange is necessary.
19-26 6809 Assembly Language Programming

We can continue by clearing memory location 0040 and setting the Zero flag (CC
= F416 instead of F016). The results at the second iteration of the second breakpoint are:

Register Contents

cc F9
B 00
A 01
X 0044

The program has not reinitialized the registers (particularly Index Register X).
The condition branch that sends the program through the entire array again should
transfer control to the initialization routine; note that we do not need to check the length
of the array a second time to eliminate the trivial cases.

Final Program:

LOA $41 GET LENGTH Of ARRAY


CMPA #1 IS THERE MORE THAN ONE ELEMENT?
BLS DONE NO, NO ACTION NECESSARY
ITER LOA u SET INTERCHANGE fLAG
STA $40
LOA $41 GET LENGTH Of ARRAY
DECA NUMBER OF PAIRS � LENGTH - 1
LOX # $4 2 POINT TO START Of ARRAY
PASS LOB , X+ IS NEXT PAIR OF EL�MENTS IN ORDER?
CMPB ,X
BliS COUNT
CLR $40 NO, CLEAR INTERCHANGE fLAG
PSHS A AND EXCHANGE ELEMENTS
LOA ,x
STB ,X
STA -l,X
PULS A
COUNT DECA IS PASS THROUGH ARRAY COMPLETE?
BNE PASS NO, GO ON TO NEXT PAIR
TST $40 WERE ANY INTERCHANGES PERFORMED?
BEQ ITER YES, MAKE ANOTHER PASS
DONE SWI

Other Test Cases

Clearly, we cannot check all possible cases for this program. Two other simple
test cases that we could use for debugging are:

1. Two equal elements


(0041) = 02 Number of elements

(0042) = 00 } Array to be sorted


(0043) = 00

2. Two elements already in descending order

(0041) = 02 Number of elements

(0042) = 01 l Array to be sorted


(0043) = 00 f
Debugging 19-27

REFERENCES

1. For more information about logic analyzers, see:

G. Brock. "Logic-State Analyzers Seek Out Microprocessor-System Faults," EDN,


January 5, 1980, pp. 137-40.
R. Lorentzen. "Logic Analyzers Finish What Development Systems Start,"
Electronic Design, March 29, 1980, pp. 81-85.
J. Marshall. "Digital Analysis Instruments," EDN, January 20, 1980, pp. 141-143.

J. McLeod. "Special Report: Logic Analyzers," Electronic Design, March 29, 1980.
pp. 48-56.

C. A. Ogdin. "Setting up a Microcomputer Design Laboratory," Mini-Micro Systems,


May 1979, pp. 87-94.
I. H. Spector and R. Muething. "Logic Analyzer Deploys Its Full Strength,"
Electronic Design, March 29, 1980, pp. 177-214.
2. W. J. Weller. Assembly Level Programming for Small Computers, Lexington Books,
Lexington, Mass., 1975, Chapter 23.

3. R. L. Baldridge. "Interrupts Add Power, Complexity to Microcomputer System


Design," EDN, August 5, 1977, pp. 67-73.

4. One way to interchange A and B without using a temporary storage location is to use
the formulas:

A=AEllB
B=AffiB
A=AffiB

You can verify this sequence if you are handy at Boolean algebra and the use of
DeMorgan's theorem.
20
Testing

Program testing1 is closely related to program debugging. We must test the pro-
gram on the data that we used to debug it; for example,

Trivial cases such as no data or a single statement


Special cases that the program singles out for some reason
Simple cases that exercise particular parts of the program

For the decimal to seven-segment conversion program in Chapter 19, these


cases cover all possible situations. The test data consists of:

The numbers 0 through 9


The boundary case l 0
The random case 6B 16

The program does not distinguish any other cases. Here debugging and testing
are virtually the same.
In the sorting program, the problem is more difficult. The number of elements
could range from 0 to 255, and each of the elements could lie anywhere in that range.
The number of possible cases is therefore enormous. Furthermore, the program is
moderately complex. How do we select test data that will give us a degree of confidence
in that program? Here testing requires some design decisions. The testing problem is
particularly difficult if the program depends on sequences of real-time data. How do we
select the data, generate it, and present it to the microcomputer in a realistic manner?
20-2 6809 Assembly Language Programming

TESTING AIDS

Most of the tools mentioned earlier for debugging are helpful in testing also.
Logic or microprocessor analyzers can help check the hardware; simulators2 can help
check the software. Other tools can also be of assistance:

1. 1/0 simulations that can simulate many devices from a single input and a
single output device.
2. In-circuit emulators that allow you to attach the prototype to a development
system or control panel and test it.3
3. ROM simulators that can be changed like RAM but otherwise behave like
the ROM or PROM that will be used in the final system.
4. Real-time operating systems that can provide inputs or interrupts at specific
times (or perhaps randomly) and mark the occurrence of outputs. Real-time
breakpoints and traces may also be included.
5. Emulations (often on microprogrammable computers) that may provide
real-time execution speed and programmable I/0.4
6. Interfaces that allow another computer to control the I/0 system and test the
microcomputer program.
7. Testing programs that check each branch in a program for logical errors.
8. Test generation programs that can generate random data or other distribu­
tions.

Formal testing theorems exist, but are only practical for verifying short pro­
grams. You must be careful that the test equipment does not invalidate the test by
modifying the environment. Often test equipment may buffer, latch, or condition
input and output signals. The actual system may not do this and may therefore
behave differently.
Furthermore, extra software in the test environment may use some of the
memory space or part of the interrupt system. It may also provide error recovery and
other features that will not exist in the final system. A software test bed must be just
as realistic as a hardware test bed since software failure can be just as critical as hardware
failure.
Emulations and simulations are, of course, never precise. They are usually
adequate for checking logic, but can seldom help test interfaces or timing. On the
other hand, real-time test equipment does not provide much of an overview of the pro­
gram logic and may affect the interfacing and timing.

SELECTING TEST DATAs

Few real programs can be checked for all cases. The designer must choose a
sample set that is in some sense representative.

Structured Testing

Testing should, of course, be part of the total development procedure. Top-down


design and structured programming provide for testing as part of the design. This is
called structured testing. Each module within a structured program should be checked
separately. Testing, as well as design, should be modular, structured, and top-down.
Testing 20-3

Special Cases

But that leaves the question of selecting test data for a module. The designer
must first list all special cases that a program recognizes. These may include:

Trivial cases
Equality cases

Special situations

The test data should include all of these.

Forming Classes of Data

You must next identify each class of data that statements within the program
may distinguish. These may include:

Positive or negative numbers

Numbers above or below a particular threshold

Data that does or does not include a particular sequence or character


Data that is or is not present at a particular time

Be careful; each two-way decision doubles the number of classes since you must
test both paths. Thus three conditional branches will result in 2 x 2 x 2 = 8 classes if
the computer always executes each branch. Limiting the size of test sets is another
important reason to keep modules short and general.

Selecting Data from Classes

You must now separate the classes according to whether the program produces
a different result for each entry in the class (as in a table) or produces the same result
for each entry (such as a warning that a parameter is above a threshold). In the dis­
crete case, one may include each element if the total number is small or sample if the
number is large. The sample should include all boundary cases and at least one case
selected randomly. Random number tables are available in books, and random number
generators are part of most computer facilities.6
You must be careful of distinctions that may not be obvious. For example, the
6809 microprocessor will regard an 8-bit unsigned number greater than 127 as negative;
you must consider this when using the branch instructions that depend on the Negative
(Sign) flag. You must also watch for instructions that do not affect flags, overflow in
signed arithmetic, and the distinctions between address-length 06-bit) quantities and
data-length (8-bit) quantities.

EXAMPLES

20-1. TESTING A SORT PROGRAM

The special cases here are obvious:

No elements in the array


One element, magnitude may be selected randomly
20-4 6809 Assembly Language Programming

The other special case to be considered is one in which elements are equal.
There may be some problem here with signs and data length. Note that the array
itself must contain fewer than 256 elements. Using the instruction CLR $40 rather than
DEC $40 to modify the interchange flag means that multiple interchanges will create no
special problems.
We could check to see if the sign of the number of elements has any effect by
choosing half the test cases with elements between 128 and 255 and half with elements
between 2 and 127. We should choose the magnitudes of the elements randomly to
avoid unconscious bias which might favor small numbers, decimal (rather than hex­
adecimal) digits, or regular patterns.

20-2. TESTING AN ARITHMETIC PROGRAM

Here we will presume that a prior validity check has ensured that the number has
the right length and consists of valid digits. Since the program makes no other distinc­
tions, test data should be selected randomly. Here a random number table or random
number generator will prove ideal; the range of the random numbers is 0 to 9.

RULES FOR TESTING

Sensible design simplifies testing. The following rules can help:

1. Eliminate trivial cases early without introducing unnecessary distinctions.


2. Avoid special cases, since they increase debugging and testing time.

3. Perform validity or error checks on the data before it is processed.


4. Avoid inadvertent distinctions, particularly in handling signed numbers or in
using instructions that are intended to handle signed numbers.
5. Check boundary cases by hand. Be sure to define what should happen in
these cases.
6. Emphasize generality. Each distinction and separate routine leads to more
testing.
7. Use top-down design and modular programming to modularize testing.

CONCLUSIONS

Debugging and testing are the stepchildren of the software development pro­
cess. Most projects leave far too little time for them and most textbooks neglect them.
But designers and managers often find that these stages are the most expensive and
time-consuming. Progress may be difficuJt to measure or produce. Debugging and
testing microprocessor software is particularly difficult because the powerful hard­
ware and software tools that can be used on larger computers are seldom available for
microcomputers.
The designer should plan debugging and testing carefully. We recommend the
Testing 20-5

following guidelines:

1. Try to write programs that are easy to debug and test. Modular program­
ming, structured programming, and top-down design are useful techniques.
2. Prepare a debugging and testing plan as part of the problem definition.
Decide early what data you must generate and what equipment you will need.
3. Debug and test each module using top-down design.
4. Debug each module's logic systematically. Use checklists, breakpoints, and
the single-step mode. If the program logic is complex, consider using the soft­
ware simulator.
5. Check each module's timing systematically if this timing is a problem. An
oscilloscope can solve many problems if you plan the test properly. If the tim­
ing is complex, consider using a logic or microprocessor analyzer.
6. Be sure that the test data is representative. Watch for any classes of data
that the program may distinguish. Include all special and trivial cases.
7. If the program handles each element differently or the number of cases is
large, select the test data randomly.
8. Document all tests. If errors are found later, you will not have to repeat tests
you have already run.

REFERENCES

1. G. J. Myers. The Art of Software Testing, Wiley, New York, 1979.


R. C. Tausworthe. Standardized Development of Computer Software, Prentice-Hall,
Englewood Cliffs, N.J., Vo1.1, 1977, Chapter 9; Vol. 2, 1979, Chapters 14 and 15.
E. Yourdon. Techniques of Program Structure and Design, Prentice-Hall, Englewood
Cliffs, N.J., 1975, Chapter 7.
2. F. J. Langley. "Simulating Modular Microcomputers," Simulation, May 1979, pp.
141-54.
L. A. Leventhal. "Design Tools for Multiprocessor Systems," Digital Design, Octo­
ber 1979, pp. 24-26.
F. I. Parke et al. "An Introduction to theN .mPc Design Environment," Proceedings
of the 1979 Design Automation Conference, San Diego, Ca., pp. 513-19.
3. R. Francis and R. Teitzel. "Realtime Analyzer Aids Hardware/Software Integra­
tion," Computer Design, January 1980, pp. 140-50.
4. H. R. Burris. "Time-Scaled Emulations of the 8080 Microprocessor," Proceedings of
the 1977 National Computer Conference, pp. 937-46.
5. R. A. DeMille et al. "Hints on Test Data Selection: Help for the Practicing Pro­
grammer," Computer, April, 1978, pp. 34-41.
W. F. Dalton. "Design Microcomputer Software," Electronics, January 19, 1978,
pp. 97-101.
6. R. D. Grappel and J. Hemenway. "EON Software Tutorial: Pseudorandom Genera­
tors," EDN, May 20, 1980, pp. 119-23.
20-6 6809 Assembly Language Programming

T. G. Lewis. Distribution Sampling for Computer Simulation, Lexington Books, Lex­


ington, Mass., 1975.
R. A. Mueller et al. "A Random Number Generator for Microprocessors," Simula­
tion, April 1977, pp. 123-27.
21
Maintenance and Redesign

Program maintenance always involves elements of redesign. A program may


not work correctly in the field because of a flaw which was not discovered during the
debugging and testing phases of development. Sometimes, however, a program works
correctly but inefficiently - taking too long to respond, for example, or requiring an
awkward sequence of actions by the operator. A manufacturer may decide to adapt a
control program to run in a different hardware configuration. Inevitably, someone will
find a use for a microcomputer that never occurred to the system designer; a user's
needs often change in unanticipated ways. Thus it may become necessary to change a
program or system even if it works correctly.
Sometimes the designer may have to squeeze the last microsecond of speed or
the last byte of extra memory out of a program. As larger single-chip memories have
become available, the memory problem has become less serious. The time problem, of
course, is serious only if the application is time-critical. In many applications the
microprocessor spends most of its time waiting for external devices and program speed
is not a major factor.

COST OF REDESIGN

Squeezing the last bit of performance out of a program is seldom as important as


some writers would have you believe. In the first place, the practice is expensive for the
following reasons:

1. It requires extra programmer time, which is often the single largest cost in
software development.
2. It sacrifices structure and simplicity with a resulting increase in debugging and
testing time.
3. The programs require extra documentation.
4. The resulting programs will be difficult to extend, maintain, or re-use.
21-2 6809 Assembly Language Programming

In the second place, the lower per-unit cost and higher performance may not
really be important. Will the lower cost and higher performance really sell more units?
Or would you do better with more user-oriented features? The only applications that
would seem to justify the extra effort and time are very high-volume, low-cost and
low-performance applications, where the cost of an extra memory chip will far out­
weigh the cost of the extra software development. For other applications, you will find
that you are playing an expensive game for no reason.

MAJOR OR MINOR REORGANIZATION

However, if you must redesign a program, the following hints will help. First,
determine how much more performance or how much less memory usage is necess­
ary. If the required improvement is 25% or less, you may be able to achieve it by
reorganizing the program. If it is more than 25% you have made a basic design error;
you will need to consider drastic changes in hardware or software. We will deal first
with reorganization and later with drastic changes. Reducing memory usage is particu­
larly important if it results in a program that fits in the ROM and RAM provided by a
simple one or two-chip microcomputer. The use of such stand-alone microcomputers
can reduce hardware costs substantially in limited applications.

SAVING MEMORY

The following procedures will reduce memory usage for assembly language pro­
grams:

1. Replace repetitious in-line code with subroutines. Be sure, however, that


the CALL and RETURN instructions do not offset most of the gain. Note
that this replacement usually results in slower programs because of the time
spent in transferring control back and forth.
2. Place the most frequently used data on the direct page and access it with
one-byte addresses. You may even want to place a few 1/0 addresses there.

3. Use the Stack when possible. The Stack Pointer is automatically updated
after each use so that no explicit updating instructions are necessary. PSH
and PUL can move entire groups of registers to and from memory.
4. Eliminate Jump instructions. Try to reorganize the program instead.

5. Take advantage of addresses that you can manipulate as 8-bit quantities.


These include page zero and addresses that are multiples of 100 hex­
adecimal. For example, you might try to place all ROM tables in one 10016-
byte section of memory, and all RAM variables in another 10016-byte sec­
tion.
6. Organize data and tables so that you can address them without worrying
about address calculation carries or without any actual indexing. This will
again allow you to manipulate 16-bit addresses as 8-bit quantities.
7. Use the shift instructions to operate on bit positions at either end of a
b}"te.
Maintenance and Redesign 21-3

8. Take advantage of such instructions as ASL, DEC, INC, LSR, ROL, and
ROR which operate directly on memory locations without using registers.

9. Use INC or DEC to set or reset flag bits.


10. Use relative branches rather than jumps with absolute or indexed address­
mg.
11. Use the Software Interrupt instructions RTS and RTI to perform jumps
and reach subroutines if they are not already being used. SWI2 should
always be available for this purpose. This approach is oarticularly helpful if
the program uses the Stack anyway for temporary storage of data and
addresses.
12. Watch for special short forms of instructions that operate directly on the
Accumulators or other registers.

13. Use algorithms rather than tables to calculate arithmetic or logical expres­
sions and to perform code conversions. This replacement may make the pro­
gram run slower.

14. Reduce the size of mathematical tables by interpolating between entries.


Here again, we are saving memory at the cost of execution time.

15. Use instructions like CMPU, CMPX, and CMPY to perform comparisons
without involving the Accumulator.
16. Employ double accumulator instructions such as AOOO, CMPO, LOO,
STD, and SUBO rather than pairs of single accumulator instructions.

17. Take advantage of the LEA instructions to perform arithmetic as well as to


calculate indirect, indexed, and relative addresses for repeated use later.

18. Use indexed addressing rather than extended addressing to handle PIAs
and other situations involving several addresses that are close together.
19. Remember that operations on some of the registers take longer than on
others. In particular, some address-length registers have more single-byte
operation codes than others; the number is largest for Index Register X,
next largest for the Double Accumulator and User Stack Pointer U, and
smallest for Index Register Y and the Hardware Stack Pointer. For example,
LOX, LOO, and LOU require one-byte operation codes, whereas LOY and
LOS require two-byte codes. So, when assigning address-length registers
in your program, try to maximize the number of single-byte operation
codes that are executed. You can use TFR or EXG to move data from one
register to another.
20. Use the indexed addressing modes to perform address-length additions
during an instruction cycle. This approach is preferable to using LEA when
you do not need the result later.

21. Try to replace sequences of branch instructions with single branches. You
may be able to eliminate sequences by rearranging computations or by using
the conditional branches that depend on combinations of flags. Examine the
precise effects of branches like BGE, BGT, BHI, BLE, BLS, and BL T; they
may be useful in situations that differ greatly from those suggested by their
mnemonics.

22. Use instructions such as BIT, CMP, and TST that affect the flags without
changing any registers or memory locations. You may be able to retain data
for later use.
21-4 6809 Assembly Language Programming

SAVING EXECUTION TIME

Although some of the methods that reduce memory usage also save time, you
can generally save an appreciable amount of time only by concentrating on frequently
executed loop". Even completely eliminating an instruction that is executed only once
can save at most a few microseconds. But a savings in a loop that is executed frequently
will be multiplied many times over.
So, if you must reduc� execution time, proceed as follows:

1. Determine how frequently each program loop is executed. You can do this
by hand or by using the software simulator or other testing methods.

2. Examine the loops in the order determined by their frequency of execu­


tion, starting with the most frequent. Continue through the list until you
achieve the required reduction.
3. First, see if there are any operations that can be moved outside the loop,
such as repetitive calculations, data that can be stored in a register or in the
stack, data or addresses that can be stored on the direct page, special cases or
errors that can be handled elsewhere, etc. Note that this may require extra
initialization and memory but will save time.

4. Try to eliminate Jump statements. These are very time-consuming. Some­


times changing the initial conditions helps, particularly if the changes allow
you to perform tests at the end of a loop rather than at the beginning.

5. Replace subroutines with in-line code. This will save at least a CALL and a
RETURN instruction.
6. Use the stack for temporary data storage if you can take advantage of the
automatic ordering it provides.

7. Use any of the hints mentioned in saving memory that also decrease
execution time. These include the use of 8-bit addresses, SWl, RTI, special
short forms of instructions, etc.

8. Do not even look at instructions that are executed only once. Any changes
that you make in such instructions only invite errors for no appreciable gain.
9. Avoid indexed and indirect addressing whenever possible because they
take extra time.
10. Use tables rather than algorithms; make the tables handle as much of the
tasks as possible even if many entries must be repeated.

MAJOR REORGANIZATION

If you need more than a 25% increase in speed or decrease in memory usage do
not try reorganizing the code. Your chances of getting that much of an improvement are
small unless you call in an outside expert. You are generally better off making a maj or
change.
Maintenance and Redesign 21-5

BETTER ALGORITHMS

The most obvious change is a better algorithm. Particularly if you are doing
sorts, searches, or mathematical calculations, you may be able to find a faster or shorter
method in the literature. Libraries of algorithms are available in some journals and from
professional groups. See the references at the end of this chapter for some important
sources.

OTHER MAJOR CHANGES

Hardware can replace software. Counters, shift registers, arithmetic units, hard­
ware multipliers, and other fast add-ons can save both time and memory. Calculators,
UARTs, keyboards, encoders, and other slower add-ons may save memory even
though they operate slowly. Compatible parallel and serial interfaces, and other devices
specially designed for use with the 6809 or 6502 may save time by taking some of the
burden off the CPU.
Other changes may help as well:

1. A CPU with a longer word will be faster if the data is long enough. Such a
CPU will use less total memory. 16-bit processors, for example, use memory
more efficiently than 8-bit processors, since more of their instructions are one
word long.
2. Versions of the CPU may exist that operate at higher clock rates. But
remember that you will need faster memory and 1/0 ports, and you will have
to adjust any delay loops.
3. Two CPUs may be able to do the job in parallel or separately if you can
divide the job and solve the communications problem.
4. A specially microprogrammed processor may be able to execute the same
program much faster. The cost, however, will be much higher even if you
use an off-the-shelf emulation.
5. You can make tradeoffs between time and memory. Lookup tables and func­
tion ROMs will be faster than algorithms, but will occupy more memory.

Deciding on a Major Change

This kind of problem, in which a large improvement is necessary, usually


results from lack of adequate planning in the definition and design stages. In the
problem definition stage you should determine which processor and methods will han­
dle the problem. If you misjudge, the cost later will be high. A cheap solution may result
in an unwarranted expenditure of expensive development time. Do not try to just get
by; the best solution is usually to do the proper design and chalk a failure up to
experience. If you have followed such methods as flowcharting, modular program­
ming, structured programming, top-down design, and proppr documentation, vou can
salvage a lot of your effort even if you have to make a major change.
21-6 6809 Assembly Language Programming

REFERENCES

Carnahan, B., et al.Applied Numerical Methods, Wiley, New York, 1969.


Chen, T.C. "Automatic Computation of Exponentials, Logarithms, Ratios, and Square
Roots," IBM Journal of Research and Development, Volume 18, pp.380-388, July 1972.
Collected Algorithms from ACM, ACM Inc., P.O. Box 12105, Church Street Station,
New York, 10249.
Despain, A. M. "Fourier Transform Computers Using CORDIC Iterations," IEEE
Transactions on Computers, October 1974, pp. 993-1001.
Edgar, A. D.and S.C. Lee. "FOCUS Microcomputer Number System," Communica­
tions of the A CM, March 1979, pp.166-177.
Hwang, K. Computer Arithmetic, Wiley, New York, 1978.
Knuth, D.E. The Art of Computer Programming, Volume 1: Fundamental Algorithms; The
Art of Computer Programming, Volume 2: Seminumerica/ Algorithms; The Art of Computer
Programming, Volume 3: Sorting and Searching, Addison-Wesley, Reading, Mass. 1967-
1969.
Luke, Y. L. Algorithms for the Computation of Mathematical Functions, Academic Press,
New York, 1977.
Schmid, H. Decimal Computation, Wiley-lnterscience, New York, 1974.
New methods for performing arithmetic operations on computers are often discussed in
the triennial Symposium on Computer Arithmetic. The Proceedings (starting with
1969) are available from the IEEE Computer Society, 10662 Los Vaqueros Circle, Los
Alamitos, Calif. 90720.
v
6809 Instruction Set

Chapter 22 and the appendices that follow it comprise a total reference for the
6809 instruction set. Chapter 22 describes each instruction in some detail; the appen­
dices summarize that information and also provide material on indexed and indirect
addressing modes.
22
Descriptions of Individual
6809 Instructions

In this chapter we present instructions in alphabetical order and describe them


in great detail. The information contained here is summarized in Appendices A and C.
We have included several instruction mnemonics which 6809 assemblers may accept
to maintain compatibility with 6800 source code. These may be 6800 instructions
which the 6809 does not have or 6800 mnemonics that are not part of the standard 6809
set. Table 3-10 shows the 6800 mnemonics and the equivalent 6809 instructions. In
some cases, the instruction is a 6800-like mnemonic extended to the 6809's additional
facilities. The assembler turns each of these mnemonics into a 6809 instruction or
sequence whose execution has results equivalent to those of the 6800 instruction.
These instructions are predefined macro calls and may not be available on all 6809
assemblers.
A description generally includes a diagram of the execution of the instruction.
Since the 6809 microprocessor has so many addressing modes, we have not attempted
to describe all the modes for each instruction.

ABA - Add Accumulator 8 to Accumulator A

The 6809 assembler translates this instruction into


PSIIS B
/\f)f)A ,'.;+

This instruction adds the two accumulators and stores the result in Accumulator A. It is
included in the assembler to allow source compatibility between the 6800 and the 6809
microprocessors.
22-2 6809 Assembly Language Programming

ABX - Add Accumulator 8 to Index Register X Unsigned

Object No. of No. of


Code Cycles Bytes

ABX 3A 3 1

Add the contents of Accumulator B to those of Index Register X. Store the result
in Index Register X. ABX treats the contents of B as an unsigned number.

Data
Memory

E F H N Z V C

o{: XX

X pp qq
Program
y Memory

PC mm mm 3A mmmm

DP mmmm + 1

mmmm + 2

ABX mmmm + 3

Suppose xx = 8416 and ppqq = 109716• After the processor executes the ABX
instruction, Index Register X will contain 111B16:

1097 = 0001 0000 1001 0111


0084 = 0000 0000 1000 0100
0001 0001 0001 1011

This instruction calculates an indexed address and stores it in Register X for


later use. For example, Accumulator B could contain a calculated selection code and
Index Register X the base address of the table from which the selection would be made.
ABX would then store the address of the selected item in Register X. Subsequent
instructions could use that address without repeating the indexing process: for example,
LOA ,X. The selected item could itself be the address of a set of parameters� these
parameters could then be accessed via indirect addressing, as in LOA [ ,X++ ] .
ABX performs almost the same address calculation as LEAX B,X. Whereas
ABX has no effect on the flags, LEAX does affect the zero flag. Be careful of another
difference between the two instructions; LEAX treats the contents of Accumulator B
as a twos complement number, while ABX interprets the value in B as an unsigned
number. For example, if B holds FF16 and X contains 27El16, execution of ABX will
leave 28E016 in X, but LEAX B,X will place 27E016 in X. LEAX B,X should be used in
Descriptions of Individual 6809 Instructions 22-3

most situations; however, when program space or execution time is at a premium, the
shorter, faster ABX can replace it. Remember, though, that when you replace LEAX
B,X with ABX, you may have to relocate the memory area being addressed by the index
register.
ABX affects no flags; it is meant to manipulate addresses rather than data. This
is one of the few 6809 instructions that lack generality; it applies to only two specific
registers - B and X - and cannot be extended to any others. The instruction is
included in the 6809 instruction set for compatibility with the 6801 processor.

ADC - Add Memory Plus Carry to Accumulator A or B


ADCA
ADCB

Immediate Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

ADCA 89 2 2 99 4 2 89 5 3 A9 4+ 2+
ADCB C9 2 2 09 4 2 F9 5 3 E9 4+ 2+

This instruction adds the contents of a memory location and the contents of the
Carry flag to the contents of Accumulator A or B. The result is stored in the specified
accumulator.
Consider performing an addition with Carry using immediate data and Accumula­
tor A.
Data
Memory

E F H N Z V C

CCR

XX
o{:
X
Program
y
Memory

PC mm mm 89 mmmm

DP 7C mmmm + 1

mmmm + 2

mmmm + 3

ADCA #$7C

Suppose that xx = 3A11, and C = 1. After the processor executes the instruction ADCA
:#=$7C, Accumulator A will contain B7 Jo·
22-4 6809 Assembly Language Programming

3A 0011 1010
=

7C = 0111 1100
Carry= ____

1011 01 11 - Nonzero result resets Z to 0

I
Ll ---- Carry out of bit 3 sets H to 1

0 lJ. 1
1 = 1, set V to 1
1 sets N to 1
'------ No carry, reset C to 0

The ADC instruction is most frequently used in multibyte additions, to include


the carry in the addition of the second and subsequent bytes. Note that for double byte
addition, the ADDD instruction (described next) will perform the 16-bit addition in one
instruction, and the ADC instruction for the high-order byte is not necessary.

ADD - Add Memory to Accumulator


ADDA
ADDB
ADDD
Immediate Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

ADDA 88 2 2 98 4 2 8B 5 3 AB 4+ 2+
AOD8 CB 2 2 DB 4 2 FB 5 3 EB 4+ 2+
ADDO CJ 4 3 03 6 2 F3 7 3 E3 6+ 2+

ADDA and ADDB add the contents of a memory location to the value in
Accumulator A or Accumulator B, placing the sum in the designated accumulator.
ADDD adds the contents of a memory word (two contiguous bytes) to the value in the
double accumulator, placing the result in the double accumulator.
Consider the 8-bit addition using direct addressing and Accumulator A.
Data
Memory

ccR(._
E F H N Z V C

...... l_x-'-I_�l _..x l_ x.._l .._ x .._I__.xl


....�.-.. .

yy dd40

XX

n{:
X

y
Program
Memory
u

PC mm mm 9B mmmm

DP dd 40 mmmm + 1

mmmm + 2
ADDA $40
Descriptions of Individual 6809 Instructions 22-5

Suppose xx = 2411, dd = 0011, and the contents of memory byte 0040- (yy) are
8816• After execution of the ADDA $40 instruction, Accumulator A will contain AF1 6:

24 0010 0100
88"' 1000 1011
=

1010 1111 - Nonzero result resets Z to 0


_.,.. No Carry from bit 3 resets H to 0
I
\...._
__

l
0 ¥ 0 0. No Carry from bit 6 or 7, reset V to 0
_
=

Bit 7 sets N to 1
_
L_______

L___
__ _ _ No Carry, reset C to 0

ADDA and ADDB are the usual single-byte addition instructions; they are also
used to add the least significant bytes of multibyte addends greater than 16 bits.
ADDD, which we will describe next, is available for 16-bit addition.
Now consider the ADDD instruction. This instruction adds the contents of two
memory locations to the Double Accumulator D. The double accumulator's high-order
byte is Accumulator A; its low-order byte is Accumulator B. The number to be added
has its high-order byte in the first memory address and its low-order byte in the subse­
quent memory address.
We will illustrate the ADDD instruction using immediate addressing.

Data
Memory

E F H N Z V C

I
ccR._....
... ..
... ....
...._ _
. x.... I l j l )
_x..L.
.. _x.._ x
....,

XX

o{: yy

X
Program
y Memory

PC mm mm C3 mmmm

DP 10 mmmm + 1

{ 11 mmmm + 2

mmmm 3
ADDD :#:$1011
+
22-6 6809 Assembly Language Programming

If xx = 1016 and yy = 5516, the instruction ADDD #$1011 yields 206616 in


Accumulator D: that is, 2016 in Accumulator A and 6616 in Accumulator B.

105516 = 0001 0000 0101 0101


101116 = 0001 0000 0001 0001

0010 0000 0110 0110-Nonzero result resets Z to 0

II
No Carry from bit 14 or 15. V = 6¥ t = 0

'-----Bit 15 resets N to 0
'------• No Carry. reset C to 0

Note that ADDD does not affect the H flag.


The ADDD instruction can be used to perform 16-bit addition in preference to
ADDB, ADCA, which together take longer and require more memory. However, it
cannot readily be extended to handle longer data because of the lack of any way to add
in carries; that is, there is no ADCD instruction. You must remember the order of the
accumulators (A high-order, B low-order) and the fact that two memory locations are
used for data: the one addressed and the one following that.

AND - logical AND Accumulator or Condition Code Register


ANDA
ANDB
ANDCC

Immediate Direct E><tended lnde><edllndirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

ANDA 84 2 2 94 4 2 84 5 3 A4 4+ 2+
ANDB C4 2 2 04 4 2 F4 5 3 E4 4+ 2+
AN DCC 1C 3 2

This instruction logically ANDs the contents of a memory location with


Accumulator A or Accumulator B; the ANDCC instruction allows only immediate
addressing and performs a logical AND of the condition code register with the immedi­
ate byte. The result of the AND operation is stored in the designated register.
Consider the AND instruction using Accumulator Band indexed addressing with
zero offset.
Descriptions of Individual 6809 Instructions 22-7

Data
Memory

E F H N Z V C

ccR ._I ....


.. ..
..__ .__ ....
a. l l l_o..._
x ... _x_._
. I ��
yy ppqq

X pp
Program
y Memory

u
�------�--�
s

mm mm E4 mmmm

DP 84 mmmm + 1

mmmm + 2

mmmm + 3
ANDB .X

Suppose that xx = FC16, ppqq = 305616, and the contents of 305616 are 1316 (yy). After
the instruction ANDB ,X executes, Accumulator B will contain the value 1016•

FC = 1 1 11 11 00
13 = 0001 0011
0001 0000- Nonzero result, Z reset to 0
V is cleared regardless of the result
'----- Bit 1 resets N to 0

Common uses of AND are:

1. To clear bits - that is, to make them 'O's. For example, the instruction
ANDA #%ll0lllll

clears bit 5 of Accumulator A while leaving the other bits of Accumulator A


unchanged. Note that logically ANDing a bit position with a 'l' leaves the
value of the position unchanged, while logically ANDing with a '0' clears the
position.
2. To test bits. For example, the instruction

ANDA �%00001000

produces a result of 00001000 ifbit 3 of Accumulator A is '1' and a result of


zero if bit 3 of Accumulator A is '0'. Thus the instruction sets the Zero flag if
bit 3 of Accumulator A is '0' and clears that flag if bit 3 of Accumulator A is
'1 '. The Zero flag can then be used as a branch condition with the instruction
BNE or BEQ. For example,

liNDA �'1>000f)l(10(J
BNE BITl RRANCH IF' BIT 1 OF A rs l

ANDA ,%00010�00
AEQ I'?. ITO RRA!'JCH IF BIT � ()F' A r:::: n
22-8 6809 Assembly Language Programming

Now consider the ANDCC instruction.


Data
Memory

E F H N Z V C

CCR

o{;
X
Program
y
Memory
u

PC mm mm 1C mmmm

DP BF mmmm + 1

mmmm + 2

mmmm + 3
ANDCC #$BF

Let the CCR = 04111• After the instruction AN DCC :#$BF, the CCR will contain

0416 = 1101 0100


BF 1 6 = 1011 111 1
1001 0100

All flags may be affected by the ANDCC operation. It clears all the flags that are
logically ANDed with 'O's, while leaving the other flags unchanged. The following
masks can be used to clear individual flags:

Flag Required Mask

Binary Hexadecimal

E 0111 1111 7F
F 1011 1111 BF
H 1101 1111 DF
I 1110 1111 EF
N 1111 0111 F7
z 1111 1011 FB
v 1111 1101 FD
c 1111 1110 FE

Of course, 'O's in more than one bit position will clear more than one flag at a
time. However, only a few possibilities are really useful. In particular, we should note:
1\NDCC ��1011 llll ENABLE FAST INTERRUPTS
1\NDCC l%1110 llll I:NJI.f�Lf: RF:G!JLAR 1\JTER!HJPT:;
MJ nc c H1 111 L 1n 1 CLEAR OVERFLOW
1\NDCC ,11111 1110 CLEAR CARHY

Remember that clearing an interrupt mask enables the interrupt from that source.
This instruction is used to enable the regular or fast interrupt, to clear the Overflow
flag for later use, and to clear the Carry flag for use as an indicator or to start multi-
Descriptions of individual 6809 Instructions 22-9

pie-precision addition - there is, of course, no carry into the least significant bytes, so
the Carry must be cleared originally. The Carry must also be cleared initially for multi­
ple-precision binary subtraction, to signify that there is no borrow required from the
least significant bytes. The CLR instruction also clears the Carry flag.

ASL - Shift Accumulator or Memory Byte Left


ASLA
ASLB
ASL

Inherent Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

ASL 08 6 2 78 7 3 68 6+ 2+
ASLA 48 2 1
ASLB 58 2 1

Shift the contents of Accumulator A or 8 or the contents of the selected byte of


memory left one bit arithmetically, clearing the least significant bit.
Consider shifting an accumulator (A):

Data
Memory
CCR

y Program
Memory
u

48 mmmm

mmmm + 1

ASLA

Suppose that Accumulator A contains 7 A 16• Executing an ASLA instruction


changes the contents of Accumulator A to F4u-,-

Carry Accumulator A

X 0111 1010

ASLA 0 /� 1 11 0100-Nonzero result. reset Z to 0

L----It--- ---,.
'-
- ------+• Bit
l
� lJ 1 = 1 . set

7 sets N to 1

H is undefined
V to 1
22-10 6809 Assembly Language Programming

The Overflow flag (V) is loaded with the Exclusive-OR of bits 7 and 6 of the origi­
nal operand; these bit values are the same as those of the resulting Carry (C) and Sign
(N) flags. Common uses of ASL include simple multiplication (by small integers such
as 2 or 4), serial-to-parallel conversion, and scaling. Note that a single ASL instruc­
tion multiplies its operand by 2. This instruction is the same as Logical Shift Left (LSL).
An ASL operation on a memory location is exactly like the accumulator opera­
tion. There is, of course, some difference in object code size and execution time,
depending on the addressing mode.

ASR - Shift Accumulator or Memory Byte Right


ASRA
ASRB
ASR

Inherent Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycle• Bytes Code Cycles Bytes Code Cycles Bytes

ASR 07 6 2 77 7 3 67 6+ 2+
ASRA 47 2 1
ASRB 57 2 1

Perform a one-bit arithmetic right shift of the contents of Accumulator A or B or


the contents of a selected byte of memory.
Consider shifting a memory location right. The addressing mode is indexed,
autoincrementing User Stack Pointer U.
Data
Memory

E F H N Z V C

CCR

o{:
X

u pp qq

PC mm mm 67 mmmm

DP co mmmm + 1

mmmm + 2

ASR .U+ mmmm + 3

Suppose ppqq 013416 and the contents of location 013416 are CB16• Executing an
=

ASR ,U+ instruction will change the contents of memory location 013416 to E516. The
final contents of the User Stack Pointer will be 013516•
Descriptions of Individual 6809 Instructions 22-11

Address 01 34 Carry

1100 1011 � X

ASR 1110 0101 1

L._______ Nonzero result, reset Z to 0


L-.----- Bit 7 sets N to 1

H is undefined

While the 6809's ASR instruction does not affect the Overflow flag (V), those of
the 6800/0 I /02/03/08 processors do.
An arithmetic right shift preserves the value of the most significant bit (or sign
bit); it can thus be used for scaling twos complement numbers, since it retains their
signs. The ASR instruction is frequently used in division routines.

BCC - Branch if Carry Clear (C = 0)

Object No. of No. of


Code Cycles Bytes

BCC 24 3 2

This instruction is the same as BRA except that it causes a branch only if the Carry
flag is 0. If the Carry flag is 1, the processor continues to the next instruction in the nor­
mal sequence.
Consider the following section of a program:

----c
----se NEXT
A DA #$7F

C=O c = 1

---��-- CLRA

After executing BCC, the processor next executes:

1. CLRA if the Carry flag is 0.


2. ANDA if the Carry flag is l .

When used after a subtract or compare on unsigned binary values, this instruction could
be called "branch if the register was higher or the same as the memory operand�" in
fact, the 6809 assembler will accept the mnemonic BHS for this instruction.
22-12 6809 Assembly Language Programming

BCS - Branch if Carry Set (C - 1)

Object No. of No. of


Code Cycle• Byte•

BCS 25 3 2

This instruction is the same as BRA except that it causes a branch only if the Carry
flag is 1. If the Carry flag is 0, the processor continues to the next instruction in the nor­
mal sequence.
Consider the following section of a program:

NEXT
A DA :io$7F
c�1 c-o

.....__--filE*+-- CLRA

After executing BCS, the processor next executes:

1. CLRA if the Carry flag is l .


2. ANDA if the Carry flag is 0.

When used after a subtract or compare on unsigned binary values, this instruction could
be called "branch if the register was higher or the same as the memory operand;" in
fact, the 6809 assembler will accept the mnemonic BHS for this instruction.

BEQ - Branch if Equal to Zero (Z - 1)

Object No. of No. of


Code Cyclee Byt..

BEQ 27 3 2

This instruction is the same as BRA except that it causes a branch only if the Zero
flag is 1. If the Zero flag is 0, the processor continues to the next instruction in the nor­
mal sequence.
Consider the following section of a program:

NEXT
:io$7F
z = 1 :1 �z 0

....__--N�f...-..- CLRA

After executing BEQ, the processor next executes:

1. CLRA if the Zero flag is 1.


2. ANDA if the Zero flag is 0.

Remember that the Zero flag is set to 1 if the most recent result was zero. When
BEQ is used after a subtract or compare, branching will occur only if the values com­
pared were exactly the same.
Descriptions of Individual 6809 Instructions 22-13

BGE - Branch if Greater Than or Equal to Zero (N EB V = 0)

Object No. of No. of


Code Cycles Bytes

BGE 2C 3 2

This instruction is the same as BRA except that it causes a branch only if:

I. The Sign flag is 1 and the Overflow flag is I, or


2. The Sign flag is 0 and the Overflow flag is 0.

If neither of these conditions is true, the processor continues to the next instruc­
tion in the normal sequence. The branch conditions can be simplified logically to the
form N EB = 0.
Consider the following section of a program:

NEXT
A DA #$7F

NffiV=O NffiV=1

After executing BG E, the processor next executes:

1. CLRA if NEBV = 0.
2. ANDA if NEBV = 1.

The conditions have the following significance if a CMP (compare) instruction


immediately precedes the branch:

I. N = 0 and V = 0 if the result of CMP is positive (N = 0), and twos comple­


ment overflow did not occur (V 0). =

2. N = 1 and V = 1 if the result appears to be negative (N = 1), but the sign


was changed by twos complement overflow (V 1). =

Thus the branch occurs if the result is a true positive (unaffected by overflow) or a
false negative (affected by overflow). This analysis assumes that the numbers are all in
twos compl�ment form. BGE thus provides a twos complement Greater Than or Equal
To branch; alternatives are:

I. BGT, a twos complement Greater Than branch.


2. BHS (BCC), an unsigned Greater Than or Equal To branch.

BGT- Branch if Greater Than Zero (Z+(NEB V = 0)

Object No. of No. of


Code Cycles Bytes

BGT 2E 3 2

This instruction is the same as BRA except that it causes a branch only if the Zero
22-14 6809 Assembly Language Programming

flag is 0 and:

1. The Sign flag is l and the Overflow flag is 1, or


2. The Sign flag is 0 and the Overflow flag is 0.
If this condition is not true, the processor continues to the next instruction in the
normal sequence. The branch condition can be simplified logically to the form
Z + (N EB V) = 0.
Consider the following section of a program:

------iitA T NEXT
A DA =#:$7F

Z +(N ffi VI "" 0 •


Z + IN ffi VI = 1

After executing BGT, the processor next executes:

1. CLRA if Z + (N EB V) = 0.
2. ANDA if Z +(N EB V) = 1.

The condition has the following significance if a CMP (Compare) instruction


immediately precedes the branch:

1. Z = 0, N = 0, and V 0 if the result of CMP is positive but not zero (Z


= = 0
and N = 0) and twos complement overflow did not occur (V 0) . =

2. Z = 0, N = 1, and V l if the result of CMP is not zero and appears to be


=

negative (N = 1), but its sign was changed by twos complement overflow (V
= 1).

So the branch occurs if the result is not zero and is either a true positive number
(unaffected by overflow) or a false negative number (affected by overflow). This
analysis assumes that all numbers are in twos complement form. BGT thus provides a
twos complement Greater Than branch; alternatives are

l. BGE, a twos complement Greater Than or Equal To branch.


2. BHI, an unsigned Greater Than branch.

BHI - Branch if Higher (Z + C - 0)

Object No. of No. of


Code Cycle• Byte•

liMI 22 3 2

This instruction is the same as BRA except that it causes a branch only if the Zero
flag and the Carry flag are both 0. If either flag is not zero, the processor continues to the
next instruction in the normal sequence.
Descriptions of Individual 6809 Instructions 22-15

Consider the following section of a program:

�---�---�� NEXT
A DA :ll:$07

Z+C=O Z+C=1

After executing BHI, the processor next executes:

1. CLRA if the Carry flag and the Zero flag are both 0.

2. ANDA if the Carry flag and/or the Zero flag is l.

The condition has the following significance if a CMP (compare) instruction


immediately precedes the branch:

1. C = 0 and Z = 0 if the result of CMP is not zero and the operation did not
produce a borrow. Remember that the operation sets C to 1 if it requires a
borrow (that is, if the contents of the register were smaller in the unsigned
sense than the number to which they were compared).
2. C = 1 and/or Z = 1 if either the result of CMP is zero or the operation pro­
duced a borrow.

BHI differs from BHS (BCC) after a comparison only if the result is zero; BHS
causes a branch in that case, while BHI does not. BHI thus provides an unsigned Greater
Than branch; alternatives are:

1. BHS (BCC), an unsigned Greater Than or Equal To branch.


2. BGT, a twos complement Greater Than branch.

The instruction BHI is generally not useful after INC/DEC, LD/ST, or TSTI
CLR/COM: CLR always resets the Carry flag to 0; COM always sets the Carry flag to 1,
and the other instructions listed do not affect the Carry flag.

BHS - Branch If Higher or Same (C - 0)

Object No. of No. of


Code Cycles Bytes

BHS 24 3 2

This instruction is exactly the same as BCC. The alternative mnemonic reflects
the fact that the condition has the following significance if a CMP (compare) instruction
immediately precedes the branch:

l. C = 0 if the operation did not require a borrow. That is, the unsigned number
in the register was greater than or equal to the unsigned number to which it
was compared.

2. C = 1 if the operation required (produced) a borrow. That is, the unsigned


number in the register was less than the unsigned number to which it was
compared.
22-16 6809 Assembly Language Programming

BHS (BCC) causes a branch if the operation did not require a borrow. BHS (BCC) thus
provides an unsigned Greater Than or Equal To branch; alternatives are:

l. BGE, a twos complement Greater Than or Equal To branch.


2. BHI, an unsigned Greater Than branch.

This instruction is generally not useful after INC/DEC, LD/ST, or TST/CLR/COM:


CLR always resets the Carry flag to 0, COM always sets the Carry flag to I, and the other
instructions listed do not affect the Carry flag.

BIT - Bit Test


BIT A
BITB

Immediate Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

BITA 85 2 2 95 4 2 85 5 3 A5 4+ 2+
BITS C5 2 2 05 4 2 F5 5 3 E5 4+ 2+

This instruction ANOs the contents of accumulator A orB with the contents of a
selected memory location and sets the flags accordingly, but does not alter the contents
of the accumulator or memory byte. We illustrate this instruction with extended
addressing and Accumulator A.
Data
Memory

E F H I N z v c

(
CCR
I I I I I I I I I X X
'-.,.-'
0

yy 1641

XX �
XX A yy J
o{:
X
Program
y Memory

PC mm mm mmmm +3 85 mmmm
- -l.
DP 16 mmmm + 1

mmmm + 2
{ 41

mmmm + 3
BITA $1641

Suppose xx = A616 and yy = E01 6. After the processor executes BIT A $1641,
Accumulator A will still contain A6 16, and memory location 164116 will still contain E0 16
Descriptions of Individual 6809 Instructions 22-17

but the flags will be modified as follows:

A6 = 10 1 0 01 1 0
EO = 1 1 10 0000
1010 0000- Nonzero result sets Z to 0.
'-----Bit 7 sets N to 1

V is always cleared.

BIT instructions frequently precede conditional branch instructions. BIT instruc­


tions are also used to perform masking functions on data. Note that BIT instructions
differ from AND instructions only in that BIT instructions do not change the con­
tents of the selected accumulator, thus allowing further tests or other operations with­
out reloading.

BLE - Branch If Less Than or Equal to Zero (Z + (N EB V) - 1)

Object No. of No. of


Code Cycles Bytes

BLE 2F 3 2

This instruction is the same as BRA except that it causes a branch only if:

1. The Zero flag is 1 or

2. The Sign flag is 1 and the Overflow flag is 0 or

3. The Sign flag is 0 and the Overflow flag is 1.

If none of these conditions is true, the processor continues to the next instruction in the
normal sequence. The branch conditions can be simplified logically to the form
Z + (N EB V) = I.
Consider the following section of a program:

__.---E---ffi:I NEXT
A DA =lf$7F

z +(NEB V) = 1 z + (NEB V) = 0

After executing BLE, the processor next executes:

l. CLRA if Z + (N EB V) = l.
2. ANDA if Z + (N EB V) = 0.

The condition has the following significance if a CMP (compare) instruction


immediately precedes the branch:

1. Z = 1 if the result of CMP is zero.


2. N = 1 and V = 0 if the result of CMP is negative (N = l), and twos comple­
ment overflow did not occur (V = 0).
3. N = 0 and V = 1 if the result appears to be positive (N = 1), but the sign was
changed by twos complement overflow (V = 1).
22-18 6809 Assembly Language Programming

So the branch occurs if the result is zero, a true negative (unaffected by overflow), or a
false positive (affected by overflow). This analysis assumes that all numbers are in the
twos complement form. BLE thus provides a twos complement Less Than or Equal To
branch; alternatives are:

l. BL T, a twos complement Less Than branch.


2. BLS, an unsigned Less Than or Equal To branch.

BLO - Branch If Lower (C - 1)

Object No. of No. of


Code Cycles Bytes

BLO 25 3 2

This instruction is exactly the same as BCS. The alternative mnemonic reflects the
fact that the condition has the following significance if a CMP (compare) instruction
immediately precedes the branch:

1. C = 1 if the operation required (produced) a borrow. That is, the unsigned


number in the register was less than the unsigned number to which it was
compared.
2. C = 0 if the operation did not require a borrow. That is, the unsigned number
in the register was greater than or equal to the unsigned number to which it
was compared.

So BLO (BCS) causes a branch if the operation required a borrow. BLO (BCS) thus pro­
vides an unsigned Less Than branch; alternatives are:

1. BLS, an unsigned Less Than or Equal To branch.


2. BLT, a twos complement Less Than branch.

BLS - Branch If Lower or Same (C + Z - 1)

Object No. of No. of


Code Cycles Bytes

BLS 23 3 2

This instruction is the same as BRA except that it causes a branch if either the
Carry flag is 1 or the Zero flag is l. If neither flag is 1, the processor continues to the next
instruction in the normal sequence.
Consider the following section of a program:

NEXT
A DA #$7F
c + z = 1 C+Z=O

...__-NH'<-+--- CLRA
Descriptions of Individual 6809 Instructions 22-19

After executing BLS, the processor next executes:

1. CLRA if either the Carry flag or the Zero flag is 1.

2. ANDA if the Carry flag and the Zero flag are both 0.

The condition has the following significance if a CMP (compare) instruction


immediately precedes the result:

1. C = 1 if the operation produced a borrow. Remember that the operation sets


C to 1 if the contents of the register were smaller in the unsigned sense than
the number to which they were compared.
2. Z = 1 if the result of CMP is zero.

BLS differs from BLO (BCS) after a comparison only if the result is zero; BLS causes a
branch in that case, while BLO (BCS) does not, since no borrow is required if the result
is zero. BLS thus provides an unsigned Less Than or Equal To branch; alternatives are:

1. BLO (BCS), an unsigned Less Than branch.

2. BLE, a twos complement Less Than or Equal To branch.

The BLS instruction is generally not useful after INC/DEC, LD/ST, TST/CLR/COM:
CLR always resets the Carry flag to 0, COM always sets the Carry flag to 1 , and the other
instructions listed do not affect the carry flag.

BLT- Branch If Less Than Zero (N ffi V - 1)

Object No. of No. of


Code Cycles Bytes

BLT 20 3 2

This instruction is the same as BRA except that it causes a branch only if:

1. The Sign flag is 1 and the Overflow flag is 0 or

2. The Sign flag is 0 and the Overflow flag is 1.

If neither of these conditions is true, the processor continues to the next instruc­
tion in the normal sequence. The branch conditions can be simplified logically to the
form N EB V = 1.
Consider the following section of a program:

NEXT
A DA '*F$7F

NE8V=1 NffiV=O

After executing BLT, the processor next executes:

1. CLRA if N EB V = 1.
2. ANDA if N EB V = 0.

·-------
22-20 6809 Assembly Language Programming

The conditions have the following significance if a CMP (compare) instruction


immediately precedes the branch:

1. N = 1 and V =0 if the result of CMP is negative (N = 1), and twos comple­


ment overflow did not occur (V 0). =

2. N = 0 and V =1 if the result appears to be positive (N = 0), but the sign was
changed by a twos complement overflow (V 1). =

So a branch occurs if the result is a true negative (unaffected by overflow) or a false


positive (affected by overflow). This analysis assumes that the numbers are all in the
twos complement form. BLT thus provides a twos complement Less Than branch; alter­
natives are:

1. BLE, a twos complement Less Than or Equal To branch.


2. BLO (BCS), an unsigned Less Than branch.

BMI - Branch If Minus (N - 1)

Object No. of No. of


Code Cycles Bytes

BMI 28 3 2

This instruction is the same as BRA except that it causes a branch only if the Sign
flag is 1. If the Sign flag is 0, the processor continues to the next instruction in the nor­
mal sequence.
Consider the following section of a program:

----I---.M NEXT
A DA *$7F

N = 1 N = 0

----��---- CLRA

After executing BMI, the processor next executes:

l. CLRA if the Sign flag is I.


2. ANDA if the Sign flag is 0.

BMI is used to test the value in bit position 7; that bit position is often used for
parity, status indicators, or peripheral status bits. Used after an operation on twos
complement binary values, this instruction will "branch if the result is minus," but the
sign may be invalid due to twos complement overflow.

BNE - Branch If Not Equal to Zero (Z = 0)


Object No. of No. of
Code Cycles Bytes

BNE 26 3 2

This instruction is the same as BRA except that it causes a branch only if the zero
Descriptions of Individual 6809 Instructions 22-21

flag is 0. If the Zero flag is 1, the processor continues to the next instruction in the nor­
mal sequence.
Consider the following section of a program:

NEXT

Z=O C NEXT
#$7F

After executing BNE, the processor next executes:

1. CLRA if the Zero flag is 0.

2. ANDA if the Zero flag is 1.

Remember that the Zero flag is set to 0 if the most recent result was not zero. Used after
a subtract or compare operation on any binary values, this instruction will "branch if the
register is not equal to the memory operand."

BPL - Branch If Plus (N - 0)


Object No. of No. of
Code Cycles Bytes

BPL 2A 3 2

This instruction is the same as BRA except that it causes a branch only if the Sign
flag is 0. If the Sign flag is 1, the processor continues to the next instruction in the nor­
mal sequence.
Consider the following section of a program:

NEXT
#$7F

N=O

NEXT

After executing BPL, the processor next executes:

1. CLRA if the Sign flag is 0.

2. ANDA if the Sign flag is 1.

Used after an operation on twos complement binary values, this instruction will
"branch if the result is positive," but the sign may be invalid due to twos complement
overflow.

BRA - Branch Always

Object No. of No. of


Code Cycles Bytes

BRA 20 3 2
22-22 6809 Assembly Language Programming

BRA always causes a branch to the specified address by placing that address in the
Program Counter. The specified address is the sum of the current value of the program
counter (after the processor has fetched the BRA instruction from memory) and the dis­
placement. The displacement is an 8-bit twos complement number contained in the sec­
ond byte of the instruction.
Data
Memory

E F H N Z V C

o{:
X
Program
y
Memory

PC mm mm

� -:l
mmmm+
+ 23
2 20 mmmm

DP ._...__ 23 mmmm+ 1

mmmm + 2

mmmm+ 3
BRA *+$25

If mmmm = 204216, after BRA *+$25 is executed, the program counter will contain
206711, and the processor continues executing instructions from that point.
Consider the following section of a program:

.---B
--- RA NEXT
ANDA :ii:$7F

NEXT CLRA

After executing BRA, the processor always executes CLRA next. It will never execute
the ANDA instruction unless a branch or jump instruction elsewhere in the program
transfers control to that instruction.
The overall effect of a BRA instruction is:

PC = PC + 2+ disp

The extra factor of 2 is the result of the 2 bytes occupied by the BRA instruction itself.
Since the displacement is an 8-bit twos complement number with the range:

-128 (100000002).::; disp.::;+127 (011111112).

the range of a BRA instruction is:

• -126 .::;_ destination .::;_ • + 129

where * refers to the value of the Program Counter at the start of the instruction.
Descriptions of Individual 6809 Instructions 22-23

BRA
does not affect any flags or any registers except the program counter (its
previous value is lost). Some typical example displacements are:

1. 05,6

The final value of the program counter is its original value plus 7 (5 more
than its normal value at the end of a 2-byte instruction).
2. F E16

The final value of the program counter is the same as its original value,
since FE16 = -2 when considered as an 8-bit twos complement number. This
displacement results in an endless loop.

3. FA1 6

The final value of the program counter is its original value minus 4-6 less
than its normal value at the end of a 2-byte instruction. FA16 = -6 when
considered as an 8-bit twos complement number.

Note that a displacement of 00 produces a no-operation instruction (the pro­


cessor continues its normal sequence) while a displacement of FF (or -1) makes no
sense since it branches back into the middle of the BRA instruction itself.

BRN - Branch Never

Object No. of No. of


C ode Cycles Bytes

BAN 21 3 2

BRN is the same as BRA except that it never causes a branch. Thus BRN is really
a no-operation; that is, control always passes to the next instruction. Note that BRN is a
2-byte no-operation, since the second byte contains the displacement that will never be
used. BRN makes the set of branches logically complete. Typical usage of BRN is as a
byte filler, or it may be used to fine-tune delay routines. See the NOP instruction
description for a discussion of uses for no-operations.

BSR - Branch to Subroutine

Object No. of No. of


Code Cycles Bytes

BSR BD 7 2

This instruction is the same as BRA except that it saves the contents of the Pro­
gram Counter (after the 2-byte BSR instruction has been fetched) in the Hardware
Stack.
BSR saves the return address in the Hardware Stack as follows:

1. Decrement the Hardware Stack Pointer and store the low-order byte of the
program counter at that address.
22-24 6809 Assembly Language Programming

2. Decrement the hardware Stack Pointer again and store the high-order byte of
the Program Counter at that address.
Data
Memory

E F H N Z V C

mm xxxx- 2

mm + 2 xxxx - 1

xxxx

o{ :
X
Program
y Memory

s XX XX

PC mm mm
80 mmmm

DP 23 mmmm + 1

mmmm + 2

mmmm + 3
BSR • +$25

Suppose xxxx = DE3016 and mmmm


102416. After the execution of BSR
=

*+$25 the stack pointer S will contain DE2E111, the Program Counter will contain
104916, location DE2E16 will contain 1016, and location DE2F will contain 261 6.
A later instruction (such as RTS or PULS PC) can then restore that address to the
program counter and thus resume execution of the calling program. BSR differs from
BRA in that BSR "remembers" where it came from, thus allowing control to pass to a
subroutine and back.
Consider the following section of a program:

..----- BSR SUBR


ANDA *$7F

- SUBR CLRA

RTS

After executing BSR, the processor always executes CLRA next just as after BRA.
However, it also saves the address of the AN DA instruction at the top of the hardware
stack. Later an RTS instruction can conclude the subroutine and transfer control back to
the return address at the top of the hardware Stack. Thus control passes from the BSR
instruction to the subroutine and back to the AN OA instruction.
Descriptions of Individual 6809 Instructions 22-25

BVC - Branch If Overflow Clear (V = 0)

Object No. of No. of


Code Cycles Bytea

BVC 28 3 2

BVC is the same as BRA except that it causes a branch only if the Overflow flag is
0. If the Overflow flag is 1, the processor continues to the next instruction in the normal
sequence.
Consider the following section of a program:

----C
---ftV NEXT
A DA :11: $7F

V=O - v =1

NEXT C RA

After executing BVC, the processor next executes:

1. CLRA if the Overflow flag is 0.

2. ANDA if the Overflow flag is l.

Used after an operation on twos complement binary values, this instruction will
"branch if there was no overflow."

BVS - Branch If Overflow Set (V - 1)

Object No. of No. of


Code Cycles Bytes

BVS 29 3 2

BVS is the same as BRA except that it causes a branch only if the Overflow flag is
l. If the Overflow flag is 0, the processor continues to the next instruction in the normal
sequence.
Consider the following section of a program:

NEXT

V=1 C NEXT

After executing BVS, the processor next executes:

1. CLRA if the Overflow flag is 1.

2. ANDA if the Overflow flag is 0.

Used after an operation on twos complement binary values, this instruction will
"branch if there was an overflow." This instruction is also used after ASL or LSL to
detect binary floating-point normalization.
22-26 6809 Assembly Language Programming

CBA - Compare Accumulators

The 6809 assembler translates this 6800 instruction into:


p�����.:; H
c�1rl\ ,�;+

This instruction subtracts Accumulator B from Accumulator A and sets the flags accor­
dingly. It is handled by the 6809 assembler to allow source compatibility with the 6800
processor. The contents of the accumulators do not change.

CLC - Clear Carry

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction ANDCC'*f::%11111110- that is, into an instruction that clears the least sig­
nificant bit of the Condition Code Register (the Carry flag). CLC does not affect any
other flags or registers. Note that the CLR instruction also clears the Carry flag.

CLF - Clear Fast Interrupt Mask

The 6809 assembler translates this 6800-like instruction into the equivalent 6809
instruction ANDCC '*l=''lh10111111-that is, into an instruction that clears bit 6 of the
Condition Code Register (the fast interrupt mask). This instruction enables the fast
interrupt - that is, the 6809 will respond to the fast interrupt request control line. No
other registers or flags are affected. Note that you can also clear the fast interrupt mask
as part of the execution of the CW AI instruction.

CLI - Clear Interrupt Mask

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction ANDCC '*f::%11101111-that is, into an instruction that clears bit 4 of the
Condition Code Register (the regular interrupt mask bit). This instruction enables the
6809's regular interrupt - that is, the 6809 will respond to the interrupt request control
line. No other registers or flags are affected. Note that you can also clear the interrupt
mask as part of the execution of the CW AI instruction.

CLIF - Clear Regular and Fast Interrupt Masks

The 6809 assembler translates this 6800-like instruction into the equivalent 6809
instruction ANDCC'*f::%10101111-that is, into an instruction that clears bits 4 and 6
of the Condition Code Register (the regular and fast interrupt mask bits). This instruc­
tion enables both of the 6809's maskable interrupts - that is, the 6809 will respond to
either the fast interrupt request control line or to the interrupt request control line. No
other registers or flags are affected. Note that you can also clear the interrupt masks as
part or the execution of the CW AI instruction.
Descriptions of Individual 6809 Instructions 22-27

CLR - Clear Accumulator or Memory


CLRA
CLRB
CLR

Inherent Ditect Extended lndexed/lnditect


Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

CLR OF 6 2 7F 7 3 6F 6+ 2+
CLRA 4F 2 1
CLRB 5F 2 1

This instruction clears a specified accumulator or a selected byte of memory -


that is, it loads the accumulator or memory location with zero.
We will illustrate clearing Accumulator B:

Data
Memory

E F H N Z V C

cc R I..._-""-""""'--..'"""l_..._ " o....1_. 1.._I_o.._I �


oJ

o{: XX
r- 00

X
Program
y
Memory
u

s
....
PC mm mm mmmm + 1 mmmm
-
- -]. 5F

DP mmmm + 1

mmmm + 2

mmmm + 3
CL RB

Suppose that Accumulator B contains 4316• After the processor executes the instruction
CLRB, Accumulator B will contain 0016. In addition, the Sign, Overflow, and Carry flags
will all be 0 and the Zero flag will be 1.

CLV- Clear Overflow

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction ANDCC#% l l l lll 01 - that is, into an instruction that clears bit I of the
Condition Code register (the Overflow flag). No other flags or registers are affected. The
Overflow flag is also cleared by many other instructions, including AND, BIT, CLR,
COM, EOR, LD, OR, ST, and TST.
22-28 6809 Assembly Language Programming

CMP - Compare Memory with a Register


CMPA
CMPB
CMPD
CMPS
CMPU
CMPX
CMPY

Immediate Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycleo Bytes Code Cycles Bytes

CMPA 81 2 2 91 4 2 81 5 3 A1 4+ 2+
CMP8 C1 2 2 01 4 2 F1 5 3 E1 4+ 2+
CMPO 10 83 5 4 10 9 3 7 3 10 83 8 4 10 A3 7+ 3+
CMPS 11 B C 5 4 11 9C 7 3 11 8C 8 4 11 AC 7+ 3+
CMPU 11 83 5 4 11 9 3 7 3 11 83 8 4 11 A3 7+ 3+
CMPX 8C 4 3 9C 6 2 8C 7 3 AC 6+ 2+
CMPY 10 BC 5 4 10 9C 7 3 10 8C 8 4 10 AC 7+ 3+

There are two forms of this instruction - an 8-bit form and a 16-bit form. The
8-bit form is associated with Accumulators A and B. The 16-bit form is associated with
the 16-bit registers D, X, Y, U, and S. This instruction subtracts the contents of the
selected memory location from the contents of the specified register and sets the Condi­
tion flags accordingly. Neither the contents of the memory location nor the contents of
the register are changed. The Carry flag represents a borrow.
Let us begin with the 8-bit case using immediate addressing and Accumulator A.

Data
Memory

E F H N Z V C
CCR

XX
D{:
X
Program
y Memory

mmmm
PC mm mm 81

DP 18 mmmm + 1

mmmm + 2

mmmm + 3
CMPA :lf$18

Suppose that xx F616. After the processor executes the instruction CMPA :#:$18,
Descriptions of Individual 6809 Instructions 22-29

Accumulator A will still contain F61c,, but the flags will be modified as follows:

F6=1111 0110
Twos complement of 18 = 1110 1000
-
1101 11 10 - Nonzero result resets Z to 0

II

++---------<.. 1 ¥ 1 = 0. reset V to 0

....._
__
__
___.. Bit 7 sets N to 1

'----- No borrow resets C to 0

H is undefined.

Note that C is the complement of the resulting carry since it represents a borrow. Com­
pare instructions are most frequently used to set flags before the execution of branch
instructions. Note that the half-carry flag (H) is undefined after the 8-bit CMP instruc­
tion.
Now consider the 16-bit case. The execution of the two-byte compare is the same
as for the one-byte compare illustrated above with the exception that a 16-bit com­
parison takes place rather than an 8-bit comparison. We will illustrate CMPX using
extended addressing.
Data
Memory

CCR

XX A4 F1

yy 4
A F2

o{:
X pp qq
Program
y
Memory
�------+---�
u

PC mm mm BC mmmm

OP { -

1-
A4
-
_ --1
mmmm + 1

F1 mmmm + 2

mmmm + 3
CMPX $4
A F1

Suppose that ppqq = I AB011,, xx (the contents of memory location A4Fl) l B1r, and =

yy (the contents of memory location A4F2) 8011,. After the processor executes
=

CMPX $A4Fl, Index Register X and memory will be unchanged but the Sign, Zero,
Overflow, and Carry flags will be modified as fo::v .> ...
22-30 6809 Assembly Language Programming

1ABO = 0001 1 01 0 1 011 0000


Twos complement of 1BBO = 1110 0100 0101 0000

1111 1111 0000 0000 -Nonzero result resets Z to 0

'--
___ :
I.__--

----
- -

- -
0

----A borrow sets C to


¥ 0= 0, reset
Bit 1 5 sets N to
V to 0

H flag is unaffected.

Notice that C is the complement of the resulting carry, just as in the CMPA
instruction. The flags are affected by the complete 16-bit operation, not by the two 8-bit
(CMPD, CMPS, CMPU, and CMPY) all
operations separately. The similar instructions
require 2-byte operation codes whileCMPX requires only one. This means that pro­
grammers should prefer Index Register X over Index Register Y and the stack pointers
to minimize the memory usage and execution time of their programs.

COM - Complement Accumulator or Memory


COMA
COMB
COM
Inherent Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

COM 03 6 2 73 7 3 63 6+ 2+
COMA 43 2 1
COMB 53 2 1

This instruction complements the specified accumulator or a selected byte of


memory. This is the ones complement operation, which replaces each 1 in the byte with
a 0, and each 0 with a 1. We will illustrate the COM instruction using the indirect
indexed mode with zero offset from Index Register X.
Data
Memory
E F H N Z V C

ccR _( __....... ........


..., l_. ..
x j_.._x ....,
(_o ..._
I _, rr ppqq

ss ppqq + 1

XX rrss

o{: t-----�

X PP qq
Program
y Memory

u mmmm
63
s mmmm + 1
94
PC mm mm mmmm + 2

DP mmmm + 3
COM LXI
Descriptions of Individual 6809 Instructions 22-31

Suppose that the contents of Index Register X are 010016 and that memory locations
0100 and 0101 contain 011316. lf the contents of memory location 0113 are 2316, then
after the processor executes the instruction COM [,X], memory location 0113 will be
changed to DC 16•

23 = 0010 0011
Ones complement of 23 = 11 01 1100- Nonzero result resets Z to 0
V is reset to 0 always

�---B
-- it 7 sets N to 1
C is set to 1 always

CWAI - logically AND Immediate Memory with Condition


Code Register and Wait for Interrupt

Object No. of No. of


Code Cycles Bytes

CWAI JC 20 2

This instruction logically ANDs the contents of the following byte of program
memory with the contents of the Condition Code Register, saves all the user registers in
the Hardware Stack, and halts execution until an external interrupt occurs.
Data
Memory

10 XX XXXX ssss - c

aa sss5- B

bb sss5- A

5S5S - 9

cc ssss- 8

dd 5SSS- 7

ee SS5S - 6

CCA
ff 5SSS- 5

99 S55S - 4

hh 5555 - 3

aa
mm ssss - 2
o{: bb
mm + 2 SSS5 - 1
X cc dd SSS5

y ee ff

hh Program
u gg
Memory
s ss ss

PC mm mm 3C mmmm

DP ii BF mmmm + 1

CWAI #$BF mmmm + 2


22-32 6809 Assembly Language Programming

The logical AND immediate is performed in exactly the same way as described in the
ANDCC instruction. Note that the operation on the Condition Code Register is done
before stacking. The entire flag (E) is set regardless of masking. The normal use of
CWAI is to clear one or more of the interrupt flags and hence enable interrupts before
suspending operations. So the sensible instructions are:
CI..;A I It% lll () l I l I ENARLE R E GULAR INTERRUPT
C\-.jAI �%1011\lll ENABLE FAST INTERRUPT
CWI\I lt%10\0llll ENABLE REGULAR AND FAST INTERRUPTS
OJAI �'1;1\lllll l WAIT FOR NONMASKABLE INTERRUPT

Remember that clearing an interrupt mask enables the interrupt from that source.
After the processor has saved the status of the system in the Hardware Stack as
shown in the diagram above, it halts execution until it receives an interrupt. Note that
the contents of the Hardware Stack Pointer are not stacked. When an interrupt occurs,
the interrupt mask bits are set to 1 and the processor jumps to the address in the
appropriate interrupt vector.
This instruction is used to synchronize the CPU with external processes.
CW AI does not tri-state the system busses. A fast interrupt may enter its interrupt
handler with the entire machine state saved; RTI will automatically restore the
entire machine state after testing the E bit of the recovered CCR.

DAA- Decimal Adjust After Addition

Object No. of No. of


Code Cycles Bytea

DAA 19 2 1

Convert the contents of Accumulator A to binary-coded decimal form.


Suppose that Accumulator A contains 3916 and memory location 15El contains 4716.
After the processor has executed the two instructions
.1\DD/\ $l5F.l
D AA

Accumulator A will contain 8616, rather than the 8016 which would be the ordinary
binary result. The Carry flag will be reset to 0 since there was no carry; the Overflow flag
is undefined; the Zero flag is reset to 0 since the result is not zero; and bit 7 sets N to 1.
This is the only instruction that requires the Half-Carry flag (H); its value is needed to
determine if a Carry occurred from the less significant digit.
The Sign and Zero flags are modified to reflect the statuses they represent. The
Overflow flag is destroyed and the Carry flag is set or reset as it should be by a hypotheti­
cal BCD addition. That is, the Carry flag is set if the BCD sum of the more significant
digits produced a carry.
Correction factors of 6 are added to each 4-bit digit of Accumulator A under the
following conditions:

I. Less Significant Digit (LSD)


a. H = 1 or
b. LSO > 9
Descriptions of Individual 6809 Instructions 22-33

2. More Significant Digit (MSD)


a. C = 1 or
b. MSD > 9 or
c. MSD > 8 or LSD > 9

This instruction makes sense only after a binary addition instruction (ADC or
ADD); the combinations ADCA, DAA or ADDA, DAA are decimal addition instruc­
tions that operate on BCD data and generate BCD results.

DEC - Decrement Accumulator or Memory


DECA
DECB
DEC

Inherent Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

DEC OA 6 2 7A 7 3 6A 6+ 2+
DECA 4A 2 1
DECB 5A 2 1

This instruction decrements by one the specified 8-bit accumulator or a selected


memory byte.
Let us consider the case of Accumulator B.

Data
Memory

E F H N Z V C

ccR ._I ____ _,j�x_,j �x_,j.__


�x_,j l l l l

n{: XX
-
......
- :J.._
XX - 1

X
Program
y Memory

PC mm mmmm + 1 5A mmmm
mm
...... -:x..
DP mmmm + 1

mmmm + 2

mmmm + 3
DECB

Suppose that Accumulator B contains 3 A16 . After the processor executes DECB,
Accumulator B will contain 39 16•
22-34 6809 Assembly Language Programming

3A = 0011 1010
Ones complement of 1 = 1111 11 11
0011 1001 - Nonzero result resets Z to 0

Il l_
� Bit is
1 :V. 1 = 0, Vis reset toO
7 resets N to 0
Carry not affected

The fact that DEC does not affect the Carry flag is quite important; it allows the pro­
grammer to use DE.C (or INC) to count iterations of a loop that is performing multi­
ple-precision arithmetic. The Carry flag is essential in such a loop to transfer informa­
tion (carries or borrows) from one iteration to the next. Decrementing a register or
memory location that contains zero produces a result of FF16 but does not set the Carry
flag.
After decrements of unsigned values, only BEQ and BNE branches will behave
consistently. However, when the operands are twos complement numbers, all signed
branches behave properly.

DES - Decrement Hardware Stack Pointer by 1

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction LEAS -1 ,S - that is, into an instruction that subtracts 1 from the Hard­
ware Stack Pointer. Note that DES provides a 16-bit decrement that does not affect the
flags.

DEX - Decrement Index Register X by 1

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction LEAX - 1 ,X - that is, into an instruction that subtracts 1 from Index
Register X. Note that DEX provides a 16-bit decrement that affects only the Zero flag.

DEY - Decrement Index Register Y by 1

The 6809 assembler translates this 6800-like instruction into the equivalent 6809
instruction LEA Y - 1, Y - that is, into an instruction that subtracts 1 from the contents
of Index Register Y. Note that DEY provides a 16-bit decrement that affects only the
Zero flag.

EOR - Logically Exclusive-OR Memory with Accumulator


EORA
EORB

Immediate Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

EORA 88 2 2 98 4 2 88 5 3 AB 4+ 2+
EOR8 C8 2 2 08 4 2 F8 5 3 EB 4+ 2+
Descriptions or Individual 6809 Instructions 22-35

This instruction logically Exclusive-OR s the contents of a memory location with


the contents of Accumulator A orB, treating both operands as simple binary data. The
results are stored in the designated accumulator.
Consider the following example using indirect indexed addressing with an 8-bit
offset and Accumulator B.
Data
Memory

E F H N Z V C

ccR ��--'-_._..-'-...._ l_x....__


I x.._I I _o ....�
.
ss ppqq + 60

tt ppqq + 61

yy sstt
D
{: 1------1 �---'
XX

X pp qq
Program
y Memory

mm mm
EB mmmm

DP 98 mmmm + 1

60 mmmm + 2

mmmm + 3
EORB [$60,X]

Suppose that xx E316 and yy = A016, and that ppqq


= C8001 6 and sstt = 3E4A 16. =

After the processor executes the instruction EORB [$60,X] AccumulatorB will contain
4316·
E3 = 1110 001 1
AO = 1010 0000
0100 0011 --Nonzero result resets Z to 0.
l__ ,___ Bit 7 resets N to 0
C is not affected

V is cleared.

Note that a logical Exclusive-OR is the same as a bit-by-bit "not equal" opera­
tion; that is, the output is 1 if and only if the inputs are not equal. EOR is used to test
for changes in bit status and to calculate parity and other error-detecting and correct­
ing codes.

EXG - Exchange Register Contents


Object No. of No. of
Code Cycles Bytes

EXG IE 8 2

This instruction exchanges the contents of one 8- or 16-bit register with another.
The subsequent byte of immediate data determines which registers are exchanged. Note
22-36 6809 Assembly Language Programming

that registers may only be exchanged with registers of like size, that is 8-bit with 8-bit
and 16-bit with 16-bit.
We will illustrate the execution of the EXG A,B instruction.

Data
Memory

E F H N Z V C

D
XX

o{: yy

X
Program
y Memory

s
....
PC mm mm
-
...
-::x. mmmm + 2 1E mmmm

DP 89 mmmm + 1

mmmm + 2

mmmm + 3
EXG A,B

Suppose that xx = 7E16 and yy = A516; then after the processor executes the EXG A,B
instruction, the contents of Accumulator A will be A516 and the contents of Accumula­
tor B will be 7E16•
The EXG instruction has many miscellaneous applications; for example,

1. Exchanging accumulators - EXG A,B


Remember, for example, that only Accumulator A can be operated on with
the DAA instruction.
2. Calling subroutines with a link register - EXG PC,X
This instruction transfers control to the address in Index Register X and saves
the old value of the Program Counter in Index Register X.
3. Changing the direct page - EXG A,DP
This instruction not only places the value from Accumulator A in the Direct
Page Register, but it also saves the old value of the Direct Page Register in
Accumulator A. Note that there is no LD instruction for the Direct Page
Register.

EXG is, of course, symmetric - for instance, EXG A,B and EXG B,A are the same
operation. Note that all EXG instructions require two bytes of memory- one for the
operation code and one for a post byte (immediate data) to specify which registers are to
be exchanged. Be careful of the fact that some EXG instructions are meaningless
(undefined register codes), while others are illegal (exchanging registers with different
lengths).
Descriptions of Individual 6809 Instructions 22-37

The post byte definition is as follows:

POST BYTE

Bit patterns defining the registers are as follows:

Register Binary Hex Register Binary Hex

D 0000 0 PC 0101 5
X 0001 1 A 1000 8
y 0010 2 B 1001 9
u 0011 3 CCR 1010 A
s 0100 4 DP 1011 B

The remaining bit patterns are undefined.


Returning to the previous example, the post byte was determined as follows:

Source: EXG A,B


-..-

!
Binary: 1000 1001

Hexadecimal: 1E 8 9

Bits 0 through 3 of the immediate byte of the instruction define one register, while bits 4
through 7 define the other. The condition codes are not affected unless one of the
registers is the Condition Code Register itself (CCR).

INC - Increment Accumulator or Memory Location by 1


INCA
INCB
INC

Inherent Direct Extended Indexed/Indirect

Object No. of No. o f Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

INC oc 6 2 7C 7 3 6C 6+ 2+
INCA 4C 2 1
INCB 5C 2 1

This instruction adds one to the contents of the specified 8-bit accumulator or byte
of memory.
Consider incrementing a memory location addressed by indirect indexed mode
with Accumulator A offset from Index Register X.
22-38 6809 Assembly Language Programming

Data
Memory

E F H N Z V C

ccR l.___,...._.___.__._
.. l_x _I "-1 _I
_x x
_ _,
ss ppqq + rr

tt ppqq + rr + 1

D {: 'r
t-------t
XX sstt

X pp qq
Program
y
Memory
u
t-----�----f
s

PC mm mm
6C mmmm

DP 96 mmmm + 1

mmmm + 2

mmmm + 3
INC [A.X)

If ppqq =
l50AI6• rr = FEI6• sstt 25E416• and XX = colo• then after the processor
=

executes the instruction INC [A, X], it will have changed the contents of memory loca­
tions 25E4 to Cl10• Note that rr is interpreted as a twos complement number, so ppqq +
rr = 150816.
co = 1100 0000
1 = 0000 0001
11 00 0001 -Nonzero result resets Z to 0


0 ¥0 = 0, reset V to 0

Bit 7 sets N to 1

C is not affected.

The fact that INC does not affect the Carry flag is quite important; it allows the
programmer to use INC (or DEC) to count iterations of a loop that is performing
multiple-precision arithmetic. The Carry flag is essential in such a loop to transfer
information (carries or borrows) from one iteration to the next. Incrementing a register
or memory location that contains FF16 produces a result of 0016 but does not set the
Carry flag� however, it does set the Zero flag.
INC and DEC are commonly used to count occurrences of events or numbers of
iterations. INC is more commonly (and more logically) used for event counting, while
DEC is more commonly used for looping since the Zero flag is then available as a con­
venient exit condition.
After increments of unsigned values, only BNE and BEQ branches will behave
consistently. When the operands are twos complement values, all signed branches
function correctly.
Note that this instruction does not apply to the Double Accumulator D. Thus,
the only accumulator forms implemented are INCA and INCB.
Descriptions of Individual 6809 Instructions 22-39

INS - Increment Hardware Stack Pointer by 1

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction LEAS 1,S- that is, into an instruction that adds 1 to the contents of the
Hardware Stack Pointer. Note that INS performs a 16-bit increment that does not affect
any flags.

INX - Increment Index Register X by 1

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction LEAX 1,X- that is, into an instruction that adds 1 to the contents of Index
Register X. Note that INX performs a 16-bit increment that affects only the Zero flag.

INY - Increment Index Register Y by 1

The 6809 assembler translates this 6800-like instruction into the equivalent 6809
instruction LEAY 1,Y - that is, into an instruction that adds 1 to the contents of Index
Register Y. Note that INY performs a 16-bit increment that affects only the Zero flag.

JMP - Unconditional Jump

Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of


Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

JMP OE 3 2 7E 4 3 6E 3+ 2+

Jump to the specified memory address. This instruction provides an unconditional


absolute jump capability, as contrasted to the unconditional relative jump capability pro­
vided by BRA and LBRA. We will illustrate its execution using the extended indirect
mode, but you should note that it can use base page direct, extended direct, or any of
the indexed addressing modes.
22-40 6809 Assembly Language Programming

Data
Memory

E F H N z v c
CCR ( rr 3A05

ss 3A06

o{:
X
Program
y Memory

PC mm mm 6E mmmm

DP 9F mmmm + 1

3A mmmm + 2

05 mmmm + 3
JMP [3A05l

If, for example, rrss = D I E5, then after the processor executes the instruction
JMP [$3A05], the Program Counter will contain D 1 E5 and execution will continue from
that point.
The terminology here is somewhat confusing (as on most computers) - JMP
with extended addressing transfers control to the extended address, not to its contents.
So JMP with extended addressing is similar to other instructions (such as LD) with
immediate addressing. For example, JMP $3E08 transfers control to (loads the program
counter with) 3E0816, not the contents of that address. JMP with indexed addressing is
executed in a similar manner, as if one level of indirection had been removed.
In the following instruction sequence:

LOX INDEX GET INDEX FOR JUMP TABLE


.JI'IP [.JTABL, X] �UMP TO APPROPRIATE TABLE ENTRY

the JMP instruction will perform an indexed jump into a table of addresses starting at
JTABL, with the index given by the contents of memory addresses INDEX and
INDEX+ l. Some part of the program preceding LOX must double the contents of
INDEX and INDEX+ 1 to account for the fact that all addresses occupy two bytes.
Note the distinction from the instruction sequence

LOX INDEX Gr:T INDEX FOR TABLE OF BR.I\.'·K!IES


,JI'iP ,JTARL,X JUMP TO APPROPRIATE BRANCH INSTRUCTION

In this sequence, the JMP instruction will transfer control to the appropriate position in
the table (base address JTABL, index given by the contents of memory addresses
INDEX and INDEX+ 1). That position must contain a JMP or branch instruction
transferring control to the appropriate routine, rather than just the address of the
routine as in the earlier case.
Descriptions of Individual 6809 Instructions 22-41

JSR - Jump to Subroutine

Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of


Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

JSR 90 7 2 BD 8 3 AD 7+ 2+

Jump unconditionally to the specified memory address, saving the old value of the
Program Counter on the hardware Stack.
We will illustrate the execution of JSR with extended addressing.

If, for example, mmmm = E56B111 and ssss = 08A016, then after the processor
executes the instruction JSR $ElA3, the program counter will contain ElA316 and
execution will continue from that point in memory. The value of the program counter at
the end of the JSR instruction (E56B + 0003 = E56E) will have been saved in the hard­
ware Stack the same way it is saved during the BSR instruction. The final value of the
Hardware Stack Pointer will be 2 less than its original value.
JSR is the same as JMP, except that JSR saves the old value of the program
counter in the hardware Stack, thus providing a subroutine linkage. An RTS instruction
at the end of the subroutine can transfer control back to the instruction immediately
following JSR, providing that the subroutine has not changed the return address or the
Hardware Stack Pointer. JSR provides an unconditional absolute jump-to-subroutine
c1pability, as compared to the relative jump-to-subroutine capability provided by BSR
and LBSR.
JSR, like JMP, can be used to handle jump tables. The only difference is that the
return address is saved at the top of the Stack. The same terminology confusion exists
22-42 6809 Assembly Language Programming

here as with JM P; JSR with extended addressing transfers control to the extended
address, not to its contents. All the indexed modes operate similarly, as if one level of
indirection had been removed.

LBCC - Long Branch If Carry Clear (C - 0)

Object No. of No. of


Code Cycles Bytes

LBCC 10 24 5(6) 4

LBCC is the same as LBRA except that it branches under the same condition as
does BCC. LBCC is a 4-byte instruction using 16-bit relative addressing while BCC is a
2-byte instruction using 8-bit relative addressing. See LBRA and BCC for details on the
operation of LBCC.

LBCS - Long Branch If Carry Set (C - 1)


Object No. of No. of
Code Cycles Bytes
--

LBCS 10 25 5(6) 4

LBCS is the same as LBRA except that it branches under the same condition as
does BCS. LBCS is a 4-byte instruction using 16-bit relative addressing while BCS is
only a 2-byte instruction using 8-bit relative addressing. See LBRA and BCS for details
on the operation of LBCS.

LBEQ - Long Branch If Equal To Zero (Z - 1)

Object No. of No. of


Code Cycles Bytes

LBEO 10 27 5(6) 4

LBEQ is the same as LBRA except that it causes a branch under the same condi­
tion as does BEQ. LBEQ is a 4-byte instruction using 16-bit relative addressing while
BEQ is a 2-byte instruction using 8-bit relative addressing. See LBRA and BEQ for
details on the operation of LBEQ.

LBGE - Long Branch If Greater Than or Equal To Zero


(N EB V = 0)
Object No. of No. of
Code Cycles Bytes

LBGE 10 2C 5(6) 4

LBGE is the same as LBRA except that it causes a branch under the same condi­
tion as does BGE. LBGE is a 4-byte instruction using 16-bit relative addressing while
Descriptions of Individual 6809 Instructions 22-43

BGE is a 2-byte instruction using 8-bit relative addressing. See LBRA and BGE for
details on the operation of LBGE.

LBGT - Long Branch If Greater Than Zero (Z + (N El1 V) - 0)

Object No. of No. of


Code Cycles Bytes

LBGT 10 2E 5(6) 4

LBGT is the same as LBRA except that it causes a branch under the same condi­
tion as does BGT. LBGT is a 4-byte instruction using 16-bit relative addressing while
BGT is a 2-byte instruction using 8-bit relative addressing. See LBRA and BGT for
details on the operation of LBGT.

LBHI - Long Branch If Higher (Z + C - 0)


Object No. of No. of
Code Cycles Bytes

LBHI 10 22 516) 4

LBHI is the same as LBRA except that it causes a branch under the same condi­
tions as does BHI. LBHI is a 4-byte instruction using 16-bit relative addressing while
BHI is a 2-byte instruction using 8-bit relative addressing. See LBRA and BHI for details
on the operation of LBH I.

LBHS - Long Branch If Higher or the Same (C - 0)


Object No. of No. of
Code Cycles Bytes

LBHS 10 24 5(6) 4

LBHS is the same as LBRA except that it causes a branch under the same condi­
tion as does BHS. LBHS is a 4-byte instruction using 16-bit relative addressing while
BHS is a 2-byte instruction using 8-bit relative addressing. See LBRA and BHS for
details on the operation of LBHS.

LBLE - Long Branch If Less Than or Equal To Zero


(Z + (N El1 V) 1) =

Object No. of No. of


Code Cycles Bytes

LBLE 10 2F 516) 4

LBLE is the same as LBRA except that it causes a branch under the same condi­
tion as does BLE. LBLE is a 4-byte instruction using 16-bit relative addressing while
BLE is a 2-byte instruction using 8-bit relative addressing. See LBRA and BLE for
details on the operation of LBLE.
22-44 6809 Assembly Language Programming

LBLO - Long Branch If Lower (C - 1)


Object No. of No. of
Code Cycles Bytes

LBLO 10 25 5(6) 4

LBLO is the same as LBRA except that it causes a branch under the same condi­
tion as does BLO. LBLO is a 4-byte instruction using 16-bit relative addressing while
BLO is a 2-byte instruction using 8-bit relative addressing. See LBRA and BLO for
details on the operation of LBLO.

LBLS- Long Branch If Lower or Same (C + Z - 1)


Object No. of No. of
Code Cycles Byte a

LBLS 10 23 5(6) 4

LBLS is the same as LBRA except that it causes a branch under the same condi­
tion �s does BLS. LBLS is a 4-byte instruction using 16-bit relative addressing while BLS
is a 2-byte instruction using 8-bit relative addressing. See LBRA and BLS for details on
the operation of LBLS.

LBLT- Long Branch If LESS Than Zero (N 61 V - 1)


Object No. of No. of
Code Cycles Bytes

LBLT 10 20 5(6) 4

LBL T is the same as LBRA except that it causes a branch under the same condi­
tion as does BLT. LBLT is a 4-byte instruction using 16-bit relative addressing while
BLT is a 2-byte instruction using 8-bit relative addressing. See LBRA and BL T for
details on the operation of LBLT.

LBMI - Long Branch If Minus (N - 1)


Object No. of No. of
Code Cycles Bytes

LBMI 10 28 5(6) 4

LBMI is the same as LBRA except that it causes a branch under the same condi­
tion as does BMI. LBMI is a 4-byte instruction using 16-bit relative addressing while
BMI is a 2-byte instruction using 8-bit relative addressing. See LBRA and BMI for
details on the operation of LBMI.

LBNE- Long Branch If Not Equal To Zero (Z - 0)


Object No. of No. of
Code Cycles Bytes

LBNE 10 26 516) 4
Descriptions of Individual 6809 Instructions 22-45

LBNE is the same as LBRA except that it causes a branch under the same condi­
tion as does BNE. LBNE is a 4-byte instruction using 16-bit relative addressing while
BNE is a 2-byte instruction using 8-bit relative addressing. See LBRA and BNE for
details on the operation of LBNE.

LBPL - Long Branch If Plus (N - 0)


Object No. of No. of
Code Cycles Bytes

LBPL 10 2A 5(6) 4

LBPL is the same as LBRA except that it causes a branch under the same condi­
tion as does BPL. LBPL is a 4-byte instruction using 16-bit relative addressing while
BPL is a 2-byte instruction using 8-bit relative addressing. See LBRA and BPL for
details on the operation of LBPL.

LBRA - Long Branch Always

Object No. of No. of


Code Cycles Bytes

LBRA 16 5 3

LBR A places the specified address in the Program Counter, thus always causing a
program branch. The specified address is the sum of the current value of the Program
Counter (after the processor has fetched the LBRA instruction from memory) and the
displacement.
Data
Memory

E H N Z V C

[){:
X
Program
y Memory

PC mm mm
---
.....


mmmm+
+ 152E
) 16 mmmm

{
DP 15 mmmm + 1

2E mmmm + 2

mmmm + 3
LBRA *+1531
22-46 6809 Assembly Language Programming

If mmmm = 102316, then after execution of LBRA *+$1531, the Program


Counter would contain 1023 + 3 + 152E = 255416 and execution would continue with
the instruction at that location.
The displacement - the contents of the second and third bytes of the instruc­
tion - forms a 16-bit twos complement number. Thus the overall effect of an LBRA
instruction is:
PC = PC + 3 + disp

The extra factor of 3 is the result of the 3 bytes occupied by the LBRA instruction itself.
LBRA does not affect any flags or registers except the Program Counter (its previous
value is lost). Note that LBRA requires only a 1-byte operation code, while the various
conditional long branches (LBCC, LBCS, LBEQ, etc.) require 2-byte operation codes.
Thus the displacement formula for the long conditional branches is
PC =PC + 4 + disp

Since the displacement is now a 16-bit twos complement number, its range has
increased to
-3276810(1000 0000 0000 0000) .$. disp .$. + 3276710(0111 1111 1111 11112)

the range of the long branches is therefore

•- 3276410 �destination� • + 3277 110

where* refers to the value of the Program Counter at the start of the instruction. Con­
sider the following section of a program:

.------ LBRA NEXT


ANDA =IF$7F

NEXT CLRA

After the LBRA instruction, the processor will always execute the CLRA instruc­
tion next. It will never execute the ANDA instruction unless a branch or jump instruc­
tion somewhere else in the program jumps to that instruction.
See the description of BRA for the short relative form, used when the destination
is close enough for a one-byte offset.

LBRN - Long Branch Never

Object No. of No. of·


Code Cycles Bytes

LBRN
10 21 5 4

LBRN is the same as LBRA except that, like BRN, no branch ever occurs. Thus
LBRN is essentially a no-operation; that is, control always passes to the next instruction
with no other changes ever occurring. Note that LBRN is a 4 byte no-op, since it
requires a 2-byte operation code followed by a 2-byte relative address (BRN is a 2-byte
no-op). Of course, the relative address could have any value, since it will never be used.
LBRN is useful as a byte filler or for tuning a delay routine. Generally it is not a very
useful instruction; it makes the set of long branches logically complete. See the descrip­
tion of NOP for a discussion of uses for no-operations.
Descriptions of Individual 6809 Instructions 22-47

LBSR - Long Branch to Subroutine

Object No. of No. of


Code Cycles Bytes

LBSR 17 9 3

LBSR is the same as LBRA except that it saves the value of the Program Counter
in the same fashion as BSR. LBSR offers 16-bit relative addressing while BSR offers 8-
bit relative addressing. Note that LBSR requires a one-byte operation code as does
LBRA. See LBRA and BSR for details on the operation of LBSR.

lBVC - long Branch If Overflow Clear (V = 0)


Object No. of No. of
Code Cycles Byteo

LBVC 10 28 5(6) 4

LBVC is the same as LBRA except that it branches under the same condition as
BVC. LBVC is a 4-byte instruction using 16-bit relative addressing while BVC is a 2-byte
instruction using 8-bit relative addressing. See LBRA and BVC for details on the opera­
tion of LBVC.

LBVS - long Branch If Overflow Set (V - 1)


Object No. of No. of
Code Cycles Byteo

LBVS 10 29 5(61 4

LBVS is the same as LBRA except that it branches under the same condition as
BVS. LBVS is a 4-byte instruction using 16-bit relative addressing while BVS is a 2-byte
instruction using 8-bit relative addressing. See LBRA and BVS for details on the opera­
tion of LBVS.

lO- load Register from Memory


LOA
LOB
LOD
LOS
LOU
LOX
LOY
lmmediete Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycleo Byteo Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

LOA 86 2 2 96 4 2 86 5 3 A6 4+ 2+
LOB C6 2 2 06 4 2 F6 5 3 E6 4+ 2+
LDD cc 3 3 DC 5 2 FC 6 3 EC 5+ 2+
LOS 10 CE 4 4 10 DE 6 3 10 FE 7 4 10 EE 6+ 3+
LOU CE 3 3 DE 5 2 FE 6 3 EE 5+ 2+
LOX BE 3 3 9E 5 2 BE 6 3 AE 5+ 2+
LOY 10 BE 4 4 10 9E 6 3 10 BE 7 4 10 AE 6+ 3+
22-48 6809 Assembly Language Programming

This instruction loads the contents of the selected memory byte(s) into the
specified register and sets the Condition flags accordingly. There are two forms of this
instruction, an 8-bit form and a 16-bit form. The 8-bit form is associated with
Accumulators A and B, while the 16-bit form is associated with the 16-bit registers D,
X, Y, S, and U.
Consider an 8-bit LD using indirect indexed addressing with a double accumula­
tor (D) offset from Index Register X; Accumulator B receives the data.

Data
Memory

E F H N Z V C

ccR ._l_....
...._ ...._ _l x ...�._
...... x l_o I
l .... ...._...
tt ppqq + rrss

uu ppqq rrss
+ 1
+

yy ttuu

D {: t----::--4 } -----..+
X pp qq
Program
y Memory

E6 mmmm

98 mmmm + 1

mmmm + 2

+ 3
LDB [D,X]
mmmm

Suppose that ppqq = 13E 116, rrss = 208816, ttuu (the contents of memory loca­
tions 3499 and 349A) = A47D16, and yy (the contents of memory location A47D) =

AA16. After the processor executes the instruction LDB [D,X], Accumulator B will con­
tain AA10.

AA = 1 01 0 1 01 0- Nonzero result resets Z to 0

Bit 7 sets N to 1 ) V is cleared

Now consider the 16-bit LD of the double accumulator using indirect indexed
addressing with autoincrementing (by 2) of Index Register Y.
Descriptions of Individual 6809 Instructions 22-49

Data
Memory

E F H N z v c

CCR I I I I I I
X X
0 tt rrss

uu rrss + 1

XX XX ttuu
o{: VY vv ttuu + 1

X
Program
y rr ss Memory

PC mm mm EC mmmm

DP 81 mmmm + 1

mmmm + 2

LDD !.Y++I mmmm + 3

Suppose that rrss 8E05H , ttuu (the contents of memory locations 8E05 and 8E06)
= =

839416, xx (the contents of memory location 8394) 0716, and yy (the contents of =

memory location 8395) = F216• After the processor has executed the instruction LDD
[,Y + +], Accumulator A will contain 0716, Accumulator B will contain F216 (thus
Accumulator D will contain 07F216), and Index Register Y will contain 8E0516+2
8E0716•

07F2 = 0000 0111 1111 0010- Nonzero result resets Z to 0

Bit 1 5 resets N to 0 / V is cleared always.

Note that the flags are affected according to the 16-bit value being loaded and not the
separate 8-bit values.

LEA - Load Effective Address Into 16-Bit Register


LEAS
LEAU Object No. of No. of
Code Cycles Bytes
LEAX
LEAS 32 4+ 2+
LEAY LEAU 33 4+ 2+
LEAX 30 4+ 2+
LEAY 31 4+ 2+

Form an effective address using one of the indexed addressing modes. Load that
address into a 16-bit register (Index Register X, Index Register Y, Hardware Stack
PointerS, or UserStack Pointer U).
We will illustrate LEA using the indirect indexed mode based on a 16-bit constant
offset from the Program Counter. The result is stored in Index Register X.
22-50 6809 Assembly Language Programming

E F H N z v c
CCR I I I
X
Program
Memory

30 mmmm

o{: 9D mmmm + 1

X XX yy 02 mmmm + 2

y 3C mmmm + 3

u mmmm + 4

PC mm mm

DP XX mmmm + 4 + 023C

yy mmmm + 4 + 0230
LEAX [$023C.PC]

Suppose that mmmm = E385 1<, xx (the contents of memory address E389 + 023C =

E5C5) = DE16, and yy (the contents of memory address E5C6) = 2F16. After the pro­
cessor executes the instruction LEAX [$023C,PC], Index Register X will contain
DE2F16 and the Zero flag will be cleared since the result is not zero. Note that LEAX
and LEA Y affect the Zero flag, while LEAU and LEAS do not; this difference is necess­
ary to maintain compatibility with the 6800 microprocessor. The 6809 assembler trans­
lates the 6800 instructions DEX and INX into LEAX instructions (LEAX -1 ,X and
LEAX 1 ,X respectively); 6800 programs often use DEX or INX for counting purposes
and employ the zero flag as an exit condition.
The LEA instruction brings to the programmer a great deal more capability
than a casual examination would suggest. It permits the easy generation of position­
independent code and simplifies the handling of local data on stacks, as well as per­
mitting the implementation of several other interesting and useful operations.
The following program segment illustrates one use of LEA. The table of values is
located 10016 bytes from the occurrence of the LEAX instruction. At assembly time,
the assembler computes this offset and inserts it as the two bytes following the LEAX
code. Note that the post byte for the two-byte offset case is 80. Note also that the offset
is the distance from the updated PC following execution of LEAX.
0100 lO qo 0109 START LEAX TABLE,PCR
0104 Ae. 80 LOOP LDA ,X+
010e.

0 20D TABLE FCC /TARLE OF CHARACTERS/

Assume that the program is stored at the locations shown. During execution, the offset
0109 is added to the updated program counter value (0104) to yield address TABLE
(0200). This value is loaded into Index Register X, rather than output on the address
bus. When the indexed instruction LOA ,X+ is executed, this newly computed address
(stored in the index register) is used to access data from the table.
Descriptions of Individual 6809 Instructions 22-51

LEA can also be used to perform arithmetic on the contents of index registers
and stack pointers. For example,

1. LEAX l,X increments (adds 1 to) the contents of Index Register X.


Similarly, LEA Y -l,Y decrements (subtracts 1 from) the contents of Index
Register Y.
2. LEAU $2COS,U adds 2C0516 to the contents of the User Stack Pointer.
3. LEAX O,PC loads the Program Counter value at the end of the instruction
into Index Register X. Note that, in position-independent code, it may be
essential to determine that value and make it readily available for use in
addressing.

LSL- Shift Accumulator or Memory Byte Left Logically


LSLA
LSLB
LSL
Inherent Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. o f No. of Object No. of No. of
Code Cycles tlytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

lSl 08 6 2 78 7 3 68 6+ 2+
lSlA 48 2 1
lSlB 58 2 1

Perform a one-bit logical left shift of the contents of Accumulator A or B or the


contents of a selected byte of memory. This instruction is exactly the same as Arithmetic
Shift Left or ASL; consult ASL for a description of its execution. The mnemonic is
available for the sake of completeness.

LSR- Shift Accumulator or Memory Byte Right Logically


LSRA
LSRB
LSR
Inherent Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. o f No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

LSR 04 6 2 74 7 3 64 6+ 2+
lSRA 44 2 1
lSRB 54 2 1

The LSR instruction is identical to the ASR instruction except that LSR causes a 0
to be shifted into bit 7 instead of keeping it intact as does the ASR instruction. Flags are
affected the same way by both instructions except for the H flag, which is not affected by
LSR. Of course in the LSR instruction, the N flag is cleared since bit 7 is cleared. Con­
sult ASR for more details on LSR.

MUL- Multiply Unsigned Numbers


Object No. of No. of
Code Cycles Bytes

MUl 3D 11 1
22-52 6809 Assembly Language Programming

Multiply the unsigned number in Accumulator A by the unsigned number in


Accumulator B. Place the result in both accumulators with the most significant bits in
Accumulator A - that is, Accumulator D holds the result.

Data
Memory

E F H N Z V C

ccR _I __...___ ...._.l_. x ..._l...-


1 x_)

XX

o{: XX X yy
yy }� �
X
Program
y
Memory

PC mm mm
- ::X. mmmm + 1 30 mmmm

DP mmmm + 1

mmmm + 2

mmmm + 3
MUL

If, for example, Accumulator A contains 6F111 and Accumulator B contains 6 1111, after
the processor executes the MUL instruction, Accumulator A will contain 2A1 6 and
Accumulator B will contain OF16 (that is, Accumulator 0 will contain 2AOF 16).

6F = 011 0 1111
61 = 0110 0001
0110 1111
0 1101 111
01 1011 11
0010 1010 0000 1111 -Nonzero result resets Z to 0.

'-------�>- Bit 7 resets C to 0.

Only two flags are affected by MUL:

1. The Zero flag is set if the entire result is zero and cleared otherwise.
2. The Carry flag is set to the final value of bit 7 of Accumulator B, thus allowing
rounding to an 8-bit result in A with the sequence:

MUL MULTIPLY
/\DCA ROUND TO R BITS
Descriptions of Individual 6809 Instructions 22-53

NEG - Twos Complement (Negate) Accumulator or Memory


NEGA
NEGB
NEG
Inherent Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

NEG 00 6 2 70 7 3 60 6+ 2+
NEGA 40 2 1
NEGB 50 2 1

This instruction replaces the contents of the selected accumulator or the specified
byte of memory with its twos complement. The twos complement of a number is the
value that, when added to the original number, produces a sum of zero. The twos com­
plement of n is thus 0- n.
Consider twos complementing Accumulator A.
Data
Memory

E F H N Z V C

ccR ( __.___...l_x-'-1�� ....


_
x l_.. _.x l_x""-I �lx

_- ....,... Xx'+1
XX
-- ( same as
D{: 0- XX

X
Program
y Memory

s
--
1
PC mm mm
......
-"I mmmm + 40 mmmm

DP mmmm +

mmmm + 2

mmmm + 3
NEGA

If, for example, Accumulator A contains 3A16, after the processor executes the NEGA
instruction, Accumulator A will contain C616•

Ones complement of 3A = 11 00 01 01
+ 1 = 1
11 00 01 1 0- Nonzero result resets Z to 0

ll
++------ 0 ¥ 0 = 0. reset V to 0

'------ Bit 7 sets N to 1

'------ A borrow sets C to 1

H is undefined.
22-54 6809 Assembly Language Programming

The Carry flag (C) represents a borrow and is set to the complement of the resulting bin­
ary carry. The V flag is set if and only if the original operand was 1000 00002• The value
0016 is replaced by itself, and only in this case is C cleared.
In the illustration above, we defined the twos complement as the ordinary (ones)
complement plus 1. The sum of any number and its ones complement must have ones
in every bit position, since any position that is 0 in the original number will be 1 in the
ones complement and vice versa. Adding 1 to the number with ones in every bit position
gives a sum of zero (with a carry, which is ignored), so adding 1 to the ones complement
must give the twos complement.

NOP - No Operation
Object No. of No. of
Code Cycles Bytes

NOP 12 2 1

NOP is a one-byte instruction that does nothing except increment the program
counter.
Typical uses of NOP are the following:

1. To provide a position for a label without affecting the object program.


2. To produce a precise delay time. Each NOP instruction adds two clock cycles
to the execution time of a sequence.

3. To replace instructions that are no longer needed because of corrections or


changes.
4. To replace instructions (such as subroutine calls) that you may not want to
include in debugging runs.

NOP is seldom used in completed programs, but it is often quite handy in the debug­
ging and testing stages.

OR - logical (Inclusive) OR
ORA
ORB
ORCC
Immediate Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

ORA BA 2 2 9A 4 2 BA 5 3 AA 4+ 2+
ORB CA 2 2 OA 4 2 FA 5 3 EA 4+ 2
ORCC lA 3 2

This instruction logically (inclusive) ORs the contents of a memory location with
the contents of Accumulator A or B or the Condition Code Register. Only immediate
addressing can be used with CCR.
First consider the accumulator OR using immediate addressing and Accumulator
A.
Descriptions of Individual 6809 Instructions 22-56

Data
Memory

E F H N Z V C

f o
cc R ______l_ x..l _x
._ J_
._ .... .._l _.

-- ..,.,..

o{: XX
� �{ XX v AB

X
Program
y Memory

PC mm mm mmmm + 2 SA mmmm
--
-"1.
DP AB mmmm + 1

ORA *$AB mmmm + 2

Suppose that xx E316• After the processor has executed the instruction ORA *$AB,
Accumulator A will contain EB16.
=

E3 = 1110 0011
AB = 1010 1011

1 110 1011 -- Nonzero result resets Z to 0

L------ Bit 7 sets N to 1

V is always cleared

OR is a common logical instruction, most often used to set a bit to a '1' value. For
example, the instruction ORA =ll=<Yu 10000000 sets bit 7 of Accumulator A to 1 while leav­
ing the other bits of the accumulator unchanged. Note that logically ORing a bit position
with a '1' produces a result of' 1' , while logically ORing a bit position with '0' leaves the
value unchanged. Now consider the ORCC instruction. Data
Memory

E F H N

CCR

n{:
X
Program
y Memory

PC mm mm 1A mmmm

DP 40 mmmm + 1

ORCC *$40 mmmm + 2


22-56 6809 Assembly Language Programming

This instruction logically ORs the contents of the following byte of program memory
with the contents of the Condition Code Register. This has the effect of setting all the
flags that are logically ORed with '1 's and leaving unchanged all the flags that are
logically ORed with 'O's. The following patterns will set individual flags:

Flag Required Mask

Binary Hexadecimal

E 10000000 80
F 01000000 40
H 00100000 20
I 00010000 10
N 00001000 08
z 00000100 04
v 00000010 02
c 00000001 01

Of course, setting more than one bit position will set more than one flag at a time.
However, only a few of the possible operations are really useful. In particular, we should
note:
ORCC ij%01()00000 DISABLE FAST INTERf\UPTS
OIKC IJ%00Cl0000 DISABLE REGULAR INTERRUPTS
ORCC �%00000010 SP.T OVERFLOW
once II ':;O 0 0000 0 l SET CARRY

Remember that setting an interrupt mask disables the interrupt from that source.

PSH - Push Registers onto the Stack


PSHU

I
Object No. of No. of
PSHS Code Cycles Bytes

J
PSHS 34 5+ 2+
PSHU 36 5+ 2+

The PSH instruction will push onto either stack any or all registers except the
Stack Pointer being used. Consider pushing both index registers onto the Hardware
Stack.
Data
Memory

E F H N Z V C

pp ssss - 4

qq ssss - 3

tt ssss - 2

uu ssss - 1
o{; ssss

X PP qq
Program
y tt uu
Memory

s ss ss

PC mm mm 34 mmmm

DP 30 mmmm + 1

PSHS X.Y mmmm + 2


Descriptions of Individual 6809 Instructions 22-57

The second byte of the instruction specifies the registers to be saved as follows:

7 6 5 4 3 2 0 4
...
.... -Bit No.
-

Object Code

Each bit position that contains 1 causes the corresponding register to be saved on the
stack. If th. register is 16 bits in length, the process_,; saves its contents as follows:

1. Decrement the Stack Pointer and store the low-order byte of the register at
the address in the Stack Pointer.

2. Decrement the stack pointer again and store the high-order byte of the
register at the address in the Stack Pointer.

If the register is 8 bits long, the processor performs only one storage operation and
decrements the stack pointer only once.
The order is as follows (with the lowest memory address at the top):

Condition Code Register


Accumulator A
Accumulator 8
Direct Page Register
Index Register X (HI)
Push Order Index Register X (LO)
Index Register Y (HI)
Index Register Y (LO)
User Stack Pointer/Hardware Stack Pointer (HI)
User Stack Pointer/Hardware Stack Pointer (LO)
Program Counter (HI)
Program Counter (LO)
22-58 6809 Assembly Language Programming

Note that some (or even all) of the registers can be omitted. The processor decre­
ments the Stack Pointer once for each byte that it saves. The internal hardware deter­
mines the order in which registers are stacked; the order in which the programmer
specifies registers does not matter. For example, the instructions PSHS A,B,X,DP and
PSHS DP,A,B,X are identical. You may specify the double accumulator D instead of A
and B.
Note that the Hardware Stack Pointer (S) cannot be pushed onto the Hardware
Stack, nor can the User Stack Pointer (U) be pushed onto the User Stack. Thus the stack
in use determines the meaning of bit 6 of the post byte. Setting bit 6 for PSHS will cause
the User Stack Pointer to be pushed onto the Hardware Stack, while setting bit 6 for
PSHU will cause the Hardware Stack Pointer to be pushed onto the User Stack.

PUL- Pull Registers from the Stack


PULU
PULS
Object No. of No. of
Code Cycles Bytes

PULS 35 5+ 2+
PULU 37 5+ 2+

The PUL instruction will pull from either stack any or all registers except the
designated Stack Pointer. Consider pulling the Condition Code Register (CCR), Index
Register Y, and the Direct Page Register (DP) from the user stack.
Data
Memory

E F H N Z V C

CCR yyyy yyyy ssss

pp ssss + 1

tt ssss + 2

uu ssss + 3
o{: ssss + 4

X
Program
y tt uu Memory

u ss ss

PC mm mm 37 mmmm

DP 29 mmmm + 1

mmmm + 2

PULU CCR,Y,DP mmmm + 3

The second byte of the instruction specifies the registers to be loaded exactly as for
PSH. The order in which registers are pulled from the stack is the opposite of that in
which they are pushed. As with PSH, you can omit any or all of the registers, you cannot
Descriptions of Individual 6809 Instructions 22-59

pull a stack pointer from its own stack, and the order in which registers are specified in
the assembly language instruction has no effect on the order in which they are pulled
from the stack.
Note that, unless you are loading the Condition Code Register itself, loading
registers in this way does not affect the flags. If you wish to load a register from a stack
and affect the flags, you should use the LD instruction in the autoincrement mode with
the appropriate Stack Pointer. For example, to load Index Register Y from the user stack
and set flags accordingly, use the instruction LOY , U + +.
The instruction PULU PC loads the Program Counter from the user stack and
thus serves as a Return from Subroutine instruction in which the linkage is in the
user stack, rather than the Hardware Stack. Pulling any set of registers that
includes the Program Counter has a similar effect. The programmer can transfer con­
trol to and from subroutines through the user stack; a sequence like

PSHU PC
JMP SUBR

transfers control to subroutine SUBR after saving the Program Counter in the user
stack. Note, however, that the subroutine will have to increment the return address past
the JMP instruction.

ROL - Rotate Accumulator or Memory Byte Left through Carry


ROLA
ROLB
ROL

Inherent Otrect Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

ROL 09 6 2 79 7 3 69 6+ 2+
ROLA 49 2 1
ROLB 59 2 1

This instruction rotates the specified accumulator or the selected byte of memory
one bit to the left through the Carry flag.
Consider rotating a memory byte using indexed addressing with zero offset from
Index Register Y.
22-60 6809 Assembly Language Programming

Data
Memory

E F H N Z V C

CCR

0 {: �----1

X
Program
y PP qq Memory

PC mm mm 69 mmmm

OP A4 mmmm + 1

mmmm + 2

mmmm + 3
ROL .Y

For example, suppose that pp = 1416, qq = 0316, the contents of memory location 1403
are 2E16, and the Carry flag contains 0. After the processor executes the instruction ROL
,Y memory location 1403 will contain 5C16 and the Carry flag will contain 0.

Carry Location 1403

0 0010 1110

0 ------- J1 01 1100 -Nonzero result resets Z to 0

'--- ---- l
�c--- -----0 ¥
L.
-

-----
..-
� =

.. Bit 7 resets N to
0. reset V to 0

The overflow flag (V) is loaded with the Exclusive-OR of bits 7 and 6 of the original
operand; these bit values are the same as those of the resulting Carry (C) and Sign (N)
flags.
The ROL instruction can be used to include the Carry in multiple-byte shifts
and to move serial U-bit) data to or from the Carry flag.

ROR - Rotate Accumulator or Memory Byte Right through


RORA Carry
RORB
ROR
Inherent Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of I Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

ROR 06 6 2 76 7 3 66 6+ 2+
RORA 46 2 1
RORB 56 2 1
Descriptions of Individual 6809 Instructions 22-61

This instruction is the same as ROL except that the rotation is from left to right.
The flags are affected in the same way except that C is now loaded with bit 0 and V is
unaffected. Consult the description of ROL for more details.

RTI - Return from Interrupt

Object No. of No. of


Code Cycles Bytes

ATI 38 6/15 1

This instruction restores the state of an interrupted task by loading the Condition
Code Register and Program Counter from the hardware stack. If the Entire flag (E) is
set, the instruction loads all the other user registers from the hardware stack.
Program
Memory

1 yyyyyyy ssss

XX ssss + 1

yy ssss + 2

dd ssss + 3

pp ssss + 4

qq ssss + 5

tt ssss + 6

uu ssss + 7

vv ssss + 8

ww ssss + 9

CCR jj ssss + A

kk ssss + B

ssss + c

XX
o{: yy

X pp qq
Program
y ._J! uu Memory

w
u vv ww

s ss ss

PC jj kk mmmm

DP dd mmmm + 1

mmmm + 2

RTI
mmmm + 3
22-62 6809 Assembly Language Programming

Suppose that yyy yyyy = 11011012, xx = CB16, yy = 1416, dd = 2E16, ppqq = 37Al16,
ttuu = E50B11, vvww = 027F16, andjjkk = E 11516•
After the processor executes the RTI instruction, the registers will appear as follows:
CCR=111011012
A= CB
B= 14
DP= 2E
X= 37A1
Y = E50B
U = 027F
PC = E11 5 Execution will continue from this address.

F irst, the condition code is pulled from the stack, and the contents of bit 7 (E ) are
examined by the hardware of the CPU to determine whether the entire machine status
has been stacked, or just the subset CCR and PC. The order of the registers in the stack
is the same as in the instructions PSHS and PULS. Note that, as in those instructions,
the Hardware Stack Pointer is not saved in its own stack.
The interrupt masks will be automatically restored to their original states. The pre­
vious values of all the user registers are lost. The Hardware Stack Pointer ends with a
value 12 (C16) larger than its starting value when E is set and a value 3 larger when E is
cleared (by a Fast Interrupt request).

RTS - Return from Subroutine

Object No. of No. of


Code Cycles Bytes

RTS 39 5 1

Program control is returned from the subroutine to the calling program by pulling
the return address from the stack and placing it in the Program Counter.
Data
Memory

E F H N Z V C

pp ssss

qq ssss + 1

ssss + 2
o{;
X
Program
y Memory

s ss ss

PC mm mm 39 mmmm

DP mmmm + 1

mmmm + 2
RTS
mmmm + 3
Descriptions of Individual 6809 Instructions 22-63

The previous contents of the program counter are lost. The processor increments the
Hardware Stack Pointer after loading each byte, so the final value of that pointer is two
larger than its starting value.
Each subroutine normally contains at least one RTS instruction; this is the
last instruction executed within the subroutine and causes control to return to the
calling program. RTS does not affect any flags. Note, however, that no RTS instruc­
tion is necessary if the last instruction in the subroutine restores a set of registers
including the program counter from the hardware stack. For example, the instruction
PULS A,B,CC,PC will restore Accumulators A and B and the Condition Code Register
from the hardware stack before returning control to the main program. Of course, the
subroutine must include an appropriate PSHS instruction, such as PSHS A,B,CC.

SBA - Subtract Accumulator B from Accumulator A

The 6809 assembler translates this 6800 instruction into


PSHS 8
SUBA , S+

This instruction subtracts Accumulator B from Accumulator A and sets the condition
flags accordingly. The 6809 assembler handles this instruction to allow source com­
patibility with the 6800 processor.

SBC - Subtract Memory from Accumulator with Borrow


SBCA
SBCB

Immediate Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

SBCA 82 2 2 92 4 2 82 5 3 A2 4+ 2+
SBCB C2 2 2 02 4 2 F2 5 3 E2 4+ 2+

This instruction subtracts the contents of the selected byte of memory and the
contents of the carry flag from the contents of the specified accumulator.
Consider SBCB using an 8-bit constant offset from Index Register Y.
22-64 6809 Assembly Language Programming

Data
Memory

E F H N Z V C

CCR

yy ppqq + 3E

X
Program
y pp qq Memory

PC mm mm E2 mmmm

DP AS mmmm + 1

3E mmmm + 2

mmmm + 3
SBCB $3E.Y

Suppose that ppqq = 10 5A 11 , , xx = 1416, yy (contents of address 1098) = 3416, and C =

1. After the processor executes the instruction SBCB $3E, Y the contents of Accumula­
tor B will be DF 111•

14 = 000 1 01 00
Twos complement of 1 = 1111 1 11 1
0001 0011
Twos complement of 34 = 1100 1100
1101 1 11 1 - Nonzero result resets Z to 0

'Il L__ 0 ¥0 = 0, reset V to 0


.

t==:
B1t 7 sets N to 1

L__
_____ Borrow sets C to 1

H is undefined

Note that C is the complement of the resulting carry since it represents a borrow.
The most common use of SBC is in implementing multiple-precision
arithmetic; this instruction allows borrows from previous byte-length operations to
be included in the current byte-length operation.

SEC - Set Carry Flag

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction ORCC=*F0ht 00000001 -that is, into an instruction that sets to 1 the least sig­
nificant bit of the condition code register (the carry flag). No other flags or registers are
affected. The COM instruction also sets the carry flag.
Descriptions of Individual 6809 Instructions 22-65

SEF - Set Fast Interrupt Mask

The 6809 assembler translates this 6800-like instruction into the equivalent 6809
instruction ORCC =#=%01000000 -that is, into an instruction that sets to 1 bit 6 of the
Condition Code Register (the fast interrupt mask). This instruction disables the fast
interrupt-that is, the 6809 will not respond to the fast interrupt request control line.
No other registers or flags are affected.

SEI - Set Interrupt Mask

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction ORCC =#=%00010000-that is, into an instruction that sets to 1 bit 4 of the
Condition Code Register (the regular interrupt mask bit). This instruction disables the
6809's regular interrupt -that is, the 6809 will not respond to the interrupt request
control line. No other registers or flags are affected.

SElF - Set Regular and Fast Interrupt Masks

The 6809 assembler translates this 6800-like instruction into the equivalent 6809
instruction ORCC=#=%01010000- that is, into an instruction that sets to 1 bits 4 and 6
of the condition code register (the fast and regular interrupt mask bits). This instruction
disables both of the 6809's maskable interrupts -that is, the 6809 will not respond to
either the fast interrupt request control line or to the (regular) interrupt request control
line. No other registers or flags are affected.

SEV- Set Overflow Flag

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction ORCC =#=%00000010-that is, into an instruction that sets to 1 bit 1 of the
Condition Code Register (the overflow flag). No other flags or registers are affected.

SEX- Sign Extend Accumulator B into Accumulator A

Object No. of No. of


Code Cycles Bytes

SEX 1D 2 1

This instruction transforms an 8-bit twos complement number in Accumulator B


into a 16-bit twos complement number in Accumulator D.
22-66 6809 Assembly Language Programming

Data
Memory

CCR

X
Program
y Memory

10 mmmm

mmmm + 1

mmmm + 2

mmmm + 3
SEX

SEX accomplishes this transformation by extending bit 7 of Accumulator B into


Accumulator A. Thus Accumulator A is set to 0016 if bit 7 of Accumulator B is 0 and to
FF 16 if bit 7 of Accumulator B is 1. SEX affects the sign flag (set according to the most
significant bit of the result - the same as bit 7 of Accumulator B) and the Zero flag (set
if the result is zero - that is, if Accumulator B contains zero). This instruction is use­
ful in performing twos complement and floating point arithmetic.

ST - Store Register into Memory


STA
STB
STD
STS
STU Direct Extended Indexed/Indirect

STX Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes
STY
STA 97 4 2 B7 5 3 A7 4+ 2+
STB 07 4 2 F7 5 3 E7 4+ 2+
STD DD 5 2 FD 6 3 ED 5+ 2+
STS 10 OF 6 3 10 FF 7 4 10 EF 6+ 3+
STU OF 5 2 FF 6 3 EF 5+ 2+
STX 9F 5 2 BF 6 3 AF 5+ 2+
STY 10 9F 6 3 10 BF 7 4 10 AF 6+ 3+

Store the contents of the specified register at the selected memory address. There
are two forms of this instruction, an 8-bit form and a 16-bit form. The 8-bit form is as­
sociated with Accumulators A and B, while the 16-bit form is associated with the 16-bit
registers 0, X, Y, S and U.
Consider the 8-bit case, storing Accumulator B using the indexed addressing
mode with a constant 16-bit offset from Index Register Y.
Descriptions of Individual 6809 Instructions 22-67

Data
Memory

E F H N z v c

CCR I I I I I I
X X
0

XX ppqq + 0302

o{: XX

X
Program
y pp qq Memory

PC mm mm E7 mmmm

DP A9 mmmm + 1

03 + 2
STB $0302,Y
mmmm

02 mmmm + 3

Suppose that xx = 6316 and ppqq = 023816• After the processor executes the
instruction STB $0302,Y memory location 053A will contain 6316.

63 = 01 10 001 1 --- Nonzero result resets Z to 0

Bit 7 resets N to 0 ) V is cleared always.

Now consider the 16-bit case, storing the D register using indexed addressing,
autoincrementing Index Register Y by 2.

Data
Memory

E F H N Z V C

CCR
-� .... ..._ j�....__ x..l_..�. x ....__l o -.I__.I
..._ ..
{ XX ppqq

yy ppqq + 1
------� �------�

ppqq + 2
1-----1

D
{ : �-----::----1
X
Program
y pp qq Memory

u
�------�--�
s

PC mm mm ED mmmm

DP A1 mmmm + 1
STD .Y++ mmmm +2
22-68 6809 Assembly Langu<�ge Programming

Suppose that ppqq 143016 , xx Cl16, and yy


= 9A16• After the processor has
= =

executed the instruction STD , Y + + memory location 1430 will contain C116, memory
location 1431 will contain 9A16, and Index Register Y will contain 14321 6•

C19A = 1100 0001 1001 1010- Nonzero result resets Z to 0.

'------ Bit 1 5 sets N to 1

V is always cleared

Note that the STS and STY instructions have a two byte object code, the first byte
being 1016.

SUB- Subtract Memory from Register


SUBA
SUBS
SUBD

Immediate Direct Extended Indexed/Indirect

Object No. of No. of Object N<J. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

SUBA 80 2 2 90 4 2 80 5 3 AO 4+ 2+
SU88 co 2 2 DO 4 2 FO 5 3 EO 4+ 2+
SU8D 83 4 3 93 6 2 83 7 3 A3 6+ 2+

Subtract the contents of the selected byte of memory from the contents of the
specified accumulator. There are two forms of this instruction, a one-byte form and a
two-byte form. The one-byte form uses an 8-bit accumulator (A or B), while the two­
byte form uses the 16-bit Accumulator D.
First consider 8-bit subtraction using Accumulator Band base page direct address-
mg.
Data
Memory

E F H N z v c
CCR I I I I I I I I
X X X X X
yy dd31

D{: XX

X
Program
y Memory

PC mm mm DO mmmm

DP dd 31 mmmm + 1

mmmm + 2

mmmm + 3
SUBB $31
Descriptions of Individual 6809 Instructions 22-69

Suppose, for example, that xx = E316, dd = 6816, and yy (in memory location
6B31) = A016• After the processor executes the instruction SUBB $31, the contents of
Accumulator B will be 43 16.

E3 = 1110 0011
Twos complement of AO = 0 110 0000
0100 0011 -- Non:tero result resets Z to 0
l

++----- 1 lJ + 0, reset to 0
1 = V

'----- 7
Bit resets N to 0
'------ No borrow. reset to C 0

H is undefined
The SUBA and SUBB instructions are used to perforiT! single-byte subtractions
or to perform the subtraction of the low-order bytes in multibyte operations.
Now consider the 16-bit form SUBD. We will illustrate its execution using
extended direct addressing.
Data
Memory
E F H N z v c
CCR I jxlxlxlx)
rr A074

ss A075

XX

o{: yy
X

y
Program
Memory
u

PC mm mm 83 mmmm

DP { �-Ao_ _---i mmmm + 1

SUBD $A074 74 mmmm + 2

For example, suppose that xx = 2A16, yy = E816, rr = 3716 and ss = E516• After
the processor executes the instruction SUBD $A074 , the contents of Accumulator D
will be F30316 - that is, Accumulator A will contain F316 and Accumulator B will con­
tain 0316•

::o::t:r:r:�:: �:s:t: Z to 0
2AE8 = 00 0 0 1 10 000
1fl111 10111 1 1
Twos complement of 37E5 = 1100 1000 0001 1011
00 0000 001 1 ---

s 00
'+-·-------------
Borrow sets to C

'------------+-Bit sets N to
Note that the Half-carry flag (H) is not affected by SUBD and that C is the com­
15 11
plement of the resulting carry, since it represents a borrow.
22-70 6809 Assembly Language Programming

SWI - Software Interrupt


SWI
SWI2
SWI3 Object No. of No. of
Code Cycles Bytes

SWI JF 19 1
SWI2 10 JF 20 2
SWI3 11 JF 20 2

This instruction increments the program counter, sets theE flag (bit 7 ofCCR)­
indicating that the entire state of the processor has been saved, and stores all the user
registers except the Hardware Stack Pointer in the hardware Stack. Control is then
passed through a vector table at the high end of memory.
Data
Memory

1yyy yyyy ssss- c

XX ssss- B

yy ssss- A

dd ssss - 9

pp ssss- 8

qq ssss- 7

tt ssss- 6

uu ssss- 5

vv ssss- 4

ww ssss- 3

CCR mm ssss - 2

mm + 1 ssss - 1

ssss

XX

o{: yy

X PP qq
Program
y tt uu
Memory

u vv ww

s ss ss

PC mm mm 3F mmmm

DP dd mmmm + 1

SWI

jj FFFA

kk FFFB
Descriptions of Individual 6809 Instructions 22-71

Note that control is passed to a service routine by placing into the program
counter the address located at FFF A and FFFB, and that the interrupt and fast interrupt
mask bits (bits 4 and 6 of the CCR) are set, disabling the maskable interrupts.
The processor stores the user registers in the same order as the PSHS instruction.
The final contents of the Hardware Stack Pointer are the original contents minus 12
(C16). The E flag is set to 1 so that an RTI instruction will restore the original state,
except that the Program Counter will have been incremented by 1. Thus an RTI will
cause the resumption of execution of the suspended program at the instruction
immediately following SWI. SWI disables both the regular interrupt and the fast inter­
rupt by setting the I and F bits of the CCR but only after the CCR has been pushed onto
the stack. Therefore interrupts are not honored during the SWI service routine, but
interrupt status is restored by execution of an R Tl.
Software interrupt instructions SWI2 and SWI3 are similar to SWI. The vector for
SWI2 is at FFF4 and FFF5, while the vector for SWI3 is at FFF2 and FFF3. SWI2 and
SWI3 are intended for the user, rather than the system software. Motorola guarantees
never to use SWI2 in any of its packaged software. SWI2 and SWI3 do not set the I and F
bits as does SWI, and thus interrupt status is maintained. SWI2 and SWI3 require two
byte operation codes.
The SWI instruction can be used for a variety of functions. The entry point for
any software package- a debug monitor, a disk operating system, or a group of
system subroutines - can be inserted into a software interrupt pointer. The software
system can then be entered by execution of a SWI instruction.

SYNC - Synchronize to External Event (Wait for Interrupt)

Object No. of No. of


Code Cycles Bytes

SYNC 13 2 1

This instruction simply halts CPU execution until a peripheral device requests
an interrupt. Any interrupt clears the halt. If the interrupt is enabled and lasts 3 cycles
or more, the processor will respond to it, stacking the registers and transferring control
to the appropriate vector address. If the interrupt is masked (disabled) or is shorter than
3 cycles long, the processor simply continues to the next instruction without stacking
registers or transferring control to a service routine. SYNC differs from CW AI as
follows:

1. SYNC does not provide a means for enabling interrupts during instruction
execution.
2. The processor tristates its busses while executing SYNC, but not while
executing CWAI.
3. SYNC provides a continuation exit without an interrupt response, whereas
CW AI requires an interrupt response.

SYNC is normally used with interrupts disabled as a HALT instruction which


is cleared by any interrupt input. CW AI is normally used with the appropriate inter­
rupt enabled as a Wait for Interrupt instruction. Figure 22-1 is a flowchart of the logic
of the SYNC instruction.
22-72 6809 Assembly Language Programming

Begin execution of
SYNC
the SYNC instruction

Interrupt Occurs Wait for any


interrupt

No

Continue Stack machine


execution at the Status transfer to
next instruction applicable interrupt
in sequence Service Routine

Figure 22-1. MC6809 SYNC Logic

TAB - Transfer Accumulator A to Accumulator B

The 6809 assembler translates this 6800 instruction into


TFH A,B
TSTA

This instruction transfers the contents of Accumulator B to Accumulator A and sets the
flags accordingly. The instruction is handled by the 6809 assembler to allow source com­
patibility with the 6800 processor.

TAP - Transfer Accumulator A to Condition Code Register

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction TFR A,CC - that is, into an instruction that transfers the contents of
Accumulator A to the Condition Code Register (CCR). The instruction is handled by
the 6809 assembler to allow source compatibility with the 6800 processor.

TBA - Transfer Accumulator B to Accumulator A

The 6809 assembler translates this 6800 instruction into


TFR 13,A
TSTA

This instruction is used to transfer data from one register to another. Data may
only be transferred between registers of like size. In contrast to the EXG instruction,
this is a one-way transfer. Consider the transfer from Accumulator A to B.

TFR - Transfer Register to Register

Object No. of No. of


Code Cycles Bytes

TFR 1F 7 2

This instruction transfers the contents of Accumulator A to Accumulator B and sets the
flags accordingly. The instruction is handled by the 6809 assembler to allow source com­
patibility with the 6800 processor.
Descriptions of Individual 6809 Instructions 22-73

Data
Memory

E F H N Z V C

::>
XX

o{:
X
Program
y Memory

mm
PC mm
-
- l. mmmm + 2 1F mmmm

DP 89 mmmm + 1

mmmm + 2

TFR A,B mmmm + 3

Suppose xx = 6A 16 and the original contents of Accumulator B are 5716. At the


end of the execution ofTFR A,B both accumulators will contain the number 6A1 6•

The TFR instruction has many miscellaneous applications:

1. Moving the contents of one accumulator to another - TFR A,B or TFR


B,A. Remember that only Accumulator A can be operated on with the
Decimal Adjust instruction.

2. Loading the direct page register - TFR A,DP. This instruction loads the
direct page register from Accumulator A. There is no LD instruction for the
direct page register.
3. Transferring control to an address contained in an Index Register - TFR
X,PC. This instruction loads the program counter with the contents of Index
Register X; the next instruction to be executed will be taken from that
address.

Note that TFR destroys the old contents of the destination register. You can save
those contents in the source register by using EXG instead. TFR, however, does not
change the contents of the source register.
AllTFR instructions require two bytes of program memory - the operation code
and the post byte (the immediate data), which specifies the source and destination
registers. Be careful of the fact that some TFR instructions are meaningless (undefined
register codes), while others are illegal (transferring contents between registers of
different sizes).
The post byte for the TFR instruction is identical to the post byte illustrated in the
EXG instruction description. The TFR post byte's higher order four bits define the
source register while the lower order four bits define the destination register. The flags
are unaffected unless CCR is the destination register.
22-74 6809 Assembly Language Programming

TPA - Transfer Condition Code Register to Accumulator A

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction TFR CC,A - that is, into an instruction that transfers the contents of the
Condition Code Register (CCR) to Accumulator A. The instruction is handled by the
6809 assembler to allow source compatibility with the 6800 processor.

TST - Test the Contents of an Accumulator or Memory Byte


TSTA
TSTB
TST

Inherent Direct Extended Indexed/Indirect

Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

TST 00 6 2 70 7 3 60 6+ 2+
TSTA 40 2 1
TSTB 50 2 1

This instruction sets the Sign and Zero flags according to the contents of the
specified accumulator or the selected byte of memory.
Consider testing a byte of memory addressed by Index Register Y with Accumula­
tor A offset.
Data
Memory

E F H N Z V C

yy ppqq + rr

Program
Memory
u
�------+---i
s

mm mm 60 mmmm

DP A6 mmmm + 1

mmmm + 2
TST A,Y
mmmm + 3

Suppose that Index Register Y contains 010016, Accumulator A contains 0211,, and
the contents of memory location 0102 are 0016• After the processor executes the instruc­
tion TST A, Y the sign and overflow flags will contain zero and the zero flag will contain
one. No registers or memory locations will be changed.
Descriptions of Individual 6809 Instructions 22-75

00 = 0000 0000- Zero result sets Z to 1

Bit 7 resets N to 0 _,}


V is always cleared

The TST instruction lets the programmer set the flags according to the contents
of an accumulator or a byte of memory without performing any operations or chang­
ing any registers.

TSX -Transfer Stack Pointer S to Index Register X

The 6809 assembler translates this 6800 instruction into the equivalent 6809
instruction TFR S,X - that is, into an instruction that transfers the contents of the
Hardware Stack Pointer S to Index Register X. The instruction is handled by the 6809
assembler to allow source compatibility with the 6800 processor. There is a slight
difference between the 6800 and 6809 stack pointers: the 6809 stack pointer points to
the last occupied byte of the stack, while the 6800 pointer indicates the next empty byte.
That is, the 6800 stack pointer value is one less than the 6809's for the same stack condi­
tion. Therefore, although TFR S,X does not increment the value before loading the
index register, as 6800 TSX does, the result is still a correct transfer of pointers.

TXS -Transfer Index Register X to Stack Pointer S

The 6809 assembler will translate this 6800 instruction into the equivalent 6809
instruction TFR X,S - that is, into an instruction that transfers the contents of Index
Register X to the Hardware Stack Pointer, S. The instruction is handled by the 6809 as­
sembler to allow source compatibility with the 6800 processor. There is a slight
difference between the 6800 and 6809 stack pointers: the 6809 stack pointer points to
the last occupied byte of the stack, while the 6800 pointer indicates the next empty byte.
That is, the 6800 stack pointer value is one less than the 6809's for the same stack condi­
tion. Therefore, although TFR X,S does not decrement the value before loading the
Stack Pointer, as 6800 TXS does, the result is still a correct transfer of pointers.

WAI - Wait for Interrupt

The 6809 assembler translates this 6800 instruction into the 6809 instruction
CW AI :#=$FF. This instruction is handled to allow source compatibility with the 6800
processor.
Appendices

The following section presents a complete set of reference tables for the 6809
instruction set.
Appendix A summarizes 6809 instruction operations and effects, and is organized
by function to display the capabilities of the 6809 processor. Appendix Bsummarizes the
indexed and indirect addressing modes: which modes are available, their assembly
language forms, and the resulting object code post bytes. For each instruction
mnemonic Appendix C shows the available addressing modes, its object code, execu­
tion time in machine cycles, and the number of bytes occupied by the instruction.
Appendices Band C can serve as aids to hand assembly of 6809 instructions. Appendix
D lists all the valid object codes and their instruction mnemonics, and Appendix E lists
all the indexed and indirect addressing post bytes and the assembler forms which gener­
ate them. These two tables can be used for hand checking and disassembly of object
code, tasks sometimes required in the debugging of an assembly language program.
A
Summary of the 6809
Instruction Set

Appendix A uses the following symbols:

The registers:

A.B Accumulators
D Double Accumulator (A and B concatenated. A high-order)
DP Direct Page Register
x.v Index registers
PC Program Counter
s Hardware Stack Pointer
u User Stack Pointer
cc Status (Condition Code) Register

The flags (statuses). starting with bit 0 of the condition code register and proceeding to bit 7:

C Carry (Borrow) flag


V Overflow flag
Z Zaro flag
N Sign (Negative) flag
I (Regular) Interrupt Mask bit
H Half-Carry flag
F Fast Interrupt Mask bit
E Entire flag

Symbols in the Status (flags) columns:

(blank) Operation does not affect flag


X Operation affects flag
0 Operation clears flag
1 Operation sets flag
Summary of the 6809 Instruction Set A-2

Other symbols and abbreviations:

ACx An accumulator. either Accumulator A or Accumulator B


adrS An 8-bit address. a 1-byte quantity which may be used to directly address memory
locations on the base (direct) page
adr16 A 16-bit memory address
b0-b7 Bits of a Post Byte or an 8-bit register
c Contents of the Carry flag. either 0 or 1
data& An 8-bit unit of binary data
data16 A 1 6-bit unit of binary data
disp8 An 8-bit signed binary address displacement
disp16 A 1 6-bit signed binary address displacement
EA Effective address calculated by any addressing method
M Memory address as determined by base page direct, extended direct. indexed, or
indirect addressing
(M] Contents of M
[M] [M + 1] 1 6-bit data item; its high-order byte is the contents of M. and its low-order byte is
the contents of the next higher address.
reg A 16-bit index register or stack pointer (5. U. X. or Y)
reg. list A list of registers to be stored on or retrieved from a stack
R16 A 16-bit register (D. S. U, X. or Y)
R1. R2 Two registers. both 8-bit or both 1 6-bit
SP A stack pointer (either S or U)
ind. forms Anv of the indexed or indirect addressing methods described in Appendix B
[interrupt vector] The address contained in one of the interrupt vectors (see Table 1 5-1)
xx(HI) The high-order 8 bits of the 1 6-bit quantity xx
xx(LO) The low-order 8 bits of the 1 6-bit quantity xx
[ ] Contents of location enclosed by brackets
([ )] Implied memory address: the contents of the memory location designated by the
contents of a register
1\ Logical AND
v Logical (Inclusive) OR
ltJ Logical Exclusive-OR
Data is transferred in the direction of the arrow
Data is transferred in both directions simultaneously, thus exchanging the contents
of the source and the destination.
Appendix A. A Summary of the 6809 Instruction Set �
w
Status 0'>
Type Mnemonic Operand(s) Bytes Cycles Operation Performed ! 00
0
E F H I N z v c '-0
>
. C/l
The 6809 permits the following addressing modes for all Pri- C/l
(1)
mary Memory Reference instructions: base page direct, I 3
extended direct, indexed, and indirect. CT
'-<
LOA } adrS 2 4 X X 0 [ACxl- (M] r

::::
LOB adr16 3 5 Load Accumulator A or B from specified memory location.
I (1Q
ind. forms 2+ 4+ c
STA } adrS 2 4 X X 0 [M)- [ACx)

(1Q
(1)
STB adr16 3 5 Store contents of Accumulator A or B in specified memory "'0
.,
ind. forms 2+ 4+ location. 0
(1Q
0 .,
::: LDD adrS 2 5 X X 0 [D) - [M]:(M + 1) ""
� adr16 3 6 Load double Accumulator from specified memory location. 3
c:
Ill
ind. forms 2+ 5+ Sign flag (N) takes the value of bit 15 of the data (bit 7 of
3
., ::::
(,) Accumulator A). (1Q
c:
.,
... STD adrS 2 5 X X 0 [M):[M + 1) - [D)
Ill
....
.,
adr16 3 6 Store contents of double Accumulator in specified memory
� 2+
ind. forms 5+ location. Sign flag takes the value of bit 15 of the data (bit 7 of
>
Accumulator A).
0
E
Ill
LOX } adrS 2 5 X X 0 [reg) - (M]:(M + 1]
::!! LOU adr16 3 6 Load specified register (X, Y, U, or S) from memory. Sign flag
> ind. forms 2+ 5+ (N) takes the value of bit 15 of the data.
iij
E
·;:
LOY } adr8 3 6 X X 0
IL LOS adr16 4 7
ind. forms 3+ 6+

STX } adrS 2 5 X X 0 [M]:(M + 1) - [reg)


STU adr16 3 6 Store contents of specified register (X. Y, U, or Sl in memory.
ind. forms 2+ 5+ Sign flag (N) takes the value of bit 15 of the register.

STY } adrS 3 6 X X 0
STS adr16 4 7
ind. forms 3+ 6+

--·- ---- - -- - --
Appendix A. A Summary of the 6809 Instruction Set (Continued)

Status
Type Mnemonic Operand(sl Bytes Cycles Operation Performed
E F H I N z v · c

The 6809 permits the following addressing modes for all


Secondary Memory Reference instructions: base page
direct, extended direct, indexed, and indirect.

ADCA } adr8 2 4 X X X X X [ACx] - [ACxl + [M] + C


ADCB adr16 3 5 Add with carry to Accumulator A or B.
ind. forms 2+ 4+

-e
..
ADDA } adr8 2 4 X X X X X [ACx] - [ACx] + [M]
Ill ADDS adr16 3 5 Add contents of specified memory location to Accumulator A
• ind. forms 2+ 4+ or B.
a.
0
> ADDD adrS 2 6 X X X X [D]- [D] + [M]:[M + 1]
...
0 adr16 3 7 Add 16-bit value from memory to double Accumulator. The
E ind. forms 2+ 6+
D operand's high-order byte is in the specified memory location;
� the low-order byte is in the next higher address.
D
1.1
c
ANDA } adr8 2 4 X X 0 [ACx] - [ACx] A [M]
D ANDB adr16 3 5 AND contents of specified memory location with Accumulator
lii
.... ind. forms 2+ 4+ A or B. (/)
D
cc c
BIT A adr8 2 4 X X 0 [ACx] A [M] 3
>
5
E
BITS } adr16 3 5 AND contents of specified memory location with Accumulator 3
"'
D ind. forms 2+ 4+ A or B. Only the Status register is affected. ...,

}
'<
:! CMPA adrB 2
>
4 X X X X X [ACx]- [M] 0
....,
...
Ill CMPB adr16 3 5 Compare contents of specified memory location with .....
, ::r
c ind. forms 2+ 4+ Accumulator A or B. Only the Status register is affected. �
0
<> o--
II CMPD adr8 3 7 X X X X [D] - [M]:[M + 1] 00
(/) 0
adr16 4 8 Compare 16-bit data with double Accumulator. Only the '-0

ind. forms 3+ 7+ status register is affected. The high-order byte of the data is in
the specified memory location; the low-order byte is in the I ::J

}
.,
c
next higher address.
Po
CMPS adr8 3 7 X X X X [reg] - [M]:[M + 1] 0
::J
CMPU adr16 4 8 Compare 16-bit data with specified register (S, U, X. or Yl.
(/)
CMPY ind. forms 3+ 7+ Only the status register is affected. The high-order byte of the
!!
data is in the specified memory location; the low-order byte is
in the next higher address. )>
,1.
Appendix A. A Summary of the 6809 Instruction Set (Continued) )>
.
U'l

Status 0\
Type Mnemonic Operand(s) Bytes Cycles Operation Performed 00
0
E F H I N z v c \0

)>
Vl
CMPX adr8 2 6 X X X X Same as CMPS/CMPU/CMPY. See page A-4. Vl
adr1 6
ind. forms
3
2+
7 (11
3
0'
6+

EORA } adrS 2 4 X X 0 [ACx] - [ACx] ¥ [M]


'--<
r

EORB adr1 6 3 5 Logical Exclusive-OR contents of specified memory location :::s
:0 ind. forms 2+ 4+ with Accumulator A or B. (JQ
� c
::1 I»
ORA a drS 2 4 X X 0 [ACx] - [ACx] V [M] (JQ
}
c
-.; (11
c ORB adr1 6 3 5 Logical (Inclusive) OR contents of specified memory location "0
0
ind_ forms 2+ 4+ with Accumulator A or B. ..,
2 0

SBCA �
(JQ
..,
a;
..
adrS 2 4 X X X X X [ACx] - !ACxl - !Ml - C I»
ca
... SBCB adr1 6 3 5 Subtract contents of specified memory location and contents 3

a. ind. forms 2+ 4+ of Carry flag from Accumulator A or B. 3
0
>
0
SUBA } a drS 2 4 X X X X X [ACxl - !ACxl - (M]
:::s
(JQ
SUBB adr1 6 3 5 Subtract contents of specified memory location from
E
� ind. forms 2+ 4+ Accumulator A or B.
:E
-
SUBD adrS 2 6 X X X X [D] - [D] - [M]:(M + 1]

u
c
adr16 3 7 Subtract 16-bit value in memory from double Accumulator.
ID
... ind. forms 2+ 6+ The operand's high-order byte is in the specified memory
ID
....
ID
address; the low-order byte is in the next higher address .
a:
>...

&17
ASL adrS X X X
0
E
ID
adr16
2
3
6
7 X X
• 0 J-o. V-N lJ C

:E ind. forms 2+ 6+ [M] I


>
...
ca
Arithmetic shift left. Bit 0 is set to 0 .
,
c
0
u ASR adrS 2 6 X X X X
I

Ill adr1 6 3 7 7 --.. 0 c I
ind. forms 2+ 6+
[M]
Arithmetic shift right. Bit 7 stays the same.

-- --- - - - - -- ....__ '--- ....... ...__ - ..... -- - - - - - ---

;
Appendix A. A Summary of the 6809 Instruction Set (Continued)

Status
Type Mnemonic Operand(s) Bytes Cycles Operation Performed
E F H I N z v c

CLR adrB
adr16
ind. forms
3
2

2+
76

6+
0 1 0 0 [MJ-oo,6
Clear specified memory location.

;;
COM adr8
adr16
ind. forms
32

2+
76

6+
X X 0 1 [M)- rMJ
Ones complement contents of memory location.

II

3 7 X X X
:1
c DEC adr8 2 6 [M)-[M) - 1
..
c adr16 Decrement (by 1) contents of memory location.
0
ind. forms 2+ 6+
g
"i
...
Ql

a.
INC adr8
adr16
ind. forms
32

2+
76

6+
X X X [M)-[M)+1
Increment (by 1) contents of memory location.

3 7 &17 1
LSL adr8 2 6 X X X X X
-
>
� 0 -0, V- N¥ C
E
adr16
II ind. forms 2+ 6+
[M)
� Logical shift left. Same as ASL.
II
u r:/l

17 �
c c::

3 7 X X
II
... LSR adrB 2 6 0 3
II
•o 3
o-
....
II adr16
"'

7
a: ..,
ind. forms 2+ 6+
>
[M) '<

0 Logical shift right. Bit is set to 0. 0


E
.....,

II ;.

3 7 X X X X X
:e NEG adrB 2 6
(I)

>
[MI -oo,6- [MI o--
16 adr16 00
Twos complement (negate) contents of memory location. Set 0
"0
c ind. forms 2+ 6+ Carry if result is 0016 and clear Carry otherwise. Set Overflow '-C>

'
0 .....
u if result is 801 6 and clear Overflow otherwise. :J
II
(,/) �
..,

3 7 X X X X
c::
ROL adrB 2 6 �
adr16
ind. forms 2+ 6+ Lri]:i7 .. o P v=N¥c
1 a·
:J
r:/l
[M) !!

I
Rotate contents of memory location left through Carry flag.

en
Appendix A. A Summary of the 6809 Instructic,n Set (Continued) >
'
....,

Status 0'-.
Type Mnemonic Operand(s) Bytes I Cycles 1---r--r-T"""--wr---r-..,- -r-"""'1 Operation Performed
00
0
EIFIHIIINIZIVIC -a

>
Vl
ID'ij ROR a drS 2 6 X XI I X Vl
Cb
c Q)
u
::I 3
Q) c adr16 7 3
..
ID
... c
Q) 0
a: (.)
·-
+' ind. forms 2+ 6+ ��7--------------------� [M)
0"
'<

"'
�= Rotate contents of memory location right through Carry flag. :J
0 Q) (JQ
E '; c:
"'
ID .,
� � TST adr8 2 6 X XI 0 [MJ- oo16 (JQ
Cb
>0 adr16 3 7 Test contents of memory location for zero or negative value.
.. > '"0
Ill .. ind. forms 2+ 6+ ..,

c E0
"0 0
(JQ
0 ID ..,
"'
��
0-
3
3
:J
LOA t data8 2 2 X I XI 0 [ACxl - data8 (JQ

LOB f Load Accumulator A or B immediate.

ID
LDD data 16 3 3 X I XI 0 [D)- data16
...
Ill Load double Accumulator immediate. Sign flag reflects bit 1 5
'6 of the data (bit 7 of Accumulator A).
Q)
E LOU } data16 3 3 X I XI 0 [reg) - data 16
.E LOX Load specified register IX, Y,U, or S) immediate. Sign flag (N)
reflects bit 1 5 of the register.
LOS } data16 4 4 XIXIO
LOY

AOCA t data8 2 2 X X I XIX I X I [ACx) - [ACxl + data8 + C


.! ADCB J Add immediate with carry to Accumulator A or B.

} I I XI
Ill

Q.
ADDA data8 2 2 X XIX X [ACx] - [ACx} + data8
0 ADDB Add immediate to Accumulator A or B.
II
...
Ill ADDD data16 3 4 XIX I X I X I [D)- [DI + data16
'6 Add 16-bit data to double Accumulator. The high-order byte
Q)
E follows the operation code: the low-order byte follows the
E high-order byte.
Appendix A. A Summary of the 6809 Instruction Set (Continued)

Status
Type Mnemonic Operand(s) Bytes Cycles Operation Performed
E F H I N z v c

ANDA } data8 2 2 X X 0 [ACx] - [ACx] A dataB


ANDB Logical AND immediate with Accumulator A or B.
BITA } data8 2 2 X X 0 [ACxl A data8
BITB Logical AND immediate with Accumulator A or B but affect
only the status register.
CMPA } data8 2 2 X X X X X [ACxl - dataB
I
CMPB Subtract immediate from Accumulator A or B but affect only
the status register.

I
CMPO data1 6 4 5 X X X X [0]- data16

}
Subtract immediate from double Accumulator but affect only
":ij the status register.
G)
:I
c: CMPS data 1 6 4 5 X X X X [reg] - data1 6
·o: CMPU Subtract immediate from specified register IS. U, X, or Yl. but
c:
0 CMPY affect only the status register.
2
G)
.. CMPX data1 6 3 4 X X X X
ftl
...
G)
Q.
EORA } data8 2 2 X X 0 [ACx] - [ACx] ¥ data8
Vl
0 EORB Logical Exclusive-OR immediate with Accumulator A or B. c
G) 3
..
ORA data8 2 2 X X 0 [ACx] - [ACx] V data8
}
ftl
:c 3
Q)
ORB Logical (Inclusive) OR immediate with Accumulator A or B. "'

}
..,
E '<
E SBCA dataB 2 2 X X X X X [ACx] - [ACx] - data8 - C 0
= SBCB Subtract with borrow (carry) immediate from Accumulator A
-,
-
:r
or B.
}
(1)
SUBA dataB 2 2 X X X X X [ACx] - [ACx] - data8 "'
00
SUBS Subtract immediate from Accumulator A or B. 0
\0

SUBD data1 6 3 4 X X X X [0] - [0] - data1 6 5'


Subtract immediate from double Accumulator 0. �
..,
c

0
:l
Vl

l>
I

CD
Appendix A. A Summary of the 6809 Instruction Set (Continued)

CD

Status 0\
Type Mnemonic Operand lsi Bytes Cycles Operation Performed 00
0
E F H I N z v c \0

;l>
Vl
BRA disp8 2 3 [PC)- [PC)+ disp8 + 2 Vl
C1>
Unconditional branch relative to current contents of Program 3
Counter. a'
-<
JMP adr8 2 3 [PC)- EA I
r
adr16 3 4 Unconditional jump to the specified (effective) address using "'
;:3
Q. ind. forms 2+ 3+ base page direct. extended direct, indexed. or indirect 1 OQ
E c:
:I addressing. "'
.., OQ
LBRA disp16 3 5 [PC)- [PC)+ disp16 + 3 I C1>
Unconditional long branch relative to current contents of Pro- "C
....
gram Counter. 0
I OQ
...,
TFR R16,PC 2 7 [PC)- [R16) "'
Unconditional jump to the address in the specified 16-bit 1 3
register (D. S. U, X. or VI.
3
:;·
OQ
BSR disp8 2 7 [[S)-1]- [PC!LOII I
[(S]-2)- [PC(HI))
[Sl- [S)- 2
[PC)- [PC)+ disp8 + 2
Unconditional branch to subroutine relative to current con-
c:
tents of Program Counter, saving current Program Counter in
:;
...

the Hardware Stack before performing branch .
a:
EXG R16,PC 2 8 [R16)--[PC)
.,
c:
Ill
Unconditional jump to the address in the specified 16-bit
register (0, S, U, X, or Yl. save current Program Counter in the
ii
(.) specified register. Can be used to call a subroutine or return

c:
from a subroutine; the specified 16-bit register acts as a link. ,
� JSR adr8 2 7 [(S) - 1)- [PC(LO))
:I
0
.. adr16 3 8 [(S] - 2] - [PC(HI)]
.Q
:I ind. forms 2+ 7+ lSI- [S)- 2
(/)
[PC)- EA
Unconditional jump to subroutine at the specified (effective)
address using base page direct, extended direct, indirect. or
indexed addressing. Saves current Program Counter in the
Hardware Stack before performing jump.
I
'---- - - - -- - '---- - '------ - - '---- '------ - -- - -'---- - -- - - - --•
Appendix A. A Summary of the 6809 Instruction Set (Continued)

I
Status
Type Mnemonic Operand(s) Bytes Cycles Operation Performed
E F H I N z v c

LBSR disp16 3 9 ([S]- 1] - [PCILO)]


� ([S] - 21 - [PC(HI)]

:II !Sl- !Sl- 2
c:
·�
c:
[PC]- [PC] + disp16 + 3 I
0 Unconditional long branch to subroutine relative to current
g contents of Program Counter. saving current Program 1
c:
Counter in the Hardware Stack before performing branch.
}
:;
..
• PULS PC. reg. list 2 5+ Return from Subroutine and load other registers from Hard-
Ill: '
"CC PULU ware or User Stack as specified in post byte. Bit 7 of the post
c: byte must be 1 so that the Program Counter is among the

registers loaded from the Stack. See the Stack functions sec- 1
'ii
u tion of this table for a description of PULS and PULU opera-
• tion.
c:
+:
:II RTS 1 5 [PC(HI)] - [(Sll
0
..
.a
[PC(LO)] - ([S] + 1]
:II !Sl- IS]+ 2

Return from subroutine: remove program counter from top of
(I)
Hardware Stack and increment Hardware Stack Pointer twice. c
3
[PC] - !PC] + disp8 + 2 if the given condition is true: I 3

..,
'<
BCC disp8 2 3 CzO
0
BCS disp8 2 3 c= 1 _,

c
BEQ disp8 2 3 z .. 1 i ;;.
(l)
0 BGE disp8 2 3 N¥V=O
+: o--
=ij
c
BGT
BHI
disp8
disp8
2
2
3
3
ZV(N¥V)=0
cvz-o
I 00
0
0 '1:)
u BHS disp8 2 3 C=O
c 5'
0 Cll
BLE disp8 2 3 ZV(N¥V)=1 .....
� ..,
u BLO disp8 2 3 c= 1 c
c:

..
BLS disp8 2 3 CVZ=1 a.
0
ID BLT disp8 2 3 N¥V=1 ::I
BMI disp8 2 3 N=1 (I)
BNE disp8 2 3 Z=O !!
BPL disp8 2 3 NzO

...
I 0
Appendix A. A Summary of the 6809 Instruction Set (Continued) �
...
...
Status
Type Mnemonic Operand(s) Bytes Cycles Operation Performed 0'\
00
E F H I N z v c ! 0
\0

I >-
BVC disp8 2 3 V=O [/]
[/J
BVS disp8 2 3 v =1 (1)

[PC] - [PC] + 2 if the given condition is not true.


I 3
£
'<
Note that BHS and BCC are different mnemonics for the same 1 r
operation code, as are BLO and BCS. ""
:J
[PC] - [PC] + disp16 + 4 if the given condition is true: (JQ
c
""
'0 LBCC disp16 4 5(6) C=O (JQ
Cl) (1)
:I LBCS disp16 4 5(6) c= 1
c: '"l:l
·.-:; LBEQ disp16 4 5(6) z= 1 ..,
c: 0
0 LBGE disp16 4 5(6) N.VV=O (JQ
..,
� LBGT disp16 4 5(6) Z V(N.V Vl = 0 ""
c:
disp16 4 5(6) C VZ=O
3
0 LBHI
·.-:; 3
LBHS disp16 4 5(6) C=O
� :J
c: LBLE disp16 4 5(6) Z V(N.VV) = 1 (JQ
0
(,) LBLO disp16 4 5(6) c= 1
c:
0 LBLS disp16 4 5(6) c v z =1
J:. LBLT disp16 4 5(6) N V
. V=1
0
c: LBMI disp16 4 5(6) N= 1
"'
= LBNE disp16 4 5(6) Z=O
LBPL disp16 4 516) .N= 0
LBVC disp16 4 5(6) V=O
LBVS disp16 4 5(6) v = 1

[PC] - [PC] + 4 if tne given condition is not true.


Note that LBHS and LBCC are different mnemonics for the
same operation code. as are LBLO and LBCS. A long branch
instruction takes 6 cycles to execute if it performs the branch
and 5 cycles otherwise.

Cl) EXG R1, R2 2 8 [R1] -- [R2]


0 >
.... 0 Exchange contents of specified registers. No effect on Status
G� register (CC) unless R1 or R2 is Status register.
.... ...
.. Cl)
·- ....
CJIUI
TFR R1, R2 2 7 [R2]- [R1]
R1 to R2. No effect on Status register
-
Gl · Transfer contents of
a: Cl)
a>
a: (CC) unless R2 is CC.
- - - - -- -
Appendix A. A Summary of the 6809 Instruction Set (Continued)

Status
Type Mnemonic Operand(s) Bytes Cycles Operation Performed
E F H I N z v c

ABX 1 3 (X] - (X) + (B]


... Add unsigned contents of Accumulator B to Index Register X .

.. 1 11 (D) - (A) X (B)
.. MUL X X
61 .
'
Multiply unsigned numbers in Accumulators A and B and place
...
cr ca result in D.
.:. �
• Cl.
.. 0
Carry flag takes the value of bit7of Accumulator B.
'61 SEX 1 2 X X (A) -FF16 if bit 7 of Accumulator B is 1 .

a: 7
(A] -0016 if bit of Accumulator B is 0.
Transform an 8-bit twos complement number in B into a 16-
bit twos complement number in D.

ASLA } 1 2 X X X X X
ASLB
�7 ..

(ACx)
0 1 -0, V = N J.l. C

Arithmetic shift left Accumulator A or B. Bit 0 is set to 0.

ASRA } 1 2 X X X X C/)
c:
ASRB
7 - 0 c 3
3
• (ACx) "'
.. ..,
Ill '<
Arithmetic shift right Accumulator A or B. Bit 7 stays the
• 0
Cl. same. -,
0
... ;.

..
..
61
CLRA} 1 2 0 1 0 0 IACx)-0016

0'--
00
" CLRB Clear Accumulator A or B.
• 0

COMA }
cr \0
1 2 X X 0 1 (ACx] - (ACx)
5'
COMB Ones complement contents of Accumulator A or B. \!?.
..,
DAA 1 2 X X X X c:
Decimal adjust Accumulator A. Convert contents of
Sl
Accumulator A (assumed to be the binary sum of BCD
cs·
operands) to BCD format. Carry is set if it was previously set ::J

or if the adjustment results in a carry. C/)

DECA } 1 2 X X X [ACxl - [ACxl - 1


DECB Decrement (by 1 I contents of Accumulator A or B. Set Over- ,..


I
flow flag if result is 7F 16 and clear Overflow flag otherwise. ...
N
Appendix A. A Summary of the 6809 Instruction Set (Continued) �
...
w
Status
"'
Type Mnemonic Operand(s) Bytes Cycles Operation Performed 00
0
E F H I N z v c \0

INCA } 1 2 X X X [ACx] - [ACx] + 1


>
Vl
Vl
(1)
INCB Increment (by 1) contents of Accumulator A or B. Set Over-
3
flow flag if result is 8016 and clear Overflow flag otherwise. �
'<

LSLA } 1 2 X X X X X
0 1- 0. V = N lJ. C
r
"'
::I
LSLB �7� [ACx]
(JQ
c
"'
(JQ
(1)
Logical shift left Accumulator A or B. Bit 0 is set to 0. Same as
'"0
ASL. .,

7
0
(JQ

}
.,

LSRA 1 2 0 X X
0 0 c 3

7
� LSRB
Gl 3
::t
1: [ACx] ::I
� (JQ
1: Logical shift right Accumulator A or B. Bit is set to 0.
0

0
..
Cll
NEGA } 1 2 X X X X X [ACxl -0016- [ACx]
...
Gl NEGB Twos complement (negate) contents of Accumulator A or B.
a.
Set Carry flag if result is 0016 and clear Carry flag otherwise.
0
... Set Overflow flag if result is 8016 and clear Overflow flag
Gl
...
., otherwise .
·=

}
Gl

LEH7� j:J
II:
ROLA 1 2 X X X X
ROLB
0 V=N lJ. C

[ACx]
Rotate Accumulator A or B left through Carry flag.

}
lEH7 -=oP
RORA 1 2 X X X
RORB

[ACx]

Rotate Accumulator A or B right through Carry flag.

-
Appendix A. A Summary of the 6809 Instruction Set (Continued)

Status
Type Mnemonic Operand(s) Bytes Cycles Operation Performed
E F H I N z v c

"ii
TSTA } 1 2 X X 0 [ACxl - 0016
t)
:I
TSTB Test contents of Accumulator A or B for zero or negative
c
value.
·;;


c
0 LEAX } ind. forms 2+ 4+ X [reg]- EA
LEAY Form the effective address according to any of the indexed/
t)
.. indirect addressing modes (see Appendix B) and load that
IV
Gi address into the specified register (X, Y, S, or U). LEA instruc-
Q.
0 tions are primarily intended to calculate an effective address
once for repeated use. but may also be employed to perform
Gi
..
16-bit arithmetic .
}
01
·g,
t) LEAS ind. forms 2+ 4+
a:
LEAU

PSHS } reg. list 2 5+ Test post byte and store registers in specified stack as follows:
PSHU Condition:
b7 = 1; [SP]- [SP] - 1, [[SP]]- [PC(LQ)]
[SP]- [SP] - 1, [[SP]]- [PC(HI)) Cl'l
c
b6 = 1; [SP)- [SPI - 1, [(SP)]- [U(LO)J or [SILO)) 3
[SPI- [SP] - 1, [(SP)]- [U(HI)) or [S(HI)) 3
II>
b5 = 1; [SP)- [SP] - 1, [(SP]]- [Y(LQ)) .,
'<
[SPI- [SP) - 1, [(SP]]- [Y(HI)l 0
._,
b4 = 1; [SP]- [SP) - 1, [(SP]]- [X(LO)) ....

u !SP)- {SP) - 1, [(SP]]- {X(HI)) ::T

IV
.. b3 = 1; [SP]- [SP] - 1, [(SP]]- [DP) 0\
(I)
00
b2 = 1; [SP) - [SPI - 1, [(SP]]- [B) 0
\0
b 1 = 1; [SPI- [SPl - 1, [(SP))- [A)
bO = 1; [SP]- [SP] - 1, [[SPll- [CC] 5'
Push all, none, or any subset of registers onto the specified �
.,
c
Stack, except for the pointer to that Stack.
$?.
Execution time increases by one cycle for each byte pushed. 0
;J
Cl'l


...


Appendix A. A Summary of the 6809 Instruction Set (Continued) �
....
U'l
Status
0\
Type Mnemonic Operand(s) Bytes Cycles Operation Performed 00
E F H I N z v c 0
\0

PULS } reg. list 2 5+ Test post byte and load registers from specified stack as
>
"'
"'
PULU follows: c..
3
Condition: c::r
Q"
bO = 1;[CCI - [[SPII. [SPI - [SPI + 1
r
b1 = 1;[AI - I!SPII . [SPI - [SP) + 1 I»
;:I
b2 = 1;[B) - [[SP]). (SP] - [SP] + 1 O'l
b3 1;[DPI - [[SPII. [SPI - [SPJ + 1 c:
=

b4 1;[X(HI)) - [(SP)l . !SP] - [SP] + 1 O'l
=
c..
[X(LOll - [(SP)]. [SP] - [SP] + 1 ..,
..,
b5 = 1; [Y(HI)] - [[SP]]. [SP] - [SP] + 1 0
O'l
[YILO)) - [(SPll. [SP] - [SP] + 1 ..,

b6 = 1; [U(HI)] or [S(HI)] - [[SP]]. [SP] - [SP] + 1 3
[U(LOll or [SILO)] - [[SPll. (SP] - [SP] + 1 3
b7 = 1; (PC(HI)] - [[SPll. (SP] - [SP] + 1 ;:I
� O'l
Gl
:I
[PC(LO)] - [(SP]]. !SP] - [SPI + 1
r::: Pull all. none. or any subset of registers from the specified
·;:::
c stack, except for the Pointer to that Stack. Status register bits
0
� are determined by byte pulled from Stack.

u Execution time increases by one cycle for each byte pulled.
Ill
....
rn

......_ --- '------ L___ --- '-- � -- L.__ -'---. --- -- -- -- ----- ---- ---
-
Appendix A. A Summary of the 6809 Instruction Set (Continued)

Status
Type Mnemonic Operand(s) Bytes Cycles Operation Performed
E F H I N z v c

CWAI data8 2 20 [CC] � [CC] A data8. This may clear CC bits.


E� 1
[S]� [SJ - 1. [[S)]� [PC(LO)]
[SJ� [S] - 1, [[S]]� [PC(HI)]
[S]� [S]- 1, [[S)] � [U(LO)]
[S]� [S] - 1, [[S)] � [U(HI)]
[SJ� [S] - 1. [[SJJ� [Y(LO)]
[SJ� [S]- 1. [[SJJ � [Y(HI)]
[SJ- [S]- 1, [[S]] � [X(LO)]
[S]- [S]- 1, [[S]] � [X(HI)]
[S] � [S] - 1, [[S]] � [DP]
[S] � [S] - 1. [[S]] � [ 8]
[S]� [SJ - 1, [[SJJ� [A]
[SJ� [SJ - 1, [[SJJ� [CC]
Stores all registers in Hardware Stack and waits for an inter-
... rupt. When non-masked interrupt occurs, vectors to corres-
c. ponding interrupt service routine. Note that a fast interrupt
2
� (FIRQ) service routine will be entered with all registers saved.
(/)
... but RTI will restore them correctly since CWAI sets E flag . c:
=
CWAI does not float the system busses. 3
3
llol
...,
'<
0
.....,
-
::r
(1)
a-..
00
0
\1:>

::l

...,
c:
::?.
c;·
::l
(/)


...
0)
Appendix A. A Summary of the 6809 Instruction Set (Continued)

...
....,
Status
Type Mnemonic Operand(sl Bytes Cycles Operation Performed 0\
00
E F H I N -z v c 0
'-0

>
ATI 1 6/15 Pull registers from Hardware Stack in accordance with value (J)
(J)
of E flag in Status register. (1>
3
If E = 0, pull the subset: cr'
-<"'
[CCI - !!Sll, lSI - lSI + 1
[P C(Hlll - !!Sll. lSI - lSI + 1 r-
"'
::l
!PC(LOll - [[Sll . lSI - lSI + 1 OCl
s::
If E = 1. pull the full complement of registers: "'
OCl
!CCI - !!Sll. (SJ - !Sl + 1 (1>
'"1:1
[A) - [[Sll. [S] - (S] + 1 ..,
0
!Bl - [(Sll. lSI - lSI + 1 OCl
..,
IDP] - [(SJI. [S] - lSI + 1 "'

IX(HI)] - [[S)), [S] - [SJ + 1 3


[X(LO)J - IISII, lSI - lSI + 1
3

c :::::
:I [Y(HI)] - !!Sll. (SJ - [S] + 1 OCl
c
·:: IY(LOll - [(SJl. !Sl - IS] + 1
c
0 [U(Hlll - [[S)), [S] - !Sl + 1
2 [U(LO)J - [(S]). [S] - (S] + 1
.. [PC(HI)) - liS]]. IS] - (S] + 1
1:1.
:I
..
.. [PC(LO)] - [(S]J. [Sl - [S] + 1
Ill
.. Status register bits are as removed from the Hardware Stack .
..:
SWI 1 19 1 1 Save all registers in the Hardware Stack and transfer control
SWI2 2 20 1 to interrupt subroutine. Vectors are in:
SWI3 2 20 1 FFFA and FFFB for SWI
FFF4 and FFF5 for SWI2
FFF2 and FFF3 for SWI3
E-1
[S] - lSI - 1, [(S)) - [PC(LOII
lSI - [S] - 1, [(S)) - [PC(HI)]
lSI - lSI - 1, [[S)) - (U(LQ)]
lSI - lSI - 1, HSII - [U(Hlll
[S] - lSI - 1, [[S)) - [Y(LO))
(S] - (S]
[S] - [S]
-
-
1,
1.
([S))
!!Sll
-
-
IY(Hll]
[X(LQ))
I
IS) - IS] - 1, [(SJJ - [X(Hlll
__j
Appendix A. A Summary of the 6809 Instruction Set (Continued)

Status
Type Mnemonic Operand(s) Bytes Cycles Operation Performed
E F H I N z v c

SYNC 1 2 lSI - lSI - 1, !!SJJ - !DPl


lSI - lSI - 1, IISII - !Bl
(S] - lSI - 1, [[SJJ - !AI
-:; [S] - lSI - 1, [[SJJ - [CCI

;:, [PC] - [interrupt vector]
c:
:;:: Note that the SWI disables the regular and fast interrupts,
c:
0 whereas SWI2 and SWI3 do not affect either one.
g
.. Stop processing instructions. Float system busses and wait
a.
;:,
..
.. for an interrupt. When an interrupt occurs, resume processing

.. as follows:
.!: a. If interrupt is enabled, transfer control to the service
routine.
b. If interrupt is disabled, continue execution at next instruc-
tion in sequence.

ANDCC data8 2 3 [CCI - !CCI A data8


Logically AND immediate data with contents of status til
c:
register. Used to clear bits of status register by logically AND- 3
..
;:, ing them with 'O's. 3
..
II "'
.. ORCC data8 2 3 [CCI - [CCI V data8 .,
rn '<
Logically (Inclusive) OR immediate data with contents of 0
....,
status register. Used to set bits of status register by logically -
ORing them with '1's. :r

"'
I 00
0
BRN disp8 2 3 Branch never. This is a No operation. '.0

LBRN disp16 5 4 Long branch never. This is a No operation. ::l


..
c:
NOP 2 1 No operation. �
0 .,
:;:: c
II $l
e a·
a.
::l
0
0 til
2 !!


...
----- Q)
B
Summary of 6809 Indexed and
Indirect Addressing Modes

Non-indirect .. Indirect
.. ..
• .. •
u :! u !
Type Form >- >-
Post-Byte
>- >-
Assembler Post-Byte (,) Ill Assembler (,) Ill
Form Op-code + + Form Op-code + +

No Offset ,R 1RR00100 0 0 [.AI 1RR10100 3 0


Constant Offset 5 -Bit Offset n.R ORRnnnnn 1 0 Defaults to 8-bit
from R 8-Bit Offset nn.R 1RR01000 1 1 [nn.RI 1RR11000 4 1
16-Bit Offset mmnn.R 1RR01001 4 2 lmmnn,RI 1RR11001 7 2

A - Register Offset A. A 1RR00110 1 0 [A, AI 1RR10110 4 0


Accumulator
B - Register Offset B. A 1RR00101 1 0 [B,RI 1RR10101 4 0
Offset from R
D - Register Offset D.R 1RR01011 4 0 [D,R) 1RR11011 7 0

Increment by 1 .R+ 1RROOOOO 2 0 Not allowed


Auto Increment/ Increment by 2 .A++ 1RR00001 3 0 I.R++) 1RR10001 6 0
Decrement R Decrement by 1 .-R 1RR00010 2 0 Not allowed
Decrement by 2 . --R 1RR00011 3 0 1. - -R I 1RR10011 6 0

Constant Offset 8-Bit Offset label. PCR 1XX01100 1 1 [label. PCRI 1XX11100 4 1
from PC 1 6-Bit Offset labei.PCR 1XX01101 5 2 llabei.PCRI 1XX11101 8 2

Extended
1 6-Bit Address - - - - [mmnnl 10011111 5 2
I ndi rect

R = X. Y. U. or S RR: 00 =X 10 = u
XX = Don't Care 01 = y 11 = s

Note: This chart conforms to Motorola nomenclature; their use of square brackets [ I indicates to the assembler that
the addressing mode is indirect - thus. their use of [ I differs from the use in Appendix A.
Address
.. Inherent Immediate Direct Extended Indexed/Indirect Relative
Mode

O perand
.... data8 or data 16 adr8 adr16 See Ap pendix B
I
label or displacement
Form

Instruction Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Mnemonic + Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

ABX 3A 3 1
XI
ADCA 89 2 2 99 4 2 89 5 3 A9 4+ 2+ CD
ADCB
ADDA
C9
88
2
2
2
2
09
98
4
4
2
2
F9
88
5
5
3
3
E9
A8
4+
4+
2+
2+
.am
ADDB
ADDD
CB
C3
2
4
2
3
DB
03
4
6
2
2
FB
F3
5
7
3
3
EB
E3
4+
6+
2+
2+
E. CD
ANDA 84 2 2 94 4 2 84 5 3 A4 4+ 2+ -.o
ANDB
ANDCC
C4
1C
2
3
2
2
04 4 2 F4 5 3 E4 4+ 2+ CDU)
ASL
ASLA 48 2 1
08 6 2 78 7 3 68 6+ 2+
'
3-
ASLB 58 2 1 CD::::S
m
::::s
ASR 07 6 2 77 7 3 67 6+ 2+

.. ..
ASRA 47 2 1
ASRB 57 2 1 ..
BCC 24 3 2
...(I) c:
::::s n
BCS 25 3 2
BEQ
BGE
27
2C
3
3
2
2
m r+-
·
BGT 2E 3 2
BHI
8HS
22 3 2 a.O
::::s
24 3 2

m
BIT A 85 2 2 95 4 2 85 5 3 A5 4+ 2+
BITB C5 2 2 05 4 2 F5 5 3 E5 4+ 2+
BLE 2F 3 2 >en
BLO
BLS
25
23
3
3
2
2 CD O
BLT 20 3 2 na.
BMI
BNE
28
26
3
3
2
2
c:CD
BPL 2A 3 2 r+U)
-· ...
BRA 20 3 2
BRN 21 3 2 0
::::s !:.
BSR 80 7 2
BVC 28 3 2
BVS
CLR OF 6 2 7F 7 3 6F 6+ 2+
29 3 ·2
-teD
-
CLRA 4F 2 1 ·
3
CLRB 5F 2 1
3
n
CMPA 81 2 2 91 4 2 81 5 3 A1 4+ 2+
CMPB C1 2 2 01 4 2 Fl 5 3 E1 4+ 2+ CD�
CMPD 10 8 3 5 4 10 93 7 3 10 83 8 4 10 A3 7+ 3+
m<
notes
(")
Address
Mode
..... Inherent Immediate Direct Extended Indexed/Indirect Relative ,:.,
Operand 0"\
..... data8 or data16 adr8 adr16 See Appendix B label or displacement 00
Form 0
-.a
Instruction Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Mnemonic + Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes
5'

..,
CMf'S 11 8C 5 4 1 1 9C 7 3 11 8C 8 4 1 1 AC 7+ 3+ c
CMPU 1 1 83 5 4 11 93 7 3 1 1 83 8 4 11 A3 7+ 3+ �
CMPX 8C 4 3 9C 6 2 BC 7 3 AC 6+ 2+ cs·
::l
CMPY 10 8C 5 4 10 9C 7 3 10 BC 8 4 10 AC 7+ 3+
COM 03 6 2 73 7 3 63 6+ 2+ n
0
COMA 43 2 1 Q.
COMB 53 2 1

C/)
CWAI 3C 20 2
DAA 19 2 1 3:::
DEC ("D
OA 6 2 7A 7 3 6A 6+ 2+
DECA 4A 2 1 3
0
DECB SA 2 1 ..,
'<
EORA \ 88 2 2 98 4 2 88 5 3 AS 4+ 2+
EORB C8 2 2 DB 4 2 FB
:::0
5 3 EB 4+ 2+ �
EXG 1E 8 2 J:i
INC oc 6 2 7C 7 3 6C 6+ 2 =
2+ ..,
INCA 4C 2 1 ("D
INCB 5C 2 1 3

JMP OE 3 2 7E 4 3 6E 3+ 2+ ::l
JSR
-
9D 7 2 8D 8 3 AD 7+ 2+ C/)
LBCC 10 24 5(61 4 1

LBCS 10 25 5(61 4 1 :I
LBEO 10 27
0.
5(61 4 1
LBGE 10 2C 5(6) 4 1 !:Tl
LBGT

10 2E 5(6) 4 1 �
LBHI 10 22 5(6) 4 1
()
LBHS 10 24 5(6) 4 1
s
LBLE 10 2F 5(6) 4 1
cs·
:I
LBLO 10 25 5(6) 4 1
LBLS 10 23 5(61 4 1 :i
LBLT 10 2D 5(6) 4 1 3

L� 10 28 5(6) 4 1 C/)
LBNE 10 26 5(61 4 1
LBPL 10 2A 5(61 4 1
LBRA 16 5 3
LBRN 10 2 1 5 4
LBSR 17 9 3
LBVC 10 28 5(61 4 1
LBVS 10 29 5(6) 4 1
LOA 86 2 2 96 4 2 86 5 3 A6 4+ 2+
2
'
LOB C6 2 06 4 2 F6 5 3 E6 4+ 2+
LDD cc 3 3 DC 5 2 FC 6 3 EC 5+ 2+
�-
Address notes
... Inherent Immediate Direct Extended Indexed/Indirect Relative
Mode

Operand
.. dataB or data16 adrB adr16 See Appendix B label or displacement
Form

Instruction Object No. of No. of Object No. of


t
No. of Object No. of No. of Object No. of No. of Object No. of No. of Object No. of No. of
Mnemonic Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes Code Cycles Bytes

LOS 10 CE 4 4 10 DE 6 3 10 FE 7 4 10 EE 6+ 3+
LOU CE 3 3 DE 5 2 FE 6 3 EE 5+ 2+
LOX BE 3 3 9E 5 2 BE 6 3 AE 5+ 2+
LOY 10 BE 4 4 10 9E 6 3 10 BE 7 4 10 AE 6+ 3+
LEAS 32 4+ 2+
LEAU 33 4+ 2+
LEAX 30 4+ 2+
LEAY
LSL OB 6 2 78 7 3
31
68
4+ 2+
I
I
6+ 2+
LSLA 48 2 1
LSLB 58 2 1
LSR 04 6 2 74 7 3 64 6+ 2+

I
LSRA 44 2 1
LSRB 54 2 1
MUL 30 11 1
NEG 00 6 2 60

I
70 7 3 6+ 2+
NEGA 40 2 1
NEGB 50 2 1
NOP 12 2 1 o--
00
ORA 8A 2 2 9A 4 2 BA 5 3 AA 4+ 2+ 0
\0

I
ORB CA 2 2 DA 4 2 FA 5 3 EA 4+ 2+
ORCC 1A 3 2 p
Vl
PSHS 34 5+ 2 Vl
2. 3 (1)
PSHU 36 5+ 2
3
I
2. 3
PULS 35 5+ 2
PULU
2. 3 �
37 5+ 2 2. 3 ' '<

I
ROL 09 6 2 79 7 3 69 6+ 2+ r­
ROLA 49 2 1 Ill
;:J
ROLB 59 2 1 O<l
ROR s::
06 6 2 76 7 3 66 6+ 2+ Ill
RORA 46 2 1 O<l

I
(1)
RORB 56 2 1
'"C
RTI 38 6i1 5 1 ...,
RTS 0
39 5 1
I O<l
...,

I
SBCA 82 2 2 92 4 2 B2 5 3 A2 4+ 2+ Ill
SBCB C2 2 2 02 4 2 F2 5 3 E2 4+ 2+ 3
SEX 10 2 1
3
STA 97 4 2 87 5 3 A7 4+ 2+ ;:J
STB 07 4 2 F7 5 3 E7 4+ 2+ O<l
STO DD 5 2 FD 6 3 ED 5+ 2+
STS 10 OF 6 3 10 FF 7 4 10 EF 6+ 3+

w
D
6809 Instruction Object Codes
in Numerical Order

The following symbols and abbreviations appear in this appendix:

adrS 8-bit address


adr16 16-bit address
dataB 8-bit data
data16 16-bit data
dd 8-bit data
dd dd 16-bit data
label The destination of a Jump or Branch
mm 8-bit displacement in the object code
mm nn 16-bit displacement in the object code
pp post byte for indexed and indirect addressing
qq 8-bit address
ssqq 16-bit address
D-2 6809 Instruction Object Codes

6809 Instruction Object Codes in Numerical Order

Object Code 1 lnstruction2. 3 Addressing Mode

OOqq NEG adr8 Base page (direct)


03qq COM adr8 Base page (direct)
04qq LSR adr8 Base page (direct)
06qq ROR adr8 Base page (direct)
07qq ASR adr8 Base page (direct)
08qq ASL adr8 I LSL adr8 Base page (direct)
09qq ROL adr8 Base page (direct)
OAqq DEC adr8 Base page (direct)
OCqq INC adr8 Base page (direct)
ODqq TST adr8 Base page (direct)
OEqq JMP adr8 Base page (direct)
OF qq CLR adr8 Base page (direct)
1021 mm nn LBRNiabel Relative
1022 mm nn LBHIIabel Relative
1023 mm nn LBLS label Relative
1024 mm nn LBHS label I LBCC label Relative
1025 mm nn LBLO label I LBCS label Relative
1026 mm nn LBNE label Relative
1027 mm nn LBEOiabel Relative
1028 mm nn LBVC label Relative
1029 mm nn LBVS label Relative
102A mm nn LBPL label Relative
102B mm nn LBMIIabel Relative
102C mm nn LBGEiabel Relative
102D mm nn LBLT label Relative
102Emm nn LBGT label Relative
102F mm nn LBLE label Relative
10 3F SWI2 Inherent
10 83 dd dd CMPD datal 6 Immediate
10 8C dddd CMPY data16 Immediate
10 8E dd dd LOY data16 Immediate
10 93 qq CMPD adr8 Base page (direct)
10 9Cqq CMPY adr8 Base page (direct)
10 9Eqq LOY adr8 Base page (direct)
10 9Fqq STY adr8 Base page (direct)
10 A3 pp1 CMPD indexed forms Indexed I indirect
10 AC ppl CMPY indexed forms Indexed I indirect
10 AE pp1 LOY indexed forms Indexed I indirect
lO AF pp1 STY indexed forms Indexed I indirect
10 83 ssqq CMPO adr16 Extended (direct)
10 BC ssqq CMPY adr16 Extended (direct)
10 BE ssqq LOY adrl 6 Extended (direct)
10 BF ssqq STY adr16 Extended (direct)
10 CE dd dd LOS data16 Immediate

Note 1. The post byte may be followed by two bytes, one byte, or no byte. See Appendix B and the discus-
sion of the post byte in Chapter 3 for more details. Appendix E lists all possible post bytes and the
operand forms that produce them.

Note 2. Some instructions have two mnemonics. In each such case. we show both forms, separated by a
slash (!).

Note 3. Appendix B displays the "indexed forms" for operands in the indexed and indirect addressing
modes.

Note 4. In the instructions EXG and TFR. the processor interprets the second byte (the immediate datal as
designating the source and destination registers.

Note 5. In the instructions PSHS. PULS, PSHU, and PULU, the processor interprets the second byte (the
immediate datal as designating which registers are to be included in the transfer of data to or from
the stack.
6809 Assembly Language Programming D-3

6809 Instruction Object Codes in Numerical Order (Continued)

Object Code 1 lnstruction2. 3 Addressing Mode

10OEqq LOS adr8 Base page (direct)


10OFqq STS adr8 Base page (direct)
10EE ppl LOS indexed forms Indexed I indirect
10EF pp1 STS indexed forms Indexed I indirect
10FE ssqq LOS adr16 Extended (direct)
10 FF ssq q STS adr1 6 Extended (direct)
1 1 3F SWI3 Inherent
11 83 dd dd CMPU data16 Immediate
11 8Cdd dd CMPS data16 Immediate
11 93qq CMPUadr8 Base page (direct)
1 1 9Cqq CMPS adr8 Base page (direct)
11 A3 pp1 CMPU indexed forms Indexed I indirect
11 AC ppl CMPS indexed forms Indexed I indirect
11 B3 ssqq CMPUadr16 Extended (direct)
11 BC ssqq CMPS adr16 Extended (direct)
12 N OP Inherent
13 SYNC Inherent
16mm nn LBRA label Relative
17 mm nn LBSR label Relative
19 OAA Inherent
1A dd ORCCdata8 Immediate
1Cdd ANOCCdata8 Immediate
10 SEX Inherent
1E dd EXG data8 Register4
1F dd • TFR data8 Register4
20mm BRA label Relative
21 mm BAN label Relative
22 mm BHIIabel Relative
23 mm B LS label Relative
24 mm BCClabel I BHS label Relative
25mm BCS label I BLO label Relative
26mm BNE label Relative
27mm BEQ label Relative
28 mm BVClabel Relative
29 mm BVSiabel Relative
2A mm BPL label Relative
2B mm B MIIabel Relative
2Cmm BGE label Relative
20mm BLT label Relative
2 E mm BGT label Relative
2F mm BLE label \Relative
30pp1 LEAX indelled forms 'lndelled I indirect
31 ppl LEA Y indelled forms lndelled I indirect
32 pp1 LEAS indelled forms Indexed I indirect
33 pp1 LEAU indelled forms Indexed I indirect
34 dd PSHS data8 Register5
35dd PULS data8 Register5
36dd PSHU data8 Register5
3 7dd PULU data8 Register5
39 RTS Inherent (Stack)
3A ABX Inherent
38 RTI Inherent (Stack)
3Cdd �· CWAidataS Immediate
30 MUL Inherent
/
3F SWI Inherent
40 NEGA Accumulator
43 CO MA Accumulator
44 LSRA Accumulator
46 RORA Accumulator
D-4 6809 Instruction Object Codes

6809 Instruction Object Codes in Numerical Order (Continued)

Object Code 1 lnstruction2. 3 Addressing Mode

47 ASRA Accumulator
48 ASLAILSLA Accumulator
49 ROLA Accumulator
4A DECA Accumulator
4C INCA Accumulator
40 TSTA Accumulator
4F CLRA Accumulator
50 NEGB Accumulator
53 COMB Accumulator
54 LSRB Accumulator
56 RORB Accumulator
57 ASRB Accumulator
58 ASLB I LSLB Accumulator
59 ROLB Accumulator
5A DECB Accumulator
sc INCB Accumulator
50 TSTB Accumulator
5F CLRB Accumulator
60 pp1 NEG indexed forms Indexed I indirect
63 pp1 COM indexed forms Indexed I indirect
64 pp1 LSR indexed forms Indexed I indirect
66 pp1 ROR indexed forms IndexedI indirect
67 pp1 ASR indexed forms Indexed I indirect
68 pp1 ASL I LSL indexed forms Indexed I indirect
69 pp1 ROL indexed forms Indexed Iindirect
6A pp1 DEC indexed forms IndexedI indirect
6C pp1 INC indexed forms Indexed I indirect
6Dpp1 TST indexed forms Indexed I indirect
6 E pp1 JMP indexed forms Indexed I indirect
6F pp1 CLR indexed forms Indexed I indirect
70 ss qq NEG adr1 6 Extended (direct)
73 ss qq COM adr1 6 Extended (direct)
74 ss qq LSR adr16 Extended (direct)
76 ss qq ROR adr16 Extended (direct)
77 ss qq ASR adr16 Extended (direct)
78 ssqq ASL adr161 LSL adr16 Extended (direct)
79 ss qq ROL adr16 Extended (direct)
7A ssqq DEC adr16 Extended (direct)
7C ssqq INC adr1 6 Extended (direct)
70 ss qq TST adr1 6 Extended (direct)
7 E ss qq JMP adr16 Extended (direct)
7F ssqq CLR adr1 6 Extended (direct)
80 dd SUBA data8 Immediate
81 dd CMPA data8 Immediate
82 dd SBCA data8 Immediate
83 dd dd SUBDdata16 Immediate
84 dd ANDA data8 Immediate
85 dd BITA data8 Immediate
86 dd LOA data8 Immediate
88 dd EORA data8 Immediate
89 dd ADCA data8 Immediate
8A dd ORA data8 Immediate
8B dd ADDA data8 Immediate
8C dd dd CMPX data16 Immediate
8Dmm BSR label Relative
8 E dd dd LOX data16 Immediate
90qq SUBA adr8 Base page (direct)
91qq CMPA adr8 Base page (direct)
92 qq SBCA adr8 Base page (direct)
93 qq SUBDadr8 Base page (direct)
6809 Assembly Language Programming D-6

6809 Instruction Object Codes in Numerical Order (Continued)

Object Code 1 lnstruction2· 3 Addressing Mode

94qq ANDAadr8 Base page (direct)


95qq BITA adr8 Base page (direct)
96qq LDAadr8 Base page (direct)
97qq STAadrB Base page (direct)
98qq EORAadr8 Base page (direct)
99qq ADCAadr8 Base page (direct)
9Aqq ORAadr8 Base page (direct)
9Bqq ADDAadrB Base page (direct)
9Cqq CMPXadr8 Base page (direct)
9Dqq JS R adr8 Base page (direct)
9Eqq LOXadr8 Base page (direct)
9Fqq STXadrB Base page (direct)
AOpp1 SUB A indexed forms Indexed I indirect
Alpp1 CMPAindexed forms Indexed I indirect
A2 ppl SB CAindexed forms Indexed I indirect
A3 ppl SUB Dindexed forms Indexed I indirect

A4pp1 ANDAindexed forms Indexed I indirect


A5pp1 BIT A indexed forms Indexed I indirect
A6 pp1 LOAindexed forms Indexed I indirect
A7 pp1 STA indexed forms Indexed I indirect
AS pp1 EORA indexed forms Indexed I indirect
A9pp1 ADCAindexed forms Indexed I indirect
AApp1 ORAindexed forms Indexed I indirect
AB pp1 ADDAindexed forms Indexed I indirect
ACpp1 CMPX indexed forms Indexed I indirect
ADppl JS Rindexed forms Indexed I indirect
AE pp1 LOXindexed forms Indexed I indirect
AFpp1 STX indexed forms Indexed I indirect
BOssqq SUB Aadrl6 Extended (direct)
Bl ss qq CMP}'. adrl6 Extended (direct)
B 2 ssqq SB CAadrl6 Extended (direct)
B 3 ssqq SUB Dadrl6 Extended (direct)
B 4 ssqq ANDAadr16 Extended (direct)
B 5ssqq BITAadrl6 Extended (direct)
B 6 ssqq LOAadr16 Extended (direct)
87 55qq STA adrl 6 Extended (direct)
B S ss qq EORAadrl6 Extended (direct)
B 9ss qq AOCAadrl6 Extended (direct)
B Assqq ORAadrl6 Extended (direct)
BB ssqq ADDAadr16 Extended (direct)
B Css qq CMPXadrl6 Extended (direct)
B Dss qq JS Radrl6 Extended (direct'
B E ss qq LOXadr16 Extended (direct)
B Fss qq STXadrl6 Extended (direct)
COdd SUBB data8 Immediate
Cldd CMPB data8 Immediate
C2 dd SB CB data8 Immediate
C3 dd dd ADDDdatal6 Immediate
C4dd ANDB data8 Immediate
C5dd BITB data8 Immediate
C6dd LOB data8 Immediate
C8dd EORB data8 Immediate
C9dd ADCB data8 Immediate
CAdd ORB data8 Immediate
CB dd ADDS data8 Immediate
cc dd dd LDDdatal6 Immediate
CE dd dd LOU data16 Immediate
DOqq SUBB adrS Base page (direct)
Dlqq CMPB adrB Base page (direct)
D-6 6809 Instruction Object Codes

6809 Instruction Object Codes in Numerical Order (Continued)

Object Code 1 lnstruction2. 3 Addressing Mode

D2qq SBCB adr8 Base page (direct)


03 qq ADDD adr8 Base page (direct)
D4qq ANDB adr8 Base page (direct)
05 qq BITB adr8 Base page (direct)
D6qq LOB adr8 Base page (direct)
07 qq STB adr8 Base page (direct)
D8qq EORB adr8 Base page (direct)
09qq ADCB adr8 Base page (direct)
OAqq ORB a drS Base page (direct)
DBqq ADDB adr8 Base page (direct)
OCqq LDD adr8 Base page (direct)
ODqq STD adr8 Base page (direct)
DEqq LOU adr8 Base page (direct)
OFqq STU adr8 Base page (direct)
EOppl SUBI;! indexed forms Indexed I indirect
E1 pp 1 CMPB indexed forms Indexed I indirect
E2 pp1 SBCB indexed forms Indexed I indirect
E3 ppl ADDD indexed forms Indexed I indirect
E4 ppl ANDB indexed forms Indexed I indirect
ES pp1 BITB indexed forms Indexed I indirect
E6 ppl LOB indexed forms Indexed I indirect
E7 ppl STB indexed forms Indexed I indirect
ES pp1 EORB indexed forms Indexed I indirect
E9 ppl ADCB indexed forms Indexed I indirect
EA ppl ORB indexed forms Indexed I indirect
EB pp1 ADDB indexed forms Indexed I indirect
EC ppl LDD indexed forms Indexed I indirect
ED ppl STO indexed forms Indexed I indirect
EE ppl LOU indexed forms Indexed I indirect
EF ppl STU indexed forms Indexed I indirect
FOS5qq SUBB adr16 Extended (direct)
F1 ss qq CMPB adr16 Extended (direct)
F2 55QQ SBCB adr16 Extended (direct)
F3 55qq ADDO adr16 Extended (direct)
F4 ssqq ANOB adr16 Extended (direct)
FS s5qq BITB adr16 Extended (direct)
F6 55qq LOB adr16 Extended (direct)
F7 55qq STB adr16 Extended (direct)
FS 55qq EORB adr16 Extended (direct)
F9 55qq ADCB adr16 Extended (direct)
FA 55q q ORB adr16 Extended (direct)
FB 55 qq ADOB adr16 Extended (direct)
FC ssqq LDD adr16 Extended (direct)
FD ssqq STD adr16 Extended (direct)
FE 55q q LOU adr16 Extended (direct)
FF ssqq STU adr16 Extended (direct)
E

6809 Post Bytes 1n Numerical Order

Post Post Post Post


Operand Form 1 Operand Form 1 Operand Form 1 Byte Operand Form 1
Byte Byte Byte

00 O,X 37 -9.Y 6E 14,S 84 (.Y]


01 1,X 38 -B,Y 6F 15.S 85 (B,Y)
02 2,X 39 -7,Y 70 -16,S 86 (A,Y)
03 3,X 3A -6,Y 71 -15.S 88 (nn.Y)
04 4,X 38 -5,Y 72 -14,S 89 (mmnn.Yl
05 5.X 3C -4,Y 73 -13.S BB (D,Y)
06 6,X 30 -3.Y 74 -12,S BC [nn,PCI3
07 7,X 3E -2.Y 75 -11,S BD {mmnn,PC]3
08 B,X 3F -1.Y 76 -10,S BF (mmnnl
09 9,X 40 o.u 77 -9,S co ,U+
OA 10,X 41 1,U 78 -B.S C1 .U++
OB 11.X 42 2.U 79 -7,S C2 .-u
oc 12.X 43 3.U 7A -6,S C3 .--u
00 13,X 44 4.U 78 -5.S C4 .u
OE 14,X 45 5.U 7C -4.S C5 B,U
OF 15,X 46 6.U 70 -3,S C6 A.U
10 -16.X 47 7.U 7E -2.S ca nn,U
11 -15,X 48 B,U 7F -1,S C9 mmnn,U
12 -14.X 49 9,U 80 ,X+ CB D.U
13 -13,X 4A lO.U 81 .X++ cc nn.PC2
14 -12.X 48 11.U 82 .-X CD mmnn,Pc2
15 -ll,X 4C 12,U 83 .--X 01 I.U++l
16 -10.X 40 13,U 84 .X 03 L--UI
17 -9.X 4E 14.U 85 � 04 LUI
18 -a.x 4F 15.U 86 A.X 05 (B.UI
19 -7,X 50 -16,U 88 nn.X 06 IA.Ul
1A -6,X 51 -15,U 89 mmnn,X DB (nn.U)
18 -5.X 52 -14.U 88 D,X 09 (mmnn,U)
1C -4.X 53 -13,U ac nn,PC2 DB (D,U)
10 -3.X 54 -12,U 80 mmnn,Pc2 DC (nn.PCJ3
1E -2,X 55 -11,U 91 LX++) DO (mmnn.PC]3
1F -1,X 56 -10,U 93 1.--Xl OF (mmnnl
20 O.Y 57 -9,U 94 LXI EO ,S+
21 1,Y 58 -8.u 95 (B,X) E1 ,S++
22 2.Y 59 -7.U 96 (A,X) E2 .-s
23 3,Y 5A -6,U 98 Inn. X) E3 .--s
24 4,Y 58 -5.U 99 (mmnn.Xl E4 .S
25 5,Y 5C -4.U 98 [D.Xl E5 B.S
26 6,Y 50 -3.U 9C (nn.PcJ3 E6 A,S
27 7,Y 5E -2.U 90 [mmnn,PC]3 EB nn.S
28 B.Y SF -1.U 9F [mmnn) E9 mmnn,S
29 9,Y 60 O,S AO ,Y+ EB D.S
2A 10.Y 61 1,S A1 ,Y++ EC nn.PC2
28 11.Y 62 2.5 A2 ,-Y ED mmnn,PC2
2C 12.Y 63 3,S A3 .-- Y F1 LS++l
20 13,Y 64 4,5 A4 .Y F3 L--SI
2E 14,Y 65 5,S AS B,Y F4 LSI
2F 15,Y 66 6,5 A6 A.Y F5 (B.Sl
30 -16.Y 67 7.5 AB nn.Y F6 IA.Sl
31 -15.Y 68 B,S A9 mmnn.Y FB (nn,S)
32 -14.Y 69 9,S AB D,Y F9 (mmnn,Sl
33 -13.Y 6A 10,S AC nn.PC2 FB (D,S)
34 -12,Y 68 ll.S AD mmnn,PC2 FC inn.PCJ3
35 -11.Y 6C 12,5 81 I.Y++l FD (mmnn.PCI3
36 -10,Y 60 13.5 83 [.--YI FF (mmnnl

Note 1: See Appendix B for addressing modes which the operand forms represent.

Note 2: May appear in source listing in the form label, PCR.


Note 3: May appear in source listing in the form llabei,PCRI.
Index

A register. See Accumulator A clearing bits, 13-10, 13-31, 15-30, 22-7


ABA,22-1 masking, 4-3-4, 13-30
Absolute addresses, 10-17. See also base page direct testing bits, 13-13, 13-30-31,22-7
addressing, extended direct addressing ANDCC, 3-5, 8-3,15-5, 18-4, 22-6,22-8-9
Absolute loader,2-17 masks for clearing individual flags, 22-8
ABX, 3-39,22-2-3 Apostrophe indicating ASCII character, 3-49,
difference f(om accumulator offset 6-5, 6-8
addressing, 3-29 Architecture of 6809 CPU, 3-3-5
difference from LEAX instruction,22-2-3 Argument lists,11-3-8
Access, 17-12,17-14 Arithmetic, 8-1-20
Access time,12-10, 21-5 add-ons,8-20
Accumulator,3-4,4-1-3 algorithms, 21-5, 21-6
A, 3-4 high-speed, 8-8, 8-12, 8-20
B,3-4 references,21-6
D,3-4,3-10 tables, 4-8-11
differences between A and B, 3-4, 4-3, 8-5 Arithmetic and logical expressions, 2-12, 3-50, 7-11
Accumulator offset addressing mode, 3-28-29, 4-9, Arithmetic processing units, 8-20
7-6, 9-14-15, 19-14 Arithmetic shift,4-3,6-10, 8-1, 8-7,8-12,22-11
difference from ABX instruction, 3-29 Array, 3-20, 3-31-32, 5-3, 8-7-8. See also data
Accumulator offset indirect addressing structures
mode, 3-29-31, 9-14, 12-13, 12-14 base address,3-20,3-28,4-9
Accuracy, 8-3-4, 8-6 index, 3-6, 3-20, 4-9
ACIA. See 6850 ACIA or 6551 AClA multi-dimensional, 8-7-8
Acknowledgment from a 6820 PIA,13-8,13-9,13-10 of addresses, 3-29-30,3-34-36,9-13-14,
Active transitions on a 6820 PIA control line, 13-4, 12-13-14
13-7--9, 13-38-39,15-8 one-dimensional,3-20, 5-4
ADC, 5-8, 8-1,8-3,8-5, 8-7,22-3-4 processing, 3-31- 3-32,5-4
AID converters, 13-13-46 ASCII character code,6-1-2
ADD, 4-2, 5-6, 8-5, 8-16, 15-27, 22-4-22-5 assembler format, 3-49,6-5, 6-8
execution diagrams,3-9,3-12, 3-14,3-16, binary conversion program, 7-8-10
3-21-24, 3-27,3-33, 22-4-5 comparison with BCD, 6-2, 6-8
ADDD,4-7- s �· 8-4,8-5,22-5-6 decimal conversion program, 7-6-7
execution diagrams, 3-10,3-34,22-5-6 FCC directive, 3-46-47
Adding Carry fbg to Accumulator, 5-9 hexadecimal conversion program, 7-6-7
Adding entry to list example, 9-2-3 letter offset,7-2
Addition: 7-bit version,6-1
BCD,8-4-6,18-11-12 table, 6-2
binary,4-2,4-7-8,8-2-4, 18-4-5,18-10-11 validity checking, 7-7
decimal, 8-4-6,18-11-12 ASCII code table,6-2
8-bit, 4-2, 18-10-11 ASCII strings,entry of,2-12,6-8. See also FCC
multiple-precision,8-2-6,18-4-5,18-11-12 directive
16-bit,4-7-8 ASCII to decimal conversion example,6-1, 7-6-7
Address arrays,3-29-30, 3-34-36,9-14,12-13-14 ASCII to EBCDIC conversion, 3-28-29
Address field,2-1,2-2, 2-10-12,3-6, 3-45, ASL, 4-3,5-14, 8-12,8-15, 13-14, 13-31, 22-9-10
3-48-50 multiplying by small integers, 7-8, 9-13
general description of options, 2-10-12 testing bit 6, 13-14
options in standard 6809 assembler,3-48-50 testing bit 7,6-10,13-14
Address register, 5-4. See also index register X, ASR,22-10-11
index register Y, stack pointer S,stack pointer U Assembler directives, 2-l,2-5-10, 2-12-14
Addressing bit in 6820 PIA control register, standard 6809 assembler,3-46-48
13-3, 13-7 Assembler-related errors, 19-15-16
Addressing modes. See also base page direct address­ Assemblers, 1-5-8, 2-1-18
ing,extended direct addressing, extended address field, 2-1,2-2, 2-10-12
indirect addressing,immediate addressing, advantages, 1-5, 1-6
indexed addressing modes,indirect addressing applications, 1-13
general description,3-6 arithmetic and logical expressions,2-12
6809, 3-7 choice, 1-7
specific descriptions, 3-7-38 comments,2-14
symbols,3-49 conditional assembly, 2-12-13
Alarms,15-1 definition, 1-5
Alphabetizing strings,6-1 delimiters,2-2-3
Analog-to-digital (A/D) converters, 13-44-47 directives, 2-l, 2-5-10,2-12-14
AND,4-3-4,13-10,13-30-31,15-30, 22-6-7 disadvantages, 1-7-8
xii

Assember (Continued) counting, 8-6


error messages, 2-16 subtraction, 8-5-6
errors from use, 19-15-16 BCD-to-binary conversion example, 7-8
features, 1-6-7 BCS, 22-12. See also BLO
field structure, 2-1-3 after CMP instruction, 4-6, 9-5,9-11, 19-17
formats, 2-2 BEQ, 22-12
inputs and outputs, 1-6 checking for FF (hex), 13-19
labels, 2-3-4,2-10, 4-7 checking for zero, 5-14, 19-22
location counter, 2-11-12, 4-6 comparing values, 4-5-6, 6-3
macros, 2-13-14 BGE, 5-12, 22-13
operations codes, 1-4,2-4-5 BGT, 5-12, 22-13-14
pseudo-operations, 2-1, 2-5-10,2-12-14 BHI, 22-14-15
rules, 1-6 after CMP instruction, 4-6, 9-11,19-7,19-12, 19-18
standard 6809 version, 3-45- 50 BHS, 22-15-16. See also BCC
symbol table, 2-7 use for clarity, 19-17
types, 2-15 Bidirectional capability of 6820 PIA, 13-37-38
Assembly-time arithmetic, 2-12,3-50,7-10 Binary machine language _programs, 1-2-3
Asterisk in standard 6809 assembler: Binary notation for masks, 4-3
before a line of comments, 3-45 Binary numbers, 3-49, 4-3, 7-8-10
current value of location counter, 3-49,4-6 use of% sign to designate, 3-49, 4-3
Asynchronous input/output: Binary rounding, 8-15
documentation of programs, 18-1-2, 18-5-7 Binary search, 9-4
handshake, 12-5-7 Binary-to-ASCII conversion example, 7-8-10
interrupt-driven, 15-28-30 Binary-to-hexadecimal conversion table, 1-3
6820 PIA, 13-49-52, 15-29-30 Bit-by-bit operations, 4-3
6850 ACIA, 14-1-6, 15-28-29 BIT, 13-31,14-6,22-16-17
TTY procedures, 13-48 Bit length, 8-3-4, 8-6
UARTs, 13-52 Bit manipulation:
Autodecrement, 3-31-36,5-3,6-6, 19-12 clearing bits, 4-4, 13-10, 13-22,13-43,15-6,
by 1, 3-32-33 15-30, 22-7
by 2,3-32,3-33-36 complementing bits, 22-35. See also EOR
compatibility with stack storage, 3-32,10-5 setting bits, 6-10,13-10,13-22,13-43,15-5, 15-13,
execution diagram, 3-34 15-30,22-56
indirect, 3-34-36 testing bits, 13-13-14,13-30-31, 15-8-9, 22-7
initialization, 3-32, 3-35, 5-3, 19-13 Bit numbering, 3-3, 3-18
Autoincrement, 3-31-36,5-2-3, 5-7,6-6, Bit patterns for instructions, 1-2,3-8, 3-18, 4-9, B -1
15-20, 19-12 Bit rate (for TTY), 13-48
alternative to DUL instruction, 22-59 Bit rate generator, 12-15
by 1, 3-31-36, S-6, 13-31-32 Blank code (in ASCII), 6-5,6-8
by 2,3-32,3-34-36, 5-17 Blanking leading zeros, 6-7-8,13-23-26
compatibility with stack loading, 3-32, 10-6, 13-31 BLE, 5-13,22-17-18
execution diagrams, 3-33, 3-35 BLO, 22-18. See also BCS
indirect, 3-34-36 use for clarity, 19-17
initialization, 3-32, 3-34,5-6 Block. See array, data structures
Automatic saving of registers, I 5-4-5,15-17 BLS, 22-18-19
Automatic (strobe) modes on a 6820 PIA, 13-7-10, after CMP instruction, 4-6, 7-3,9-12, 19-12
13-26, 13-27, 13-29, 13-40, 13-43 BLT, 5-13, 22-19-20
Auxiliary carry flag. See Half-carry flag BMI, 22-20
signed operations, 5-11
B Register.See Accumulator B
testing bit 6, 15-8-9
Backwards branches, 4-6,22-23
testing bit 7, 5-11, 5-15,13-11, 15-8, 19-5
Base address, 3-20,3-26, 3-28, 3-30, 4-9, 4-10, 7-4
BNE, 22-20-21
Base page. See direct page
checking for carry after INC, 8-15
Base page direct addressing, 3-4,3-11-13,4-1-2,
comparing values, 4-5, 6-6
execution diagrams, 3-11' 3-12
loop control, 5-6, 5-7, 19-22
Base register, 3-16, 3-17, 3-18, 3-19
Boldface type, 1-1
BASIC computer language, 1-9,1-111
Bootstrap loader, 2-17
Baud, 13-47
Borrow, 3-8, 4-5, 8-1, 8-6. See also Carry flag,
Baud rate generator, 12-15
subtraction
Baudot character code, 6-1
Bottom-up design, 17-26
ijCC, 22-11. See also BHS
BPL, 22-21
after CMP instruction, 4-5-6, 9-10, 19-12,19-17.
signed operations, 5-11
testing bit 0, 13-14
testing bit 7,5-11,13-11,13-14,13-39,13-47,15-9
testing bit 7, 5-14,13-14
BRA, 3-37-8, 5-15,22-21-23
BCD representation, 7-8, 8-4-6. See also decimal
Brackets around addresses, 3-15, 3-26,3-45
numbers
Branch instructions, 2-3, 3-36-3-38, 4-6-7. See
addition, 8-4-6
also relative addressing
xiii

Breakpoint, 19-2-5,19-8 Clearing memory example, 4-4


clearing, 19-4 Clearing 6820 PIA interrupt flags, 13-3,13-7, 13-11,
correcting return address, 15-14, 19-3 13-39,13-40,15-8,15-16, 15-17,15-19, 15-24, 19-16
example of use, 19-25-26 CLF, 15-5, 22-26
inserting, 19-3 cu. 15-5, 22-26
precautions, 19-5 CLIF, 15-5, 22-26
return address, decrementing of, 15-14,19-3 Clock interrupts, 15-24-24
setting, 19-4-5 CLR, 4-4, 5-8, 6-4,13-8,13-11, 22-27
software interrupt instructions, use of, 19-3-5 CLV, 22-27
BRN, 22-23 CMPA, B, 22-28-29
BSR, 10-1, 10-7, 10-17,22-23-24 branch instructions, 4-6
Bubble sort, 9-10 comparison with SUB, 7-7
Buffer, 9-5,15-11,15-19-20,15-22-23 confusion in use, 19-12
Buffered interrupts, 15-11, 15-19-20, 15-22-23 direction, 19-13
BVC, 22-25 effect on Carry flag, 4-5, 5-4, 19-12
BVS, 22-25 effect on Zero flag, 4-5,6-4, 19-12
Byte disassembly example, 4-4-5 input instruction, 13-11
Byte-length data, 3-46 signed numbers, 5-12
unsigned numbers, 4-5,5-12, 19-12
C flag. See Carry Flag
CMPD, X, Y, U, S, 22-28, 22-29-30
Calculating relative offsets, 4-6,5-6,5-9-10,
checking an address register, 5-3,7-10,19-7
5-13,5-15
length of operation codes, 10-16
Calculator chips,
Code conversion, 7-1, 7-7
Calendar time, 15-25-27
ASCll to binary, 7-10-11
Call by name, 11-13
ASCII to decimal, 7-7-8
Call by value, 11-13
ASCll to EBCDIC, 3-28-29
Call instruction. See BSR, JSR
BCD to binary, 7-8
Carriage return character, 6-2,6-4
decimal to ASCll, 6-1
Carry (C) flag; 3-4, 3-5,4-2,4-3, 4-5, 5-8. 8-1, 8-6
decimal to binary, 7-8
adding to accumulator, 5-8
decimal to seven-segment, 7-3-5,13-24-25,
arithmetic use, 8-1,8-3
18-11, 19-17, 19-20, 20-1
clearing of, 8-3,22-26
hexadecimal to ASCII, 7-2-4
decimal adjust, 8-5, 8-6
Coding, !V-3, 17-2
definition, 3-4
COM, 22-30-31
effect of CMP, 4-5,9-12, 19-12
Combining control information, 13-31-32
effect of MUL, 3-4,22-52
Commas in operand field, 3-45
equality case, 9-11,19-12,19-17
Comments, 2-2, 2-15,18-2-7
instructions with no effect, 3-5, 8-3,22-34, 22-28
delimiters in 6809 assembler, 3-45
mverted borrow, 8-6
examples, 18-4-7
parallel/serial conversion, 13-52
guidelines, 2-14-15, 18-2-4
position in CCR, 3-3
questions that comments should answer, 18-5
serial/parallel conversion, 13-47
Common-anode display, 13-22, 13-23
setting of, 8-3, 13-51,22-64
Common-cathode dipslay, 13-22, 13-23
shifts, 4-3, 8-12
Common programming errors, 19-11-16
subtraction, 8-5-6
Communications with interrupt service routines
Case structure, 17-17, 17-18

15-10-11, 15-18-19,15-29-21
CBA, 22-26
Comparison instructions. See CMPA CMPD
CCR. See condition code register
'

Compiler, 1-9,1-10
Centering data reception, 12-8,13-30, 13-48
Complementary binary form, 13-45
Changing the return address, 11-4,11-5,11-6,11-8,19-3
Computer program, 1-2
Changing values in the stack, 15-13-15
Condition code. See flag
Character codes, 6-1-2
Condition Code Register, 3-3,15-5,15-6, 15-14. See
Character manipulation, 6-1,6-5, 6-8,6-12
also ANDCC, ORCC
Character strings, entry of, 2-12,6-8. See also FCC
bit assignments, 3-3
directive
flags, 3-4-5
Checking an ordered list example, 9-3-4
Conditional assembly, 2-12-13
Checklist, 19-10-11, 19-17-18,19-22-24
Condition branch instructions, 4-7, 9-4, 19-12,
Checksum, 5-15,8-12
A-10-11
Circular shift. See ROL, ROR instructions
Consecutive structure, 17-16
Classes of data for testing, 20-3
Constant offset from base register, 3-17-23, 3-28,
CLC, 3-44, 8-3, 22-26
5-12, 9-7, 9-8, 9-9,15-14-15
Cleaning up the stack, 11-8,11-11, 11-13
comparison with accumulator offset, 3-28
Clear condition codes, 22-8-9
from hardware stack pointer, 10-7,15-14-15
Clearing bits, 4-4,13-10, 13-22,13-43,15-6, 15-30, 22-7
short offset modes, 3-20,3-21-23,5-13
Clearing breakpoints, 19-4
zero offset mode, 3-20,3-21
Clearing Carry flag, 8-3,22-26
Constant offset from base register
Clearing flags, 3-5,8-3,15-5,15-7,22-8-9. See also
indirect, 3-25-27,9-8-9, 10-17, 11-4
ANDCC instruction
xiv

Constant offset from program counter, 3-23-25, 10-17 sorting example, 19-21-26
comparison with program relative addressing, 3-37 tools, 19-1, 19-2-10
Control characters, 6-2,6-4 Debugging examples, 19-17-26
Control information, 13-30-32 DEC (decrement by I) instruction, 22-33-34
Control lines on 6820 PIA, 13-1,13-3, 13-4, 13-6-8 clearing bit 0, 15-12, 15-13,15-30
use independent of parallel data port, 13-40, effect on Carry flag (none), 8-6, 22-34
13-43,15-24 loop control, 5-5, 5-6, 22-38
Control ports, 12-2-4 Decimal accuracy, 8-3, 8-6
Control register: Decimal addition example, 8-4-6,18-11-12
in 6820 PIA, 13-3-10 Decimal arithmetic, 8-1,8-4-6,8-12-15,8-16,
in 6850 ACIA, 14-1, 14-3-5 18-11-12
Converters: addition, 8-4-6, 18-11-12
AID, 13-43-47 rounding, 8-16
D/A, 13-40-43 self-checking digit calculation, 8-12-15
microprocessor-compatible, 13-42 subtraction, 8-5-6,8-17
successive approximation, 13-44 Decimal default in address field, 2-10, 3-48, 19-15
Cost of redesign, 21-5 Decimal digits in ASCII, 6-1, 6-8
counter, 13-26-28 Decimal numbers:
Counting down, 5-6, 22-38 accuracy, 8-3,8-6
Counting I bits, 6-10,13-51 addition example, 8-4-6,18-11-12
Credit verification terminal example. See also arithmetic, 8-1,8-4-6,8-12-15,8-16, 18-11-12
verification terminal 16-9-13, 17-5-10, comparison with ASCII numbers, 6-2, 6-8
17-13-14, 17-22-25,17-29-31. counting, 8-6
Cross-assembler, 2-5 decrement, 8-6
Cross-compiler, 1-13 increment, 8-6, 8-16
Cross-reference, 2-16 rounding, 8-16
Current value of location counter, 2-11-12, 3-49,4-6 subtraction, 8-5-6,8-17
CWAI, 15-6, 15-17,22-31-22-32 Decimal subtraction, 8-5-6, 8-17
Decimal to ASCII conversion, 6-1
D register. See Double accumulator
Decimal to binary conversion example, 7-9
DAA, 22-32-33
Decimal to hexadecimal conversion table, 1-3
after series of additions, 8-14
Decimal to seven-segment conversion example:
effect, 8-5
debugging, 19-17-20
example programs, 8-4-6, 8-12-14, 8-16
documentation, 18-11
hexadecimal to decimal conversion, 7-3
program example, 7-3--6
use after certain instructions, 8-5-6
subroutine, 13-26, 18-11
DIA converter, 13-40-43
testing, 20-1
Darlington transistor, 13-22
Decisions, 17-12, 17-14
Data accepted flag, 15-21
Decoder, 7-1, 13-23-24, 13-26-27
Data accepted signal, 13-9
Decoding commands, 9-3
Data-address confusion, 2-11,4-3, 19-13, 19-19
Default values, 3-12, 3-13,3-48, 3-49,19-15
Data direction register, 13-1, 13-3, 13-6-7
addressing modes, 3-12, 3-13, 3-49, 19-15
addressing, 13-6
direct page, 3-12, 3-48
establishing directions, 13-7
errors, 19-15
DATA directive, 2-6-7, 2-10, 11-3. See also FCB,
number base in address field, 2-10,3-48, 19-15
FCC, FDB directives
Defensive programming, 2-3, 2-4, 2-7, 2-12,2-15
Data flowchart, 17-4
Defining inputs, 16-1
Data ready flag, 14-4, 15-18
Defining names, 2-7. See also EQU directive
Data ready signal, 12-6,13-8,13-9
Defining outputs, 16-2
Data structures, 3-20, 3-25-26, 9-5-9, 17-2,
Definition lists, 2-7,18-8-9
17-31-32. See also array, lookup table
Degenerate (trivial) cases, 9-11, 19-12, 19-24
design of, 17-31-32
Delay constant (for I ms delay), 12- l l, 12-12
selection, 17-32
Delay routines, 12-9-12, 13-6, 15-24-27
use, 3-20,3-25-26,9-6-9,17-31-32
using real-time clock, 15-24-27
Data transfer example, 4-1-2
Delimiters in standard assembler, 2-2-3, 3-45,6-8
Debouncing switches, 13-14-15
rules for use, 2-2-3
Debugging, IV-4, 19-1-27
Demultiplexer, 12-2, 12-3
assembler-related errors, 19-15-16
DES, 22-34
branches, 19-11
Design decisions, limiting effects of, 17-12,17-14
checklists, 19-10- II
Design of programs, 17-1-32. See also program
code con version example, 19-1 7- 20
design
common programming errors, 19-11-15
DEX, 3-41, 6-5, 22-34
definition, IV-4
DEY, 22-34
examples, 19-17-26
Digital-to-analog (D/ A) converters, 13-40-43
interrupt-driven programs, 19-16
Direct addressing. See also base page
loops, 19-11
direct addressing
programming errors, 19-11- 15
base page, 3-11-13, 4-1, 4-2, 21-2
review, 20-5
XV

definition, 3-6 E !lag, 3-5, 15-3-4, 15-6


execution diagrams, 3-11, 3-12, 3-13, 3-14 meaning, 3-5, 15-4
extended, 3-13-14 position in CCR. 3-3
special meaning to 6809 manufacturers, 3-11 use, 15-6
Direct memory access (DMA), 12-8 EBCDIC character code, 3-28, 6-1, 6-10
Direct page, use of, 3-12, 4-1, 4-2,5-9, 21-2 Edge-sensitive interrupt (NMI), 15-7,15-12
Direct page (DP) register, 3-4, 3-11, 3-12, 3-40. 7-8 Editing strings of digits, 6-8
default value, 3-12, 3-48 Effective address, 3-7, 3-14, 3-15, 4-9, 5-5-6, 6-5.
effect of Reset, 3-40 See also addressing modes, indexed
loading of, 7-8, 22-36, 22-73 addressing modes, LEA instruction
SETDP directive, 3-48 8-bit summation example, 5-5-5-7, 18-10- II
Directives, 2-1, 2-5-10, 2-12-14, 3-46-48. See Empty state, 9-9
also pseudo-operations Emulation, 20-2
Disabling interrupts, 15-2,15-11-13, 15-14-15 in-circuit, 20-2
Disassembly table, D-2-6 Enabling and disabling interrupts. 15-11-14, 15-17,
Displays, 13-20-29 15-31, 19-15. See also CLF, CLI. CWAL SEF, SEI
multiple, I 3-22-29 automatic by CPU, 15-3
multiplexing of, 13-26-29 during a service routine, 15-14-15
seven-segment, 13-22-29 errors, 19-16
single, 13-20-22 instructions, 15-5-6,15-17
Division, 8-1, 8-8-12 restoring state after disable, 15-13
by power of 2, 8-1,8-15 6820 PIA, 15-13-14,15-30
DMA, 12-8 6850 ACIA, 14-3-4, 15-29
DMA controller, 12-8 when to disable, I 5-l I -12
Do-forever structure, 17-17 when to enable, 15-12
Do-until structure, 17-16, 17-17 Encoder, 13-14, 13-38
Do-until structure. 17-16, 17-17 END directive, 2-9, 3-48
Do-while structure, 17-16, 17-17, 17-19, 17-26 Endless loop instruction, 17-17, 19-3
examples, 17-19 Entire (E) flag, 3-5, I 5-4, I5-6
flowchart, 17-17 Entire state of processor, 15-4-5,15-13-14
Documentation, 13-11, I 3-32, 8-1- 14 diagram, 15-5
comments, 2-15. 18-2-7 indexed offsets, 15-14
definition, IV -4 ENTRY directive, 2-9
flowcharts, 18-7 EOR, 5-16, 122-34-35
input/output routines, I 3-11 Equal elements, 9-11- 12
library forms, 18-9-12 Equality, checking for, 4-5
memory maps, 18-7-8 EQUATE (EQU) directive, 2-7,2-10
package, 18-12-13 Error-correcting codes, 6-10, 12-8
parameter and definition lists, 18-8-9 Error-detecting codes, 6-10, 12-8
production software, 18-13 Error exit from a service routine, 15-14
self-documenting programs, 18-1-2 Error handling, 16-3, 16-5, 16-8 .16-12, 17-14
status and control, 13-32 recovery, 17-14
structured programs, 18-7 Error messages, 2-16-17,19-15-16
Dollar sign, 3-9. 3-48 Errors, 19-11-16
Double accumulator, 3-3, 3-4. See also ADDD, Even parity generation example, 6-9-10, 13-52
CMPD and SUBD instructions Examples:
clearing of, 5-8 format, Il-l
errors in use, 19-15 interrupts, 15-5
instructions, 3-4,3-10, 3-33-34, 4-8, 22-6,22-69 standard memory addresses, "Guidelines for
organization, 3-4, 4-8 Examples" point (unnumbered) 7 under
shifting, 8-12 "Guidelines for Examples"
use in MUL instruction, 7-8, 8-7 subroutines, 10-3
Double buffering of interrupts, 15-11, 15-20, Execution time:
15-22-23 delay routine, 12-11-12
Double-byte shifts, 8-12 division program, 8-12
Double counting of switches, avoiding of, 13-15 indexed addressing modes, B-1
Doubling a binary number, 4-3, 5-15 instructions, E-2-5
Doubling a der imal number, 8-14-15 interrupt-related operation, 15-8
Doubly linked lists, 9-9 multiplication program, 8-8
Downward gro.vth of stack, 10-5-6, 11-2 reduction of, 21-4
DP register, 3 I, 3-11,3-12, 7-8. See also searching methods, 9-5
page register EXG, 22-35-37
Driver programs, 17-11. See also 110 driver jump and link, 10-17-18
Dummy operations on 6820 PIA, 13-9-11, 15-9, loading direct page register. 7-7, 22-36
15-17. 15-21 register codes, 22-37
Dump, 19-5-8 uses, 22-36
Dynamic allocation, I0-17 Expanding program stubs, 17-27-30
XIIi

Expressions,2-12,3-50,7-11 Halving a decimal number, 8-15


Extend addressing,3-13-14 Hand assembly, 1-6
special meaning to 6809 manufacturers, 3-13 Handshake
Extend indirect addressing,3-14-16,15-16 AID converter,13-43-47
post byte value (9F hex),3-1 S definition,12-5
EXTERNAL directive,2-9 diagrams,12-6-7
External reference,2-9 6820 PIA operating modes, 13-8-9
Extra factor of 2 in relative address calculations, software equivalent, 15-11
3-36-37,4-6-7,22-22 Hardware stack pointer, 3-4,5-6,10-3,10-5-7,10-
17,13-31-32,15-3-5, 15-13-IS.Seealsostack
F flag,3-5,15-3-5,15-15
pointer S
position in CCR, 3-3
Hardware/software tradeoffs, 7-2,12-9,13-38,
Factor of 6 in decimal addition,8-5
13-52-53, 15-28, 21-5
Fast interrupt, 15-3-6, 15-10, 15-30
Hashing,9-3
difference from regular interrupt,15-6
Headings,18-3
during execution of CWAI instruction,15-6
Hexadec imal conversion table,1-3
Fast interrupt disable (F) flag,3-5, 15-3-5, 15-15
Hexadecimal loader,1-4-5
FCB directive, 3-46, 4-9,7-6,11-3-5,11-7
Hexadecimal programs, 1-3-5
FCC directive,3-46-47, 6-8,11-3
Hexadecimal to ASCII conversion example,7-2-3,
FOB directive, 3-46-47,11-3-5.11-7
10-4-7
Field structure,2-1-2, 3-45
High-level language,1-8-14
Fields in post-byte,3-17-18, B-1
High-speed 110 devices, 12-2,12-8
FIFO, 9-5
Hold in the stack,11-8-11
5-bit offset,3-21-22, 5-13
Housekeeping directives, 2-5, 2-9-10
5357 AID converter,13-44-47
Human factors,3-33,16-3-4 .
Finding non-blank character example, 6-5-6
Human interaction, 6-8,16-3, 16-6. 16-8, 16-12
FIRQ input, 15-3-6, 15-10,15-30
Fixed format, 2-2,6-5 I flag, 3-5, 15-3, 15-5-6, 15-14
Flags,3-3-5,8-3. See also ANDCC, condition code position in CCR, 3-3
register,ORCC saving and restoring,15-13
bit assignments in CCR,3-3 Identifying a key by scanning, 13-32 to 13-38
clearing, 3-5, 8-3, 22-8-9 If-then-else structure,17-16,17-19, 17-25
effects of instructions,3-4-5,A-3-19 examples,17-19
setting, 3-5, 8-3,22-55-56 flowchart,17-16
Flexibility, 5-5, 9-6-7 Illegal indexed addressing modes, 3-17,3-35
Flowcharting,17-2-10, 18-7 Immediate addressing,3-6. 3-9-11,4-3,4-9, 5-9
advantages, 17-2-3 definition, 3-6
data,17-4 execution diagrams, 3-9-11
disadvantages,17-3-4 instructions lacking the mode,3-11
general version,17-4 Implied memory address. 3-20, 3-32. See also
limitations, 17-3-4 autodecrement, autoincrement, zero offset
programmer's version, 17-4 indexed addressing mode
switch and light system,17-4-5 Implied subtraction,7-7. See also CMP instructions
switch-based memory loader,17-5-6 INC,22-37-38
symbols,17-3 checking for FF. 13-19
use in documentation,18-7 counting, 6-4. 22-38
verification terminal, I 7-5-10 effect on Carry flag,8-6,22-38
Forcing direct or extended addressing,3-12-13, 3-49 rounding, 8-15
Forcing 8-bit or 16-bit offsets, 3-49 setting bit 0, 15-13,15-30
Format for storing 16-bit data and addresses, 3-46, 16-bit version,8-15
4-8, I 0-5 In-circuit emulation, 20-2
FORTRAN,1-8-10 Independence,17-1,17-12,17-14
FORTRAN-line (do) loops, 5-1-2, 17-16,19-12 Index,3-6, 3-20, 4-9-10, 7-4-5
Forward reference, 2-16 Index calculations,4-10, 8-7-8
Framing, 13-30 Index register X,3-4,4-9.5-6-7, 22-29
Framing error,13-48, 13-50,14-5 preference over Y, S, and U registers,5-7,21-3
Free format,2-2, 6-5 Index register Y,3-4,5-6
Frequently used instructions, 3-1,3-2 Indexed addressing modes,3-16-36
accumulator offset,3-28-29
General parameter passing techniques,11-3-13
accumulator offset indirect,3-29-31
General interrupt service routines,15-30-31
autodecrement, 3-31-34
Global variable, 2-14
autodecrement indirect, 3-34-36
H (half-carry) flag, 3-5, 8-5-6 autoincrement,3-31-34
effects of instructions,8-5-6 autoincrement indirect,3-34-36
need for,8-5 comparison with 6800 indexing,3-40
position in CCR,3-3 constant offset from base register.3-19-23
Half-carry flag. See H flag constant offset from program counter,3-23-25
Halt instruction. See CWAJ, SYNC instructions constant offset indirect, 3-25-28
xvii

extended indirect, 3-14-16 Instructions that read and write memory,13-11,


general description, 3-16-19 14-3, 14-5. 19-14
illegal modes, 3-17, 3-35 Interchanges,9-11,19-22-23
memory requirements,B-1 Intermediate carry flag. See Half-carry flag
notation, 3-19 Interpolation, 21-3
post-byte, 3-17-18, E-1 Interpreter,1-12
6800 indexing, comparison with,3-40 Interrupt disable flag,3-5,15-3, 15-5-6, 15-13-14
summary, B-1 Interrupt overhead, 15-15, 15-27
time requirements, B-1 Interrupt-related instructions,15-6-7
unimplemented modes, 3-17 Interrupt response, 15-2-4
Indirect indexed addressing, 3-17,3-25-27 Interrupt service routines, 15-8-11,15-13-33
Inefficiency of high-level languages, 1-11 communications with main program 15-10-11
Information-hiding principle,17-14 debugging, 19-16
Inherent addressing,3-6,3-8 general versions,15-30-31
Initial values in RAM, 2-9 keyboard, 15-17-20
Initializing variables, 5- l ,5-6,6-4, 19-11-12 printer, 15-2Q-23
Input handshake, 12-5-6 real-time clock, 15-23-28
Input/output startup, 15-15-17
categories, 12-2 subroutine use,15-13
chips, 12-14-15 teletypewriter, 15-28-30
comparison to memory,12-1 transfer of control, 15-2
examples, 13-12-52, 14-5-6 Interrupt vectors, 15-2, 15-4, 15-10
instructions, 13-10-11 table,15-10
interrupt-driven examples,15-15-30 Interrupts
1/0 device table, 3-29-31,3-34-35, 12-13-14 ACIA (6850), 15-8
1/0 driver, 9-5 advantages,15-1
INS,22-39 breakpoints, 19-3
Inserting elements in linked lists, 9-7 characteristics, 15-1-2
Instruction execution times, C-2-5 disabling, 15-2,15-11-15
Instruction set,1-1, 3-1, 3-7, 3-38 , 22-1 , A-2 disadvantages,15-3
Instruction tables enabling,15-2,15-11-13,15-17
execution times,C-2-5 executing general subroutines, 15-13
extensions from 6800 instructions,3-39,3-43-44 initialization,15-12-13
frequently used, 3-2 instructions, 15-5-6
generalizations of 6800 instructions, 3-43 nonmaskable, 15-2, 15-7
identical to 6800 instructions, 3-39,3-42 overhead, 15-15,15-27
implementations of missing 6800 operation PIA (6820),15-7-8
codes,3-44 polling systems, 15-2,15-8-9
memory usage, C-2-5 priority systems, 15-2, 15-24, 15-30-31
new instructions,3-43-44 response, 15-2-4
object codes in numerical order, D-2-6 service routines, 15-8-11, 15-13-33
occasionally used, 3-2 6809 system, 15-2-7
operation code mnemonics,3-39 vectored systems,15-2, 15-10
post-bytes in numerical order, E-1 Inverse, 4-11. See also ones complement
seldom used, 3-3 Inverting decision logic,19-12, 19-17, 19-20, 19-22
summary, 3-38-39,A-2-19 INX, 3-41, 3-44,6-5,19-13, 22-39
Instructions INY, 22-39
bit patterns,1-2, 3-18, 4-3 IRQ input, 15-3, 15-5, 15-10, 15-14-15
definition, 1-2-2 JMP, 3-11,5-14,9-13-14,10-6,19-15,22-39-40
effects on flags,3-4-5, A-3-19 JSR, 22-41-42
execution times, C-2-5 examp_les of, 10-6,11-5, 11-10
extensions from 6800 instructions, 3-39,3-43-44 execution time, I 0-7
frequently used, 3-2 function, 10-1
generalizations of 6800 instructions, 3-43 lack of immediate addressing, 3-11
identical to 6800 instructions, 3-39, 3-42 operation, 10-5-6
implementations of missing 6800 operation return address,10-5-6, 11-3-4
codes, 3-44,6-5, 22-1 Jump and link instruction,10-17-18,22-36. See also
input/output, 13-10-11 EXG instruction
interrupt-related,15-6-7 Jump instructions. See also BRA, condition branch,
memory usage,C-2-5 EXG, JMP, JSR,RTS,RTI, SWI,and TFR
new,3-43-44 differences in addressing,9-4, 22-40
object codes in numerical order, D-2 to D-6 EXG instruction, 22-36
occasionally used,3-2 jump table, 9-2-4
operation code mnemonics, 3-39,C-2-5 lack of immediate addressing, 3-11
recommended use,3-1 meaning,2-3
seldom used,3-3 TFR, 22-73
summary, 3-38-39, A-2-19 Jump table,9-2-4, 22-40. See also case structure
xviii

Keyboard interface, 9-14, 13-8-9, 13-22-40 Limited state of processor, 15-3,15-4,15-14. See also
encoded keyboard, 13-8-9, 13-38-40 E flag, fast interrupt, RTI instruction
unencoded keyboard, 13-32-38 diagram, 15-4
Keyboard interrupts, 15-17-20 indexed offsets, 15-14
Keyboard scan, I 3-34-38 Linear structure, 17-16
Link editor, 2-17
Labels
Link register, 10-17-18, 22-36. See also EXG
choice of, 2-4
instruction
definition, 2-3, 4-7
Linked lists, 9-7-9
field, 2-2-3
Linking directives, 2-9
first character, 3-46
Linking loader, 2-17
in jump instructions, 2-3-4
List processing, 9-1-9
meaning, 2-3,2-7, 2-9
Loader program, 2 -I 7
reasons for use, 2-3,2-4, 4-7
Local variable, 2-14
selection rules, 2-4
Location counter, 2-8-9, 2-11-12, 3-49, 7-6
6809 assembler, 3-45-46
Logic analyzer, 19-9- I0
space after, 3-45
Logical 110 device, 12-13-14
truncation, 2-4, 3-46
Logical shift, 4-4, 8-14-15, See also LSR
with assembler directives, 2-6-10, 3-48,7-6
Long branch instructions, 3-37, 5-10, 22-42-4 7
Lamp test, 13-23-25
Lookup tables
Language level, choice of, 1-12-14
arithmetic applications, 4-8- II
Latching, 2-1-3, 13-1, 13-39-40
code conversion, 3-28-29, 7-1, 7-4-6, 13-26
by 6820 PIA, 13-1, 13-39-40
1/0 device assignment, 3-30 , 3-34, 12-13
LBCC, 22-42
jump, 9-12-14, 22-40
LBCS, 22-42
keyboard, 9-14,13-37-38
LBEQ, 22-42
reducing execution time, 21-4
LBG E, 22-42-43
saving memory, 21-3
LBGT, 22-43
tradeoffs involved, 4-10- I I
LBHI, 22-43
uses, 4-11
LBHS, 22-43
Loops, 5-1-4. See also do-while structure
LBLE, 22-43
debugging, 19-11
LBLO, 22-44
decreasing execution time, 5-14, 6-4,6-6,21-4
LBLS, 22-44
execution time, 5-1
LBLT, 22-44
flowcharts, 5-2-3
LBMI, 22-44
sections, 5-1
LBNE, 22-44-45
structures, 17-16-17,17-19,17-21-22, 17-26
LBPL, 22-45
LSL, 22-51. See also ASL instruction
LBRA, 5-10, 22-45-46
LSR, 22-51
LBRN, 22-46
digit shift, 4-4
LBSR, 22-47
division by 2,8-15
LBYC, 22-47
normalization, 4-4,13-31
LBYS, 22-47
testing bit 0, 13-14, 13-17, 14-5
LDA,B, 4-1-2, 22-47-8
effects on flags, 5-11 Machine-independence, 1-8-9
execution diagrams, 3-29, 3-31, 3-35 Mach1ne language, 1-1-5,1-12
LDD, 4-8, 22-47-49 Macro, 2-13-14, 19-13
LOS, 4-10, 10-3, 22-47 Macroassembler, 2-16
execution diagram, 3-11 Maintenance, 13-43,IV -4,18-13
LOU, 4-10, 9-7, 10-16, 11-5, 11-7, 22-47 Maintentancc manual, 18-13
LOX, 4-9-10, 5-6, 9-7, 9-15, 22-47 Major changes in systems, 21-4-5
LOY, 4-10, 5-7,9-7, 10-16,22-47 Majority logic, 12-8, 13-30
LEA. See also indexed addressing modes,_6800 Manual mode, 13-8,13-10, 13-43,13-47
operation codes Manufacturer's mnemonics, 1-5
addressing uses, 6-5, 11-4, 11-8,19-3, 19-6,21-3, 22-50 Mark state on teletypewriter line, 13-48-49
arithmetic uses, 6-5, 8-J, 8-6,8-15, 11-8, 21-3, 22-51 Mask, 4-3, 13-13, 13-14, 13-30-31,13-35
cleaning up the stack, 10-17,11-8,11-11 by bit position, 13-14
description, 22-49-51 notation, 4-3
space allocation, 10-17, 11-8, 11-10, 19-6 Maskablc interrupt, 15-2-4
LED, 13-20-29 Masking example, 4-3-4
control of, 13-20-21 Master reset of 6850 ACIA, 14-3-5, 15-29
interface, 13-20-21 Matrix keyboard, 13-33-34
turn-on time, 13-21 Maximum count in loops, need for, 6-4
Length of registers, 3-3, 4-9 Maximum value
Letter offset, 7-3 example program 5-l 0 -· 12
Letters and numbers, confusing of, 2-4 subroutine, 10-10- II
Letters, seven-segment codes for, 13-23, 13-26 Medium-speed 1/0 devices, 12-2, 12-5-8
Library routines, 2-4, 10-1, 18-9-12 Memory dump, 19-6-8
Lightface type, I-I Memory map, 18-7-8
xix

Memory-mapped 1/0. 3-5, IJ-10-11 Negative logic, 13-20, IJ-23


Memory operations,4-3-4, 5-9. See also single- Negative numbers, 5-9-10
operand instructions Nested subroutines, 10-6, 10-17-18
Memory,special features of, 12-1 Nibble,4-4
Memory/time tradeoiTs, 4-10-11. 21-4 NMI input,15-2-3, 15-7-8, 15-10, 15-12·
Memory usage, decreasing, 21-2-3 Nonmaskable interrupt input. See NMI input
Meta-assembler, 2-16 NOP, 22-54-55
Microassemblcr,2-16 Normalization example, 5-14- 16
1\l
" icroprocessor analyzer, 19-9-10 Number base, choice of, 2-11-12, 3-48-49, 4-3
Microprocessor-compatible converters, IJ-42 Number sign, 3-9, 3-49,4-3
Microprogramming, 2-16 Number systems, default choice, 3-48,19-15
Millisecond delay program 12-9-12 Number systems, identification of, 2-10, 3-48-49
Minus sign,3-19 Numbers and letters, confusing of, 2-4
Missing 6800 operation codes, 3-41,3-44 Nybble,4-4
Mnemonic. 1-4, 2-4-5
Object code
definition. 1-4
alphabetical order, C-2- 5
manufacturer's, 1-5
definition, 1-2, 1-6
6809 set, 3-39
Jisassembly table, D-2-6
standard, 1-5
numerical order, D-2-6
Mnemonic operation codes for 6809,3-39
post-bytes,3-18, B-1, E-1
Modifying programs for your microcomputer,10-3,
Object program,1-2, 1-6
13-13, 15-16
Occasionally used instructions, 3-2
Modular programming, 17-11-14
Octal programs, 1-3
advantages, 17-11
Offset. 3-16-17, 5-13
disadvantages,17-11-12
Ones complement, 4-11, 4-14, 22-30-31
information-hiding principle, 17-14
Ones complement program. 4-11
principles,17-12
One-pass assembler, 2-16
review, 17-14
One-shot,12-9
switch and light system, 17-12
Operand field, 2-2, 2-10-12, 3-6, 3-45,3-48-50
switch-based memory loader,17-13
Operands, number of, 2-4-5
vcrif1cation terminal,17-IJ-14
Operation code, 2-1-2. 2-4-6
Module,17-11-12
alphabetical list for 6809, 3-39,C-2-5
Monitor programs, 1-5, 4-5, 7-3, 19-4
numerical order, D-2-6
breakpoints,19-4
Operation interaction,16-3, 16-6, 16-8, 16-12-13
interrupt handling,15-16
return of control, 4-2. 15-6, 22-71 OR, 22-55-56
use in setting bits,6-10,13-10, 13-22, 13-31,
stack pointer, 10-3
13-43, 15-13-14,15-30
Motorola standard assembler, 3-22, 3-45-50
MUL,7-9, 8-7, 22-51-52 ORCC, 3-5, 8-3,13-52, 15-5, 22-55- 56
masks for setting individual flags, 22-56
effect on flags, 22-52
Order of instruction execution, 5-7
Multibyte data, updating of. 15-12
Multidimensional arrays,8-7-8 Ordered list example, 9-4-5

Multiple origins, reasons for, 3-47. See also ORG ORIGIN (ORG) assembler directive,2-8,3-47,4-10
Output control assembler directives, 2-9-10
directive
Output handshake, 12-5, 12-7
Multi-position switches, 9-14, 13-16-20
Multiple-precision arithmetic, 8-1-6 Output ready signal, 12-7, 13-40

Multiple-precision binary addition example Overflow, 5-12


Overllow (V) llag, 3-3,35)-5, 4-5, 5-12
commenting,18-4-5
definition, 3-5
program example, 8-2-4
position in CCR, 3-3
subroutine,10-15-16, 11-6-8,11-12-13
signeu numbers, 5-12
Multiplexing displays, 13-25-29
Overrun error,13-52,14-2
Multiplexing 1/0 devices, 12-2-5
Multiplication,7-9, 8-1,8-7-8 P register. See condition code register, flags
by power of 2, 8-1. 8-14-15 Parallel I/O, 13-16, 13-22, 13-32, 15-17-23
Multiplication example, 8-7-8 Parallel interface Jevices,12-14-15. See also 6820
Multiplying by small decimal numbers, 7-9 Peripheral Interface Ad<tpter
N llag, 3-3, 3-5,4-5, 5-12, 5-15, 13-11, 13-31 Parallel interface standards, 12-14
Names,use and choice of, 2-4, 2-7,2-10 , 18-2, 18-8 Parallel/serial conversion. 13-48,13-51-52
National 5357 AID converter, 13-44-47 Parameter lists, 18-8-9
NEG, 22-53-54 Parameters, 10-2, 10-7, 10-9,10-11, 10-14,10-16
Negative clements example, 5-9-10 general passing techniques, 10-2, 11-3-13
Negative flag, 3-5 types, 11-14
BIT instruction,13-31 Parentheses, 3-50
meaning, 3-5,4-5, 5-11 Parentheses around addresses, 5-6
position in CCR,3-3 Parity,6-9-10, 12-8, 13-48, !3-52
signcu numbers,5-12. 5-15 Parity generation,6-9-10. 12-8, 13-52
testing bit 7, 13-11 PASCAL, 1-8, I - l l
usc, 3-5, 13-11' IJ-31
XX

Passing parameters principles, 17-1-2


argument lists. 11-J-!l review, 17-32-33
definition, 10-2 structured programming, 17-15-26
general methods, 11-3-I 3 top-down design, 17-26-JI
in registers, 10-2, 10-7, 10-9, 10-11, 10-14, 11-3 Program logic manual, 18-13
in the stack, 10-2.10-7,11-8-13 Program loops, 5-l- 3
Pattern comparison debugging, 19-11,19-17,19-22
program example, 6-11-13 reducing execution time, 6-4, 21-4
subroutine, 10-12114 time/memory tradeoffs. 21-2.21-4
PCR notation, 3-19,3-25, 3-49, I 0-17, 22-50 Program relative addressing, 3-23-25. 3-36-38
Pending interrupts, 15-8 Program speed, increasing. 21-4
Percentage sign, 3-49, 4-3 Program stub, 17-26-28
Peripheral interface adapter. See 6820 Peripheral Programmable 1/0 devices, 12-14-15. See also
Interface Adapter 6820 Peripher<JI Interface Adapter
Peripheral ready signal, 12-5, 12-7,13-8, 13-11, 14-4 Programm<Jble timer, 12-9
Physical 1/0 device, 12-13 Programmed 1/0, 15-1
PIA. See 6820 Peripheral Interface Adapter Programmer's flowchart, 17-4
Plus sign, 3-19 Programming mode of 6809 processor, 3-3
Pointer, S-3, 5-6 Programming time, division of, IV-3
Polling, 12-5, 13-11,15-8-9 Pseudo-operations, 2-1.2-5-10, 2-12-14.
definition, 12-5 3-46-48, 11-5, 3-46-48,11-5
6820 P1As, 13-11,15-8-9 definition, 2-1, 2-5
of 6850 ACIAs, 15-8 general description, 2-5-10, 2-12-14
Polling interrupts, 15-2, 15-9-10,15-29 mixing with instructions, 11-5
disadvantages, 15-9 standard 6809 assembler, 3-46-48
Portability, 1-7, 1-9 PSH, 22-57-58
Position. determination of. 3-23-24, 10-17, 22-51 bit assignments for registers, 11-2-3
Position-independent code, 3-23,10-2, 10-17,22-51 examples, 11-5, 11-10
Positrve logic, 7-4,13-20.13-23 operation, 11-1-J
Post-byte, 3-17-18, 3-40, 4-9, 5-13 order for storing registers, 11-2
bit definitions, 3-18 passing parameters, 11-5, 11-8
extended indirect addressing, 3-15 reducing memory usage, 21-2
extra time and memory requirements, R-1 saving interrupt status, 15-13
fields, 3-17-18 saving registers, 10-9,12-11
information contained in it, 3-17 temporary storage, 9-12
list in numerical order, E-1 PUL. 22-58-59
position in instruction, 3-17.3-18 alternative that affects flags. 22-59
purpose, 3-17 bit assignments for registers, 11-2-J
Post bytes, meanings in numerical order, E-1 examples. 11-5-7.11-11
Postincrement, 3-17 operation, 11-1-J
Power fail interrupt, 15-2,15-7, 15-24 order for loading registers, 11-2
Precedence rules, 3-50 passing parameters, 11-5, 11-7, 11-11
Predecrement, 3-17 replacement of RTS, 11-6, II-II, 22-59, 22-63
Prctix byte, 6-13 restorr ng interrupt stat us. 15-1 3
Preindexcd addre�sing, 3-17 restoring registers, 10-9, 11-6, II-II, 12-11
Printer interrupts, 15-20-23 temporary storage, 9-12
Priority interrupt controller (6828), 15-10 Pull order for registers, 11-2
Priority interrupts, 15-2, 15-6, 15-9. 15-24, 15-31 Pushbutton, 13-12-16
Priority register, 15-2, 15-31 Push order for registers, 11-2
Problem definition. 16-1-14,17-32-33
Queue. 9-5-9
definition, IV-J
examples, 16-4-13 RAM, initiali1.ation of, 2-9,19-11-12
litctors, 16-1-4 Random test cases, 20-1, 20-J-4
review. 16-14,17-33 Range
switch and light system, 16-4-6 8-bit signed offset, 3-23, J-36, 4-6, 5-8
switch-based memory loader, 16-6-9 5-bit signed offset, 3-20, 5-12
verirrcatinn terminal, 16-9-IJ offset from program counter, 3-36, 4-6, S-8-9
l'rncedure-orrented language. 1-8 RDRF flag (in 6850 ACIAJ, 14-3-5
Processing requirements, 16-2, 16-5, 16-lL 16-12 Read-only bits, 11-3, 13-7
Production software. documentation of, 18-13 Read-only memory, execution from, 2-9. 5-2, 11-3.
Program, 1-2 19-4,19-15
Program counter, 2-3, J-4, 4-6. 10-1-2, 1-5-7 argument lists, 11-3
determination of current value, 3-23.10-17,22-51 breakpoints, 19-5
Program design, 17-1-34 errors, 19-15
delinition, JV-3,17-1 Read strobe from 6&20 PIA, 13-7-10
flowcharting, 17-2-10 Read/write (1{/W) sign<JI, use in addressing 6850
modular programming. 17-11-14 ACIA, 14-1-2
xxi

Real-time clock, 15-23-28 Revisions, documentation of,18-3-4


clock time, 15-25 RMB directive,3-47
definition, I 5-24 ROL, 22-59-60
frequency, I 5-24 double-length shifts, 8-12
high-frequency,15-24, 15-28 serial 1/0, 13-48-49
priority, I5-24 testing bits 6 or 7, 13-14
service routines, 15-25 Rollover, 13-38
service time, 15-27-28 ROM simulator,20-2
synchronization, 15-24 ROR,22-60-62
Receive routine, 13-48-51, 14-5, 15-28-30 serial 1/0, 13-48-49
Recovery from lethal errors, 17-14 Rotate instructions. See ROL, ROR
Recursive subroutine, 10-3 Rounding
Redesign of programs, IV-4, 21-1-6 after M U L, 22-52
Reentrant programs, 10-2 binary. 8-15
definition, 10-2 decimal, 8-16
examples, 10-7,10-9, 10-11, 10-14,11-6-7, II-II RS-232 interface, 12-14
stack usage, I 0-17 RTI, 15-6, 16-13, 15-17, 15-19, 21-3,22-61-62
standard subroutines, 15-31 reenabling interrupt status, 15-1
Register addressing, 3-6, 3-8, I I -I- 2 RTS,22-62-63
Register designations after operation codes,3-45 changing return address, 11-4
Register dump, 19-5-6 effect, I 0- I - 2
Registers,3-3-4 execution time, I 0-7
coding in EXG, TFR instructions, 22-37 multiple exits, 10-14
diagram, 3-3 operation, 10-6
indexed oll5ets in the stack, 15-14 reducing execution time, 21-3
order in the stack,15-4-5, 15-14 replacement by PUL, 11-6, II-II, 22-63
preference in use, 21-3 Run-time package, I-ll
pull order, I 1-2
S flag. See Negative flag, Sign flag
push order, 11-2
S register. See stack pointer S
Regular interrupt, 15-3, 15-4, 15-8, 15-15
Sampling inputs. 12-8, 13-30
Relative addressing, 3-6, 3-36-38, 4-6, 5-8
Saving and restoring interrupt status, 15-13, 15-30
Relative offsets, calculation of, 4-6-7, 5-6-7,
SBA, 22-63
5-9-10, 5-12, 5-15, 22-22-23
SBC, 8-1, 22-63-64
Relocatable programs, 3-36, 10-2, I 0-7, 10-11
Searching examples, 9-1-5
Relocating loader, 2-3, 2-17, 10-2
Searching methods, 9-4
Relocation constant,2-3, 10-2
SEC, 8-3. 22-64
Reorganizing programs to save execution time, 5-14,
SEF, 15-6,22-65
6-4, 6-6,21-4
Segments, labeling of, 7-3, 13-23
Repeat-until structure, 17-16
SEt, 15-6, 22-65
RESERVE assembler directive, 2-8-10. See also
SElF, 15-6, 22-65
RMB directive
Seldom used instructions. 3-3
Reset,15-8-9
Self-assembler, 2-16
address, 3-4 7, 15-9
Self-checking numbers
effect on flags, 15-2, 15-15
program example, 8-12-15
effect on interrupt system, 15-2-3, 15-12, 15-15
testing, 20-4
6820 PIA, 13-3, 13-39, 15-8, 15-15
Self-compiler, 1-11
6850 ACIA, 14-3-5
Self-documenting programs, 18-1-2
vector, 15-10
Semaphore, 15-11
Resident assembler, 2-16
Separating status information, 13-30-31
Resuming programs after a breakpoint, 19-3, 19-5
Sequential execution of instructions, 1-2, 17-16, 19-14
Return address, I 0-1-2, 10-5-7
Sequential structure, 17-16
adjustment after breakpoint, 19-3
Serial input/output,13-48-52, 14-1-6, 15-28-30
adjustment past argument lists, 11-4-6, 11-8
interrupt-driven version, 15-28-30
changing in stack, 15-14-15
LSI devices, 12-15, 13-52-53
in user stack, 22-59
order of transmitting bits, 13-48
restoring by EXG, 10-18
6850 ACIA, 14-1-6
restoring by PUL, 11-6, 11-11,22-59, 22-63
standard intefaces, 12-14
restoring by RTI, 15-6, 22-61-62
teletypewriter 1/0, 13-47-52
restoring by RTS, 10-6
UARTs, 13-52
saving by CWAI, 15-6, 22-31
Serial interface devices, 12-15, 14-1-6. See also
saving by EXG, 10-17-18.22-36
6850 ACtA
saving by interrupt response, 15-3-4
Serial interface standards, 12-14
saving by JSR, I 0-5-7
Serial output from 6820 PIA. 13-10, 13-43,13-47, 15-29
saving by PSH, 22-59
saving by SWI, 15-6, 22-70-71 Serial to parallel conversion,13-48 , 13-52, 15-28
user stack, 22-59 Set conditions codes, 3-5,8-3, 13-52, 15-5, 22-55
Return instruction, 10-1. See also RTI, RTS SETDP assembler directive, 3-48
Returning control to the operating system, 15-6, 22-71 Setting bits, 6-10, 13-10, 13-43,15-5, 15-30, 22-56
xxii

Setting breakpoints, 19-3-5 6551 Asynchronous Communications Interface


Selling directions in 6820 PIA,13- l , 13-6-7 Adapter (ACIA), 12-15
Selling !lags, 3-5,8-3, 13-52, 15-5, 22-55-56 6800 compatibility,3-38-44
in the stack, 15-14. 15-15 addressing modes, 3-40
Setting 6820 PIA status bits,13-3-4,13-7-9, differences, 3-41,3-43
13-11, 13-38-39, 13-44, 15-8 flags, 3-40. 22-50
Seven-segment code, 7-3-5. 13-22-24 indexing, 3-40
conversion program,7-3-5,18- l l instructions. 3-41-44. 6-5. 8-3, 10-5. 22-1
decimal digits, 7-3, 13-25 object code, 3-3!1, 3-42
letter and symbols, 13-26 registers,3-40
Seven-segment displays, 7-3,7-5. 13-22-29,18-11, similarity, 3-38
19-17-20, 2-10 stack pointer,3-41. 10-5, 22-75
labeling of segments, 13-23 6800 operation codes, 3-41-44, 6-45, 8-3, 10-5,
7447 seven-segment decoder/driven, 13-23-24 22-1. See also CLCL, CLI, DEX, IN X. SEC, SEI
74148 priority encoder, 13-17 6801 compatibility, 3-44, 8-12, 22-3
SEV, 22-65 6820 Peripheral Interface Adapter (PIA), 12-15,13-1
SEX, 22-65-66 addresses, 13-3
Sharing of information (among modules), 17-12, 17-14 automatic strobe mode, 13-7-10, 13-26-27,
Shift instructions. See also ASL, ASR, LSR, ROL, 13-29. 13-40, 13-43
ROR instructions B port drive, 13-21-22
double-length,8-12 bidirectional capability, use of. 13-37-38
effects of, l 9-13 block diagram,13-2
Shift left example,4-2-3 clearing status bits, 13-3, 13-7, 13-11, 13-39 ,15-9
Short data fields, processing of, 13-30-32 control lines, 13-3-4, 13-6-10
Short (5-bit) oi'L�et indexed addressing mode,3-20. 5- control register, 13-3-10
Short relative branches, 5-8 data direction register, 13-1, 13-3. 13-6-7
Sign extension,5-12. See also SEX instruction differences between port A and port B. 13-7. 13-21
Sign (negative) llag,3-3. 4-5. 5-12,5-14,13-11, 13-31 disabling interrupts,15-11-12, 15-30
Signature analyzer, 16-3 document'ation problems,13-11, 13-43
Signed numbers,comparison of. 5-12 dummy operations, 13-9, 15-9, 15-17,15-21, 15-24
Signed offsets, 3-20, 3-23, 3-28-29,3-36-37. 3-40, enabling interrupts, 15-12-13,15-30
4-6, 5-12,22-2. See also A BX instruction examples of initialization, 13-8-20
Signetics NE5018 D/A converter, 13-40-43 general description,13-1
Simulator program 19-8-9 indexed offsets for registers. 13-3,13-16
Single-bit errors, 6-10 initialization, 13-6-10
Single-entry,single-exit structures, 17-15-16 internal addressing, 13-3
Single-operand instructions, 3-8 interrupts, 15-7-8,15-11-13
accumulator,3-8 interrupt inputs, control of, 13-7,15-7-8
application to memory,4-3-4,5-8 latching, 134-1. 13-39-40
e)(ecution,4-4 manual mode, 13-8, 13-10,13-43, 13-47
immediate addressing, lack of,3-11 output strobes, 13-7-10, 13-26-29, 13-43
indexed addressing, 7-11 pending interrupts, 15-8
read-only memory or registers, 14-3, I 9-14-15 polling,15-9-10
usc in 1/0, 13-11, 14-3,19-14 read strobe,13-7-10
Single-step mode,19-2 registers,13-1, 13-3
example of use, 19-18-19 reset,13-3,13-39, 15-8
limitations, 19-2 setting status bits, 13-3-4,13-7-9
16-bit addresses or data,storage of, 3-48,4-8 transferring data, 13-10-11
i6-bit decrement in memory,15-14, 19-3 write strobe, 13-7, 13-9, 13-26-29, 13-43
16-bit increment in memory, 8-15 6821 Peripheral Interface Adapter (PIA),12-15. 13-1
16-bit instructions,3-10,3-13-14,4-8,4-10 6828 Priority Interrupt Controller, 15-10
autodecrement, 3-33-34 6840 Programmable Timer, 15-24
base page direct addressing, J-11 6844 DMA Controller, 12-8
double accumulator instructions. 4-8, 4-11. 5-8 6846 Multifunction Support Device
extended direct addressing,3-13 (ROM/10/Timer), 12-9, 15-24
immediate addressing, 3-9-10 6850 Asynchronous Communications Interface
moving addresses, 9-6 (ACIA), 12-15, 14-1-6
operations on index registers and stack addressing, 14-1,14-3
pointers, 4-10 block diagram, 14-2
transfers, 7-8 control register,14-1, 14-3-5
16-bit ones complement example, 4-11 features,14-3-4
16-bit registers,3-3-4, 4-8- I 0, 5-6,10-16 initialization, 14-5, 15-29
choice of, 5-6, 10-16, 21-3 interrupt mode,15-28-29
transfer to or from stack,11-2, 22-57 interrupts, I 5-8-9
16-bit shift, 8-12 master reset, 14-3-5,15-29
16-bit summation example, 5-6-8 polling
6502 compatibility. 3-45, 10-5 power-on reset,14-5
6522 Versatile Interface Adapter (VIA), 12-15 read-only registers,14-3
xxiii

receive routine, 14-5 temporary storage, 9-12, 10-9,10-17,11-8,


register contents,14-3 -·4 13-3,15-13,15-19,15-30
reset,14-3-5,15-29 usual assignments, S-6
status register, 14-3, 14-5 Stack pointer U, 3-3,3-4
transmit routine,14-6 difference from stack pointerS, 3-4,22-58
write-only registers,14-J-4 index register,3-17,3-19,3-23,3-35,5-7,8-3,19-6
-
Slow 1/0 devices,12-2-5 passing parameters,10-16,11-2,11-5 :__7,11-11
Software delay routines, 12-9-12, 13-46 subroutine linkages, 22-59
Sortware development Stack values,changing,15-13115
coding, IY-3 Standard mnemonics, 1-5
debugging,19-1-27, 20-5 Standard 6809 assembler (from Motorola),3-45-50
documentation, 18-1-14 address field,3-48-50
tlowcharl, IV -2 addressing mode notation, 3-49
measuring progress, IY-3 arithmetic and logical expressions, 3-50
problem definition, 16-1-14 automatic optimization of constant offset
program design, 17-1-34 mode, 3-22
redesign, 21-1-6 delimiters, 2-3, 3-45
stages, Y
I -1-4 field structure, 3-45
testing, 20-1-6 labels, 3-46, 3-48
Sort ware handshake, 15-11 pseudo-operations, 3-46-48
Software/hardware tradeoff's, 7-1,12-9, 13-38, Start bit,12-5,13-48, 13-49
13-52-53,15-27,21-5 Start bit Interrupt,15-29-30
Software interrupt instructions, 22-70-71 Starting address of any array or table, 3-20, 3-28,
availability of SWI2 lO end user,15-6 3-30, 4-9-10, 7-5-6, 8-7
br�akpoint,19-3-5 Starting code, searching for, 13-30
debugging usc, 19-3-5 Startup interrupt, 15-15-17
decrementing return address after breakpoint, Statement, 2-1
15-14, 19-J Static allocation of temporary storage, 10-17
effects,15-6 Status nag. See condition code register nags
reducing memory usage, 21-3 Status information,13-29-31
transferring control to operating system,15-6, 22-71 favored bit positions,13-31
trap,15-6 Status register
uses,15-6,19-3-5,22-71 6809 CPU. See condition code register
vectors,15-10 6850 ACIA, 14-3,14-5
Software simui<Hor, 19-8-9,20-2 STD<S,U,X,Y),22-66-68
Sorting example effects,4-8
debugging,19-21-26 moving addresses, 9-6, I 1-4, 11-6,11-8
program,9-10-12 two-byte operation codes,10-16,22-68
testing, 20-4 Stop bit,12-5,13-48, 13-52
Sorting methods, 9-11-12 Storage requirements
Source code, 1-6 ASCII,6-2, 6-8
Square brackets indicoting imlirection,3-15, 3-45,3-49 BCD, 6-2, 6-8, 7-8
Space state,13-48,13-49 Stray interrupts,clearing of, 13-39,13-47,15-21
Spaces in 6809 assembler statements, 3-45 String comparison, 6-11 -13, 10-12-14
Spaces in strings of characters, 6-5, 6-8 String editing, 6-5-10
Speed,increasing of,21-4 String length
STA ,B, 3-11, 4-1 -2,22-66-67 program example,6-3-4
Stack subroutine,10-7-9,11-4-6,11-8-11
changing values saved in, 15-13-15 Strings of characters, 6-1-16
interrupts,15-3-5 Strobe,12-5,13-38
parameter passing, 10-2, 10-7, 11-8-13 Strobe signal from 6820 PIA,13-7,13-9-10,
subroutine return addresses, 10-1, 10-5, 22-59 13-26-29,13-40
temporary storage, 9-12, I 0-9, I 0-17, 11-8,13-31 Structured programming,17-15-26,18-7
Stack pointer,3-J-4,11-1-2 advantages,17-19
Stack pointerS,3-4 disadvantages,17-20
argument lists, 11-3-8 review,17-25
contents,10-6 rules,17-26
difference from stack pointer U,3-4,22-58 structures,17-15-19
indexed offsets for registers, 15-13-15 switch and light system,17-21
initialization,10-J, 10-5 switch-based memory loader,17-21-22
interrupts, 15-3-5 terminators, 17-26
JSR instruction, I 0-5- 7,22-41-42 use in documentation, 18-7
parameter passing, 10-2, 10-7,11-8-13 verification terminal, 17-22-25
return address, 10-6 when to use,17-20
RTI instruction, 10-6-7, 22-61-62 Structured testing,20-2-3
RTS instruction, 10-6-7,22-62-63 Structures. See data structures, structured programming
subroutine use, I 0-5-7 Stubs,17-26-28
SWI instructions,15-6,15-10,19-3-5,22-70-71 SUB,7-7,8-5-6,8-17,22-68-69
xxiv

SUBD. 4-14, 8-5, 22-68-69 SYNC, 15-6-7, 22-71


Subroutine documentation, 10-3 diagram, 15-7
examples, 10-5,10-9, 10-11, 10-14, 10-16, 11-5, Synchronizing with 1/0 devices, 12-5,12-8,
11-7, 11-10, 11-13 13-29-30
library examples, 18-9-12 Synchronizing with real-time clock, 15-23-24
Subroutine linkages Synchronous 110, 12-8
hardware stack, 10-5-6, 22-41 Syntax, 1-10
index register, 10-17-18, 22-36
TAB, 22-72
user stack, 22-59
Table, lookup, 3-28-31, 4-8-11, 7-1,7-4-6, 9-1,
Subroutine library, 10-1, 18-9-12
9-3, 9-5, 12-13-14. See also lookup tables
Subroutines, 10-1-20,15-13,18-9-12
Table of squares example, 4-8-II
comparison with macros, 2-3
TAP, 22-72
delay, 12-10-12
TBA, 22-72
documentation, 10-3,18-9-12
TORE llag in 6850 ACIA, 14-3-4, 14-6
errors in usc. 19-13
Teletypewriter data format, 13-49
examples, 10-4-16,11-4-13,18-10-12
Teletypewriter interface, 13-48-53, 14-1-6
instructions, 10-1-2, 10-5-6
Teletypewriter interrupt, 15-28-30
interrupt service routines. use by, 10-2,15-13
Teletypewriter output routine
library, 10-1, 18-9-12
commenting, 18-5-7
linkages. 10-5-6,10-17-18,22-36, 22-41,22-59
self-documentation, 18-1-2
macros, comparison with, 2-3
Testing, 20-1-6
nesting, I 0-17
aids, 20-2
parameters, I 0-2. 11-4
code conversion e11ample, 20-1
passing parameters, 10-2, 10-7, 11-3-13
data, selection of, 20-3
position-independence, I 0-2,I 0-17
definition, IV-4
reducing execution time, 21-5
debugging, relationship with, 20-1
reducing memory usage, 21-2, 21-3
examples, 20-1,20-4
reentrancy, 10-2
review, 20-5
relocatability, I0-2
rules, 20-2-4
specifying parameters, 11-14
self-checking numbers example, 20-5
storage allocation, 10-17
sorting example, 20-4
types, 10-2
special cases, 20-3
Successive approximation AID converter, 13-44
structured testing, 20-2-3
Summation example, 5-4-9, 18-10-11
test data, selection of, 20-3
SWI, 4-2. 15-6,15-10, 19-3-5. 21-3-4,22-70-71.
tools, 20-2
See also software interrupt instructions
vector, 15-10 Testing bits, 13-13-14, 13-30-31,15-8-9,22-7

Switch and light system example; Testing examples, 20-1,20-4


error handling, 16-5-6 TFR, 22-72-73

flowchart, 17-4-5 direct page register, loading of,7-7,22-73


effects, 7-7
inputs, 16-4
modularization, 17-12 examples of use, 4-4, 7-7,19-6

outputs, 16-5 jump instruction, 22-73

problem definition, 16-4-6 lo<�ing direct page register, 7-7, 22-73

structured program, 17-21 order of operands, 19-12

top-down design, I 7-27-28 program counter, determination of current

Switch-based memory location example value, 10-17

error handling, 16-8 register codes, 22-77


restrictions, 7-7, 22-73
flowcharts, 17-5-6
use-;, 22-73
inputs, 16-6,16-8
Time/generality tradeoiTs, 11-3
modularization. 17-13
operating interaction, 16-8-9 Time budgets for delay routines, 12-11-12
Time constants, 12-11-12
outputs, 16-8
problem definition, 16-6-9 Time/memory tradeolls,4-10-11, 21-2-4

processing requirements, 16-8 Time-wasting routines, 12-9-12. 13-49, 15-23-27

structured program 17-21-22 Timing loop,l 2-9-23, 13-49


Timing methods. 12-9-12
top-down design, 17-28-29
choice, 12-9
Switch bounce, 13-14-15
real-time clock,15-23-27
SWI2, 22-70-71. See also soft ware interrupt
Top-down design. 17-26-31
instructions
advantage�. 17-27
avoidance in packaged software, 22-71
disadvantages. 17-27
vector, 15-10
SWI3, 22-70-71. See also software interrupt procedure,17-31
review, 17-JI
instructions
stubs, 17-26-28
vector, 15-1 0
Switches, 13-12-20 switch and light system. 17-27-28

Symbol table, 2-7 switch -based memory loader, 17-28- 29

Symbols for llowcharting, 17-3 verilication terminal,17-29-31

---··· ----- _ _,__


XXV

TAP, 22-74 Variable offsets in i n t.l exe d addressing, 3-28-31.


Trace. 19-5 See also accumulator offset addressing mode,
Transmi�sion errors, 12-8 accumulator offset indirect addressing mode
Transparent delay routine, 12-10 Varied length of instructions. 1-6, 2-11, 4-6
Traps, 15-7. See al.so software interrupt instructions Vector,"IS-2, 15-10
Trial subtraction in division. 8-9 6X09 I able, 15-10
Trivial cases, 5-12, 9-3, 9-11, 19-12, 19-24. Vectored interrupts, 15-2, 15-10
20-1' 20-3 Verilication terminal example
1 runcalion or labels, 2-4, 3-46 error handling, 16-12-13
TST. 22-74-75 \lowcharts, 17-5- I 0
interrupt clearing., 15-9, 15-22 inputs, 16-11
memory lesl, 5-l 0. 8-15 nwdularilation, 17-13-14
6800 version, difference from, 3-41 operator interactron, 16-12-13
slaws checking, 13-1 I. 13-14, 19-5 outputs, 16-11-12
TSX, 22-75 problem definition. 16-9-13
Two-byte operation codes, 3-10-11 processing requirements, 16-12
comparison instructions, 7-11, 22-29 st ructurcd program. 17-22-25
load instructions, 3-10-ll, 5-6, 6-\3, 10-J(i wp-down design. 17-29-31
long condiuonal branches, 5- l 0
WAI. 22-75. See also CWAI. SYNC instructions
min1111i1ing. USC, 2\-3
While-do structure, 17-16, 17-17, 17-19
prelix byte, 6-13
Word-length ( 16-hil) data. 3-46, 3-47. See also FDB
store instructions, I 0-16
t.lireclive
Two-dimensional arrays, X-7- 8
Write strobe from 6820 PIA, 13-7, 13-9, 13-26-29,
Two-pass assembler ,2-16
13-43
Twos complement, 4-16
Twos complcmcrll o'crllow. 5-12. See also ovcrtlow X register. See index register X
\lag.
Y regrsler. See index re gis t er Y
TXS. 22-75
Z (Zero) flag, 3-5
li register. See slack pointer ll
131T. effec t of, 13-31
LART. 1.1·52-53. See also 6551 /\CIA, 6850 ACIA
carry recognition, 8-15. 13-19
Unconditional branches, 5-14. See also BRA. JMP,
CM P, ellccl of, 4-5, 6-4. 19-12
LBKA tnstructions
definition, 3-5
Unsigned numbers, comparison or, 4-5-6,5-12
e4uality checkinkg, 4-5
Unsigned offsets rn addressing. See ABX instruction
L D. effect of. 5-I 0, 9-3
Until-do slrucwrc, 17-16-17
loop control. 5-5-6
User stack in subroutine lrnkages, 22-59
position in CCR, 3-3
User slack pointer. See stack pointer U
rounding, use in, 8-15
User's guide, 18-13
ST, ellcc1 of. 9-3
V (()vcrllow) tlag. 3-3, 3-5, 4-5. 5-12. . <iee also over­ Zero oiTsel indexed addressing mode. 3-21-22. See
Jlow \lag also constant offset indexed addressing mode
Validrty checks on ASCII characters, 7-8 Zero offsel, omission of, 3-19, 3-2 2

You might also like