6502 Technical Reference
6502 Technical Reference
for
6502 Assembler
Contents
i
Chapter 1-5 2500AD 6502 Assembler/Linker Quick Reference
1-5-1 Assembler 54
1.1 Prompt Mode 54
1.2 Command Line Mode 56
1.3 Filename Extension 56
1.4 Assembly Language Syntax 56
1.5 Assembler Directives 59
1-5-2 Linker 64
2.1 Prompt Mode 64
2.2 Command Line Mode 65
2.3 Data File Mode 65
ii
Chapter 2-4 RICE65 Basics
2-4-1 The RICE65 Program Files 83
2-4-2 The Application 83
2-4-3 Oscillator Source 83
2-4-4 Program Execution 84
2-4-5 Breakpoints 85
2-4-6 Real-time Tracing 86
2-4-7 RICE65 Debugging Environment 87
iii
2-7-8 ASM Single Step 101
2-7-9 Step over Call 101
2-7-10 Return to Caller 101
2-7-11 Animate 101
2-7-12 Animate Speed… 102
iv
Chapter 2-12 Options Menu
2-12-1 Display Option 115
v
2-12-2 Trace Option… 115
2-12-3 Set Memory Range 116
2-12-4 Fill Memory Range 117
2-12-5 Save Setup 117
2-12-6 Restore Setup 118
vi
Manual for 6502 Assembler
Fig. 1-1-1 shows a register structures diagram of the 6502 microprocessor. There are 6 main
registers: a 16-bit program counter (PC), an 8-bit accumulator (A or AC), two 8-bit index registers (X
and Y), an 8-bit stack pointer register (S or SP), and an 8-bit status register (P).
7 A 0 Accumulator
7 Y 0 Index Register Y
7 X 0 Index Register X
15 0 0 0 0 0 0 01 8 7 S 0 Stack Pointer
7 0
N V 1 B D I Z C Processor Status Register
Carry
Zero
IRQ Disable
Decimal Mode
BRK Command
Overflow
Negative
Fig. 1-1-1 Register structures of the 6502 microprocessor
Ver.98-01 1
Low-level Tooling System
Three 8-bit registers of the six main registers, which are the accumulator and the X, Y registers,
can be used to save temporary data values, to communicate with memory, to maintain counters, or for a
variety of other applications. The three registers are called general-purpose registers.
The accumulator is the only register in which arithmetic and logical operations can be performed,
and it holds one of the operands for each add, subtract, AND, OR, and Exclusive-OR instruction. The
6502 also has instructions to logically shift the contents of the accumulator to the right or to the left.
The X and Y registers are primarily employed as index registers to access sequential values in
memory, but the fact that they can be incremented and decremented under program control also makes
them popular as general purpose counters.
Status Register
The processor status register (P), see Fig. 1-1-2, contains seven usable bits. Five of these bits are
“status flags”; they provide information on the result of a previously executed instruction (in most
cases, the preceding instruction). The two other bits are “control bits”.
7 0
Carry 1=True
Zero 1=Result Zero
IRQ Disable 1=Disable
Decimal Mode 1=True
BRK Command 1=Break
Overflow 1=True
Negative 1=Negative
Carry flag (C) is used to save any carry produced by an add operation, any borrow produced
by a subtract operation, or the value of a bit after a shift operation. The carry
also reflects the result of a compare operation.
Zero flag (Z) represents whether or not the result of an operation is zero.
Break flag (B) indicates whether an interrupt request to the 6502 was caused by a “break”
instruction or by an externally generated interrupt.
Overflow flag (V) is applicable only to arithmetic operations on signed numbers. It is set if the
addition of two like-signed numbers or the subtraction of two unlike-signed
numbers produces a result greater than +12710 or less than -12810.
Negative flag (N) represents whether or not the result of a signed arithmetic operation produced a
negative result. This bit is also used as a general-purpose indicator of the state
of the most-significant bit position in the accumulator.
Ver.98-01 2
Manual for 6502 Assembler
The 6502 has several instructions that can be used to check the condition, or state, of each of these
flags. According to the results of these checks, the 6502 can decide whether or not to execute one of two
possible sequences of instructions. All flags remain set or cleared after these “check” operations are
performed. Therefore, not all 6502 instructions affect the flags.
About the control bits - the IRQ Disable bit (I) and the Decimal Mode bit (D):
IRQ Disable bit (I) is used to “lock out” external interrupts to the 6502 at times when, for some
reason, the microprocessor is not prepared to serve an interrupt. The 6502
automatically disables interrupts while it is being reset or when it is serving a
previous interrupt. Programs can also disable interrupts during periods when a
certain sequence of instructions must be executed uninterrupted.
Decimal Mode bit (D) controls whether the internal ALU of the 6502 is to operate as a straight binary
adder or as a decimal adder. In binary mode, the ALU treats arithmetic
operands as 8-bit binary numbers. In decimal mode, the ALU treats arithmetic
operands as two BCD (Binary-Coded Decimal) digits packed into one 8-bit
byte. If the Decimal Mode bit set to “1” then the ALU operates in BCD type,
and the results will be equivalent to them got from normal decimal system.
The 6502 microprocessor can be programmed so that at some point in a program, program
execution can be transferred to another sequence of instructions that is stored in another part of
memory. Before this transfer actually occurs, the 6502 saves the address of the next instruction in its
current sequence of instructions. And, after the new sequence of instructions has been executed, the
program control would be returned to the point that is just after the instruction that caused transfer
operation. The return address is saved in an area of memory called a stack.
The stack is also a portion of memory that is designated to accept these return addresses. However,
the stack must be implemented in Page 1 of the 6502 address space – the addresses from 0100 to 01FF
(hexadecimals). Since this design restriction and the address register for the stack (the Stack Pointer) is
only 8 bits wide that ensures the high-order two digits of the address are always 01.
Data are entered onto, and extracted from, the stack of the 6502, in memory, the same way that we
stack papers on the desk. The last item to be placed on the stack is also the first item to be removed
from it. This type of stack is usually referred to as “last in, first out”. As return addresses are entered
onto the stack, they are really stored in R/W memory at lower and lower memory addresses; the stack
“builds” toward address 0. The Stack Pointer, therefore, is automatically decremented by 1 as each new
address byte is pushed onto the stack, and is automatically incremented by 1 as each address byte is
pulled off of the stack. The A and P registers can also be saved on the stack, if desired.
Program Counter
The last (sixth) register described is the program counter that is a 16-bit counter that determines
which memory location will be accessed next. It is automatically incremented after each memory access
so that it addresses the next consecutive memory location. Since the program counter is 16 bits wide, it
can address any location in the 64K-byte address space of the 6502.
Ver.98-01 3
Low-level Tooling System
The 6502 has three separate signals, RES , IRQ , and NMI , by which external devices can cause an
executing program to be interrupted.
c Reset ( RES ) is used to initialize the 6502 to a known state, or to start the 6502 when power is
first applied to the system. While RES is active, the 6502 can neither transmit nor receive
information. When RES goes high level, the microprocessor loads the program counter with the
contents of memory locations FFFC and FFFD (hexadecimal), the address from which the first (or
initial) instruction will be fetched.
d Interrupt ReQuest ( IRQ ) is an input signal by which most peripheral devices request service
from the 6502. Here, “request” is the keyword here. Unlike the Reset signal, which interrupts the
6502 unconditionally IRQ simply informs the microprocessor that some peripheral device in the
system is waiting to send or receive information. An interrupt request will be acknowledged only if
the Interrupt Disable bit (I) of the processor status register is reset to a logic zero. If “I” is reset,
the 6502 will load the contents of the two uppermost memory locations, FFFE and FFFF
(hexadecimal), into the program counter. If “I” is set when the interrupt request is received, the
microprocessor ignores the request, and continues executing as if no request has been made. The
6502 does not “remember” the request, but when the “I” bit is reset, the 6502 is interrupted.
e Non-Maskable Interrupt ( NMI ) is an interrupt that cannot be disabled. The IRQ input signal is
maskable; that is, it can be enabled or disabled, depending on the state of the “I” bit in the
processor status register. Non-maskable interrupt, NMI , does not merely request to interrupt the
microprocessor, like RES , it does interrupt the microprocessor each time it is activated. The NMI
line is designed to interrupt the 6502 under some condition that requires immediate attention, such
as a power failure. The address of the sequence of instructions that serve the NMI interrupt is
stored in two consecutive memory locations, FFFA and FFFB (hexadecimal). Fig.1-1-3 shows the
Reset and Interrupt vectors locations of the 6502.
Address Contents
: »
: »
: »
NMI - L
FFFA
NMI - H
FFFB
RES - L
FFFC
RES - H
FFFD
FFFE IRQ - L
FFFF IRQ - H
Ver.98-01 4
Manual for 6502 Assembler
All programs in this Part are given in the assembler format. This format divides each line in the
program (i.e., each line of program code) into four fields: label, op code, operand and comment.
c Label field is used to mark a symbolic name or label to the location of an instruction, so that it can
be referenced by other instructions in the program. The label field is an optional field; In fact, most
instructions will not be labeled. However, if an instruction is labeled, it should follow the
n o
restrictions: The label must begin in the leftmost column of the line (column 1); The label must
p
begin with an alphabetic character (A through Z); The label must be no longer than six
q
characters; And the labels must be different. For example, the instruction JUMP KEYIN3 will
cause the program counter to be unconditionally loaded with the memory address that has been
assigned the label KEYIN3. The instruction at label KEYIN3 will be the next instruction to be
executed after the JUMP (JMP) instruction is executed.
d Op code field is mandatory for every line in the program that contains an instruction, and must
contain one of the 56 valid mnemonics of the 6502 (see 1-2-2). The op code may begin in any
column except column 1, and must be separated from a label (if present) by at least one space.
e Operand field is used to specify data or an address for instructions that require an operand. The
operand must be separated from the op code by at least one space. The assembler will accept
operands in any of five forms. Applying an appropriate prefix character to the operand, as
followings to specify the five forms:
f Comment field is always optional, and is used to add an explanatory note to a statement. The
contents of the comment field are not executed, so you can write what kind of comment you want.
However, the text of the comment should be preceded by a semicolon (;). Comments may be used
alone, too, without being appended to a line that contains an instruction.
Ver.98-01 5
LSD
MSD
MSD
Ver.98-01
0 1 2 3 4 5 6 7 8 9 A B C D E F
7, 1
BRK ORA ind,X ORA zpg ASL zpg PHP ORA imm ASL A ORA abs ASL abs
0 7, 1 6, 2 3, 2 5, 2 3, 1 2, 2 2, 1 4, 3 6, 3
0
BRK imm
Low-level Tooling System
BPL rel ORA ind,Y ORA zpg,X ASL zpg,X CLC ORA abs,Y ORA abs,X ASL abs,X
1 2, 2 ♠ 5, 2 á 4, 2 6, 2 2, 1 4, 3 á 4, 3 6, 3
á 1
JSR abs AND ind,X BIT zpg AND zpg ROL zpg PLP AND imm ROL A BIT abs AND abs ROL abs
2 6, 3 6, 2 3, 2 3, 2 5, 2 4, 1 2, 2 2, 1 4, 3 4, 3 6, 3
2
BMI rel AND ind,Y AND zpg,X ROL zpg,X SEC AND abs,Y AND abs,X ROL abs,X
3 2, 2 ♠ 5, 2 á 4, 2 6, 2 2, 1 4, 3 á 4, 3 6, 3
á 3
RTI EOR ind,X EOR zpg LSR zpg PHA EOR imm LSR A JMP abs EOR abs LSR abs
4 6, 1 6, 2 3, 2 5, 2 3, 1 2, 2 2, 1 3, 3 4, 3 6, 3
4
7, 1 = Cycles, bytes
BVC rel EOR ind,Y EOR zpg,X LSR zpg,X CLI EOR abs,Y EOR abs,X LSR abs,X
5 2, 2 ♠ 5, 2 á 4, 2 6, 2 2, 1 4, 3 á 4, 3 6, 3
á 5
6
RTS ADC ind,X ADC zpg ROR zpg PLA ADC imm ROR A JMP ind ADC abs ROR abs
1-2-2 Instructions Op Code Matrix
6 6, 1 6, 2 3, 2 % 5, 2 4, 1 2, 2 % 2, 1 6, 3 4, 3 % 6, 3
6
4, 3
D 2, 2 ♠ 5, 2 á 4, 2 6, 2 2, 1 4, 3 á 6, 3
á
CPX imm SBC ind,X CPX zpg SBC zpg INC zpg INX SBC imm NOP CPX abs SBC abs INC abs
E
0 1 2 3 4 5 6 7 8 9 A B C D E F
Manual for 6502 Assembler
Moving data into and out of memory is the most basic operations of the 6502, due to a memory-
oriented architecture. All such transfers are made via three registers – the Accumulator (A) register, the
X register and the Y register. We call the process of transferring data from memory into one of the
registers as “load data”. There are three Load instructions:
Instruction Description
LDA Load Accumulator with memory
LDX Load X register with memory
LDY Load Y register with memory
There are two flags of the processor status register will be changed to provide some information about
the value that has been loaded into the register, but the source location in memory is unaffected during
the load operation. If the most significant bit (bit 7) of the loaded data is an 1 then the “negative flag
(N)” of the processor status register will be set, and will be reset if bit 7 of the loaded value is a 0.
Furthermore, the “zero flag (Z)” will be set if the loaded value is 0; otherwise it will be reset. Example:
LDA $12C3
It will load the contents of memory location $12C3 into the accumulator. If the contents of memory
location $12C3 is $33 then the contents of accumulator will be $33 after the instruction executed.
The process of transferring data from one of the registers of the 6502 into memory is called “store
data”. There are three Store instructions:
Ver.98-01 7
Low-level Tooling System
Instruction Description
STA Store Accumulator in Memory
STX Store X Register in Memory
STY Store Y Register in Memory
The store instructions do not change the contents of the source registers (A, X, Y) and the
processor status register. How can we do about storing a value in memory? Combining a “load
immediate” and “store” instructions is the simplest way to store a value in memory, like:
LDA #33
STA $71
Which stores #33 in zero page memory location $0071.
There are several instructions for adding and subtracting both binary-coded and binary-coded-
decimal numbers in the 6502 microprocessor. All that instructions involve two operands, one in the
accumulator and the other in memory or direct second byte value of the instruction (if immediate
addressing mode is used) – refer to 1-2-12 “6502 Addressing Modes”.
Representation of Numbers
The 6502 can add or subtract both unsigned and signed numbers. Actually, the forms make no
difference to the microprocessor, but programmer should know how to interpret both forms.
In an unsigned number, each data bit carries a certain binary weight, according to its position
within the number. Data bits are numbered from right to left, an 8-bit data with the rightmost bit labeled
as b0 and the leftmost bit labeled as b7. The bit binary weight is correlative to the bit position that b0 has
a weight of 20 (decimal 1), b1 has a weight of 21 (decimal 2), and b7 has a weight of 27 (decimal 128)
etc. Therefore, one byte can represent an unsigned number from decimal 0 (00000000) to decimal 255
(11111111). Æ(128 + 64 + 32 + 16 + 8 + 4 + 2 + 1=255)
Ver.98-01 8
Manual for 6502 Assembler
In a signed number, the seven low-order bits (bit 0~6) represent data, and have the same weights
as with unsigned numbers. The most significant bit (bit7) indicates the sign of the number. If the
number is positive then the bit7 is logic 0; otherwise bit7 is logic 1. The range of the positive signed
numbers is within decimal 0 (00000000) to decimal +127 (01111111). And, the negative signed
numbers may be within the range of decimal –1 (11111111) to decimal –128 (10000000).
b7 b6 b5 b4 b3 b2 b1 b0 bit position
1 0 1 0 0 1 1 0 data
27 26 25 24 23 22 21 20 binary weight
1*128 + 0*64 + 1*32 + 0*16 + 0*8 + 1*4 + 1*2 + 0*1 = 166 equivalent decimal values(unsigned)
1( - ) 0*64 + 1*32 + 0*16 + 0*8 + 1*4 + 1*2 + 0*1 = -38 equivalent decimal values(signed)
Someone might be bewildered and wonder why –1 is represented by binary 1111111, rather than
by 10000001? Because we use “two’s complement” form to represent their negative-signed numbers.
And, why “two’s complement”? The two’s complement form was introduced to eliminate the problems
that zero represented in two forms, 00000000 (the positive form) and 10000000 (negative form). In
two’s complement, zero is represented by only one form 00000000. To derive the negative two’s
complement form of a binary number; you just take the positive form of the number and reverse the
sense of each bit. You change each 1 to a 0 and change each 0 to an 1, and add 1 to the result. The
following example shows the steps required in deriving the binary representation of –16 (in two’s
complement form).
00010000 +1610
11101111 “one’s complement”
+ 1 add 1
Some instructions of the 6502 can cause ALU to operate as a binary adder or as a decimal adder
during addition and subtraction. As operating as a binary adder, the ALU treats both 8-bit operands as
binary numbers, with values from 00000000 to 11111111. When operating as a decimal adder, the
ALU treats both operands as Binary-Coded Decimal (BCD) numbers, with two 4-bit BCD digits
packed into each 8-bit operand.
We can use two instructions to choose the binary or decimal modes of the ALU. The two
instructions are “SED” (Set Decimal Mode) and “CLD” (Clear Decimal Mode).
Ver.98-01 9
Low-level Tooling System
The SED forces the ALU perform as a decimal (BCD) adder, and it will also set the Decimal Mode
(D) control bit of the processor status register. The CLD instruction causes the ALU to perform as a
binary adder, and clear the Decimal Mode bit (D) in the processor status register. The Decimal Mode
bit (D) is undefined when power is applied; it must be either set or cleared by the initialization program.
Addition
Ver.98-01 10
Manual for 6502 Assembler
Sometimes, you don’t need proceed an ADC instruction with a CLC instruction. If an immediate
value is being added to the accumulator and you know the Carry flag has been set by some previous
operation then you can use an immediate value, which is one less than the value you want to add, rather
than using a CLC instruction before ADC instruction. For instance, to add 33 to the accumulator and
the Carry is set to one, you can only code:
ADC #32
The result will be same with coding CLC followed by ADC #33. In fact, it’s not a good idea to do so.
Except absolute addressing (indexed or un-indexed, three bytes), refer to 1-2-12, the all ADC
instructions are two bytes long. The ADC instructions will affect the following four flags in processor
status register:
c Carry flag (C). If the sum of a binary addition exceeds decimal 255 (hex. FF) or if the sum of a
binary-coded decimal addition exceeds decimal 99, then the Carry will be set to logic 1; otherwise
it is reset.
d Zero flag (Z). It will be set if the sum is zero; otherwise, it is reset.
e Negative flag (N). When this flag used as a general-purpose state indicator of the most-significant
bit of the accumulator, the flag will be set if the bit7 of the result is a logic 1; otherwise it is reset.
During the signed numbers are being added the N flag will be set if the result is negative and reset
if it is positive.
f Overflow flag (V). This flag is applicable only for signed numbers arithmetic operation. If both
positive or both negative numbers are added and the result exceeds +12710 or –12810, which causes
bit7 of the accumulator to be changed, then the V flag will be set; otherwise it is reset.
For add operation, the N and V flags are relevant only if signed numbers are being added. To add
multi-byte numbers, simply clear the Carry flag before adding the low-order bytes, and then execute a
series of LDA (load) / ADC (add) / STA (store) instructions, once for each byte to be added. For
example, a double-precision addition routine
This routine adds two 16-bit numbers. One number is stored in locations
$30 and $31, the other is stored in locations $32 and $33.
The sum replaces the number in locations $30 and $31.
DPADD CLC CARRY = 0
LDA $30 Add low-order bytes
ADC $32
STA $30
LDA $31 Add high-order bytes
ADC $33
STA $31
Ver.98-01 11
Low-level Tooling System
Subtraction
Ver.98-01 12
Manual for 6502 Assembler
f Overflow flag (V). This flag is applicable only for signed numbers arithmetic operation. If two
unlike-signed numbers (one positive and the other is negative) are subtracted and the result exceeds
+12710 or –12810, which causes bit7 of the accumulator to be changed, then the V flag will be set;
otherwise it is reset.
Like addition operation routine, to subtract multi-byte numbers, you just set the Carry flag before
subtracting the low-order bytes, and then execute a series of LDA (load) / ADC (add) / STA (store)
instructions, once for each byte to be subtracted. For example, a double-precision addition routine:
SEC Carry = 1
LDA #00 Accumulator = 0
SBC $31 Subtract $0031
STA $31 and re-store in memory $0031
Signed Number Arithmetic
Actually, the operation of addition and subtraction makes no difference whether the numbers are
signed or unsigned. However, that doesn’t mean every addition and subtraction routine, mentioned
above, can be used with numbers from both signed and unsigned systems. That only means the
mechanics portions of the addition and subtraction of these routines are universal. The signed arithmetic
routine may include some additional instructions that will treat a negative result differently from a
positive result, such as an overflow conditional operation (i.e., the sign bit is altered) may be treated
differently from one in which no overflow occurs.
Except as a general-purpose state indicator of the most-significant bit of the accumulator for N
flag, the N and V flags are applicable only for signed numbers arithmetic operation, that is they are
meaningless for un-signed numbers arithmetic operation.
Ver.98-01 13
Low-level Tooling System
In signed numbers arithmetic routine, the final status of the two flags usually used to decide how to
process the result. The N flag only reflects the result is positive or negative, but the V flag presents
whether the contents of the accumulator is valid or not.
If the V flag is set, the contents of the accumulator are invalid. The V flag will be set if the addition
of two like-signed numbers or the subtraction of two unlike-signed numbers, which will produce a result
more positive than +12710 or more negative than –12810; otherwise, the V flag is reset. Once set, the
overflow flag can be reset with a special one-byte instruction – CLV (Clear Overflow(V) flag). The
overflow flag will be reset automatically at the beginning of the next ADC or SBC instruction.
There are several instructions that can increment and decrement the contents of the X, Y
registers, or memory location in the 6502.
Ver.98-01 14
Manual for 6502 Assembler
The example below shows a routine that copies the contents of eight consecutive bytes in memory
into another portion of the memory. In this example, the X register functions as an index register and Y
register acts as the byte counter. The last instruction – BNE, has not been described yet, but all it does
is make the 6502 loop back and load another byte (via the LDA $30,X instruction at label NXTBYT)
until the byte counter – Y register has been decreased to zero.
This routine copies an eight-byte block of memory, starting at location
$0030, into another part of memory, starting at location $0300
LDX #00 Index = 0
LDY #08 Byte counter = 8
NXTBYT LDA $30 X Load next byte
STA $0300 X Store next byte
INX Increment index
DEY Decrement index
BEN NXTBYT Loop until all bytes copied
In some cases, counters are maintained in memory rather than in X or Y registers. There are two
instructions allow you to perform increment or decrement operation on memory without using ADC or
SBC. They are:
Instruction Description
DEC DECrement memory by 1
INC INCrement memory by 1
The two instructions above permit four addressing modes – absolute, zero page, absolute indexed X,
and zero page indexed X (refer to 1-2-12). These instructions affect the same flags in the processor
status register – Negative (N) and Zero (Z), as the register increment and decrement instructions.
Unlike the arithmetic instructions – ADC and SBC, the INC and DEC instructions do not affect the
Carry flag. So, If you are using a multi-byte memory counter to increment, you must check the Z flag
(rather than the C flag) to decide whether or not to increment the next higher byte; if Z is set (indicates
the current byte’s value is zero and generates a carry), then increment. Similarly, if a multi-byte counter
must be decremented, you must check the N flag to decide whether or not to decrement the next higher
byte; if the DEC instruction caused N to switch from 0 to 1 (indicates a borrow happened), decrement.
Ver.98-01 15
Low-level Tooling System
Sometimes you will want to check just one or more bits in a memory location or register, rather
than entire 8-bit byte. In this case the logic instructions of the 6502 are useful for programmer.
There are three logic instructions, which operate on the accumulator with the contents of a memory
location or immediate value specified in the operand.
Instruction Description
AND AND memory with accumulator
EOR Exclusive-OR memory with accumulator
ORA OR memory with Accumulator
All instructions occupy two bytes in memory if a zero page or immediate addressing mode is used, and
three bytes in memory if an absolute addressing mode is used. All three instructions affect two flags:
Ver.98-01 16
Manual for 6502 Assembler
c The Zero flag. It will be set if the result is zero; otherwise, it is reset.
d The Negative flag. It will be set if the bit7 = 1 of the result; otherwise, it is reset.
AND Instruction
AND instruction is used to filter, mask, or strip out (clear to zero) certain bits in the accumulator,
so that some form of processing can be performed on the remaining bits. If each bit in which both
memory and accumulator are in logic 1 then the bit in the accumulator is set to 1 after the instruction;
otherwise that bit is reset to 0. Table 1-2-1 summarize the AND result:
The AND instruction is useful for testing the accumulator bits selected for a 1 value (to check
a status byte, perhaps, to find out which bits are “on”), or to mask out bits that are no interest in a
particular program application. The ASCII characters 0 to 9 are assigned the value listed in Table 1-2-2
(assume the most-significant bit is always a logic 0). If the four most-significant bits are masked out of
the ASCII codes so that they are reset to zero, the remained four least significant bits are same with the
BCD value. For example,
ASCII code of 510 0 0 1 1 0 1 0 12
mask the four most-significant bits to zero
BCD code of 510 0 0 0 0 0 1 0 12
It will be very easy to mask the four most-significant bits to logic 0 by using logic AND instruction.
ASCII
Character BCD
Hexadecimal Binary
0 30 00110000 0000
1 31 00110001 0001
2 32 00110010 0010
3 33 00110011 0011
4 34 00110100 0100
5 35 00110101 0101
6 36 00110110 0110
7 37 00110111 0111
8 38 00111000 1000
9 39 00111001 1001
Ver.98-01 17
Low-level Tooling System
For example, you store the ASCII code of 510 in accumulator and ANDing the value with 000011112,
and then you will get the result you want.
LDA #$35
AND #$0F
The accumulator will contain 00000101, or BCD 5.
OR Instruction
The ORA (OR Memory with Accumulator) instruction produces a logic 1 result in each bit of
accumulator for corresponded bit of memory or accumulator contains a logic 1. The ORA instruction is
usually used to set some bits of the accumulator to a logic 1, for example:
ORA #01
It will set the least-significant bit of the accumulator to a logic 1, and leave all other bits unchanged.
EOR Instruction
The EOR (Exclusive-OR Memory with Accumulator) instruction is used to determine which bits
differ between two operands, and it can also be used to complement selected accumulator bits. The
EOR instruction produces a logic 1 result in each bit of accumulator for corresponded bit of memory or
accumulator (but not both) contains a logic 1; otherwise all other bit positions are cleared to 0. For
example,
EOR #$0F
The instruction will complement the four least-significant bits of the accumulator and the four most-
significant bits leave unchanged. The EOR is also used to determine whether two values are identical or
not, EOR will set the Zero flag (Z) if, and only if, the contents of memory are identical to the contents
of the accumulator. Table 1-2-4 summarizes the EOR conditions:
Ver.98-01 18
Manual for 6502 Assembler
Most of the program examples with instructions were executed in the order in which they appeared
in program. Control has not been transferred to another section of a program based on the results
received by executing an instruction or a series of instructions. Now, we will discuss how program
execution can be transferred from one section of a program to another section, and why this is useful.
Have you ever-read magazines and come across a direction, like “Jump to page 10”? That is also a
jump instruction.
The jump instructions of the 6502 cause the next operation to happen at a point rather than the
next consecutive memory location. And the jump instruction of the 6502 is unconditional; it occurs
every time the 6502 encounters it in a program.
The operand of a jump (JMP) instruction is usually a label, so you will often see JMP instruction
like:
:
:
ADC $30
INX
JMP THERE
HERE STA $33
:
:
THERE SEC
SBC $32
:
The program will jump to the instruction labeled THERE in the example, and it executes SEC,
SBC $32…and so on. Will the STA $33 instruction located label HERE ever be executed? Yes, but
only if an instruction in some portion of the program transfers control to that location.
The JMP instruction is used to skip over a group of instructions that are executed under some
conditions, or a group of instructions that are executed during some other part of the program. The JMP
instruction can operate with absolute addressing or indirect absolute addressing (refer to 1-2-12). Since
both modes are absolute, the jump can be to any place in memory.
The JMP instruction occupies three bytes in memory and takes three cycles to execute with
absolute addressing and five cycles to execute with indirect absolute addressing. Furthermore, the JMP
instruction does not affect any flag in processor status register.
Ver.98-01 19
Low-level Tooling System
Like the JMP instruction, the branch instructions cause the program execution to be transferred to
a specific memory location. Whereas the JMP instruction transfers control to some absolute address in
memory, the branch instructions transfer control to a relative address in memory – transfer control to a
specified number of memory locations forward or backward from the next instruction after the branch
instruction. Another difference between the JMP instruction and branch instructions is that the branch
instructions are decision-making instruction or called as conditional jump. Each branch instructions
check the status of a single flag in the processor status register. If the state of the flag meets the
requirements specified by the branch instruction, then the instruction is executed; otherwise, execution
continues with the next consecutive instruction in the program. The branch instructions and flag they
check are summarized in Table 1-2-5.
You will find from Table 1-2-5, the branch instructions are executed based on the status of four
flags – Carry (C), Negative (N), Zero (Z), and Overflow (V).
As you know, the branch instruction transfers are taken relative to the branch instructions, so that
these instructions operate in only relative addressing mode. For this reason, the branch can just stretch
across to 127 bytes forward or 128 bytes backward, from the branch instruction. You can always
combine a JMP instruction with the branch instruction to branch anywhere in memory.
For example, here is how a program might execute a branch on the Carry-set condition to an
instruction (at CSET) that is more than 127 locations past, or 128 locations ahead of the BCC
instruction:
Ver.98-01 20
Manual for 6502 Assembler
Table 1-2-6 gives the hexadecimal equivalents for the full range of branch, both forward and
backward. If you have a SYSTEM that offers the mnemonic entry mode, you can ignore this table and
enter the absolute (16-bit) address itself, rather than the relative displacement; otherwise, here is how
you can use Table 1-2-6.
If you want code a Branch on Carry Clear (BCC) instruction that will branch 89 bytes forward if
the condition is met, you would look up 89 in the Forward Relative Branch Table. Position 89 is in
column 9 and row 5. The column gives the least-significant hexadecimal digit value and the row gives
the most-significant hexadecimal digit value, so the BCC instruction should be coded like:
BCC $59
All branch instructions occupy two bytes in memory. These instructions are executed in two cycles
if the condition is not met and three cycles if the condition is met (four cycles if the branch crosses a
page boundary).
Up to this point, the branch instructions check on the state of a status flag that reflects the result in
an arithmetically altered register.
Ver.98-01 21
Low-level Tooling System
Ver.98-01 22
Manual for 6502 Assembler
Example 1-2-1 contains a routine that checks whether the contents of two memory locations are
identical, and sets a flag in memory.
Example 1-2-2 contains another memory-to-memory comparison routine, and stores the greater value in
the higher order location in memory. Example 1-2-3 contains a register-to-constant comparison routine
in which two branch instructions are used with one compare instruction, so that the ”less than”, “equal
to”, and “greater than” conditions are checked.
Ver.98-01 23
Low-level Tooling System
STA $72
Accumulator equals to 7
JMP DONE
GT7 STA $73
Accumulator is greater than 7
DONE :
:
Example 1-2-4 is a routine that will move consecutive memory bytes (max. 256 bytes), with the
CPX instruction doing the “all bytes moved?” check each time a byte is moved.
c The Negative flag (N) receives the initial (un-ANDed) value of bit7 of the memory location being
checked.
d The Overflow flag (V) receives the initial (un-ANDed) value of bit6 of the memory location being
checked.
e The Zero flag (Z) is set if the AND operation generates a zero result; otherwise, it is reset.
The BIT instruction performs the same operation as the AND instruction, but it does not enter the
ANDed result in the accumulator. Furthermore, the AND instruction affects two flags – N and Z and
both flags reflect the post-ANDed status, the BIT instruction affects three flags – Z, N and V, but only
the Z flag reflects the post-ANDed status.
Ver.98-01 24
Manual for 6502 Assembler
The BIT instruction only used in absolute and zero page addressing. And, it’s worth to note that
only the Z flag reflects the result of the simulated AND operation; the N and V flags represent the
values of the two high-order memory bits in their unaltered state. For example, waiting for a memory bit
to become logic0:
In that example, If the “BNE LOOP” was “BEQ LOOP” then just check a logic 1 in b3. The BIT
instruction can check more than one bit at a time, but with some limitation. When two or more bits are
set in the accumulator mask, a subsequent BIT instruction will set Z flag only if both check bits are
logic 0 in memory; otherwise, will reset Z if either or both check bits are logic 1 in memory.
However, the limitation will disappear if only one bit of the check bits is in the b0 to b5 and the
other check bit(s) are either or both in b6 to b7. The bit6 and bit7 can be checked with their own branch
instructions (BVS and BVC for bit6, BMI and BPL for bit7) because b6 and b7 provide AND-
independent status indicator. For example, waiting for any of three memory bits to become logic 0.
It is useless if you are checking elements of tables or any other indexed or indirect-accessed data
because the BIT instruction is restricted to absolute and zero page addressing.
However, the BIT instruction can often replace a compare instruction for data at known addresses.
The easy access to bit6 and bit7 (via V and N flags) makes these bits ideal for storing status
information. And, the N and V may be widely used in interrupt request scheme of the input / output
structure of the 6502 system
Ver.98-01 25
Low-level Tooling System
Ver.98-01 26
Manual for 6502 Assembler
Carry 7 0
ASL: 0
7 0 Carry
LSR: 0
7 0
ROL:
Carry
ROR: 7 0
Carry
Fig. 1-2-1 Diagram of the SHIFT and ROTATE Instructions
Besides the Carry flag is affected, the shift and rotate instructions affect two other flags in the
processor status register:
c ASL, ROL, and ROR cause the Negative flag (N) to be set if bit7 of the shifted result is set to
logic 1; otherwise, it is reset. The LSR instruction always causes the Negative flag to be reset
because it shifts a “0” into bit7.
d The Zero flag (Z) will be set if the shifted result is “0”; otherwise, it is reset.
Single-byte numbers can be shifted using only the shift instruction, ASL or LSR. Multi-byte
numbers require a combination of these shift and rotation instructions. In multi-byte shift operation, the
Carry flag is used to propagate bit values that have been displaced out of previously shifted bytes.
For example, a 24 bits (three bytes) unsigned numbers stored in location $71 (low-order byte),
$72, and $73 (high-order byte) can be left-shifted with:
ASL $71 First shift low-order byte
ROL $72 Shift middle byte w/Carry flag
ROL $73 Shift high-order byte w/Carry flag
Multi-byte numbers right shifts operation in left-to-right order, where the high-order byte is shifted
first, with an LSR instruction.
Ver.98-01 27
Low-level Tooling System
The right-shift routine for three bytes numbers starting at location $71 is:
The four shift and rotate instructions perform as “logic” shifts without regard to sign. If a signed
number is right-shifted, the sign bit will be shifted 1 bit position to the right, and its value will be
replaced with a 0. If a signed number is left-shifted, the sign will be shifted into the Carry flag, and its
value will be replaced by bit6. Your program must restore the displaced sign value. Example:
In a logical right shift, the sign is vacated by the operation. You can preserve the sign by recording
its original value in the Carry flag and by using an ROR instruction to shift it into the most-significant
byte.
Ver.98-01 28
Manual for 6502 Assembler
Although the 6502 is a memory-oriented architecture, it also has 6 one-byte instructions that allow
you to copy the contents of one register into another without disturbing the source register.
Instruction Description
TAX Transfer Accumulator to index X
TAY Transfer Accumulator to index Y
TSX Transfer Stack pointer to index X
TXA Transfer index X to Accumulator
TXS Transfer index X to Stack pointer
TYA Transfer index Y to Accumulator
For X and Y registers, the 6502 just can increment or decrement them. The transfer instructions
provide a simple way to copy X and Y into the accumulator for a more complex arithmetic operation,
and have the result returned. Considering a case in which you want to access every tenth element in a
list rather than consecutive elements.
Ver.98-01 29
Low-level Tooling System
The access instruction would be an index instruction, such as LDA LIST, Y, in which LIST is a
label assigned to the starting location of the list. To access every tenth element, you must add 10 to the
index Y between load operations.
How can you add 10 to Y register? One way is to code ten consecutive INY instructions. A more
efficient way is to transfer Y to the accumulator, add 10 (immediate), and return the sum to Y for the
next list access.
The stack of the 6502 is of the “last-in-first-out” variety. That is, the last item (a data byte) that is
entered onto the stack is the first item to be extracted from the stack. This scheme causes data to be
retrieved in the reverse order from which it was stored.
A stack address register called the Stack Pointer (SP or S), which always points to the next free
memory location on the stack, used to access stack information. The Stack Pointer is automatically
decremented after a byte is pushed onto the stack, and is automatically incremented before a byte is
pulled from the stack, so the stack built in the direction of address 0.
The stack is implemented in page 1 (location $0100 ~ $01FF) of the address space. Thus, the
Stack Pointer must be initialized by the user’s program to address $01FF when the power is applied.
The stack can hold up to 256 bytes of information because a page comprised of 256 byte locations. The
purposes of using the stack: (1) to save interrupt or subroutine return addresses, and (2) to temporarily
save register content
The contents of SP are undefined when power is applied, and must be initialized by the user’s
program. You can use a special instruction – TXS to initialize the Stack Pointer.
Instruction Description
TXS Transfer index X to Stack-pointer
That is an one-byte instruction with two cycles execution.
Since the stack starts at memory location $01FF, most system programs initialize the Stack Pointer
to $FF (recall that the high-order address byte $01 is automatically supplied by the 6502). For example,
LDX #$FF
Load $FF into X register.
TXS
Transfer X register to Stack Pointer
A program, using another implied-addressing instruction, can also read the contents of the Stack
Pointer:
Instruction Description
TSX Transfer Stack-pointer to index X
That is also an one-byte instruction with two cycles execution.
This instruction is rarely used because you do not care where in the stack information is being
stored in the most cases.
Ver.98-01 30
Manual for 6502 Assembler
The 6502 microprocessor has four instructions that allow the contents of both the accumulator and
the processor status register to be stored in the stack.
Instruction Description
PHA PusH Accumulator on Stack
PHP PusH processor status on Stack
PLA PulL Accumulator from stack
PLP PulL Processor status from stack
All the four instructions are implied addressing instructions, which occupy only one byte in
memory. The PHA and PHP instructions work identically, except they push different registers onto
stack. In each case, the contents of the register are pushed onto the stack at the location being pointed to
by the Stack Pointer. Then, the Stack Pointer is decreased by one to the next lower address. Neither
instruction changes the contents of its source register.
Similarly, the PLA and PLP instructions increment the Stack Pointer to the next higher address,
and load the contents of the memory location, addressed by the Stack Pointer, into the appropriate
destination register.
Figure 1-2-2 shows the effect of the PHA instruction on the Stack. In Fig. 1-2-2 (A), the Stack
Pointer (S) is pointing to the top of the stack (location $01FF), and the accumulator contains $33. After
PHA is executed (Fig. 1-2-2 (B)), the Stack Pointer has been decremented to $FE and the contents of
the accumulator have been stored in location $01FF. After the PUSH, if you execute a PLA instruction,
the Stack Pointer will be incremented to point to $01FF and the accumulator will be loaded with the
contents of location $01FF.
Memory
Registers $AA $01FC
S $FF $XX $01FD
$YY $01FE
A $33 $ZZ $01FF
©A ª Before PHA
Memory
Registers $AA $01FC
S $FE $XX $01FD
$YY $01FE
A $33 $33 $01FF
(A ) After PHA
Ver.98-01 31
Low-level Tooling System
Why someone needs to save registers on the stack? The reason is to preserve their contents while
they are being manipulated by other programming operations. This is particularly true in subroutines.
It looks as if only the accumulator and the processor status register can be saved on the stack. That
is true based on the instruction functions, but by using the register transfer instructions, you can move
the X and Y registers into the accumulator, push them onto the stack, and later pull them off and restore
them with additional register transfer instructions. Example 1-2-7 shows the coding required saving not
only the accumulator and the processor status register, but also the X and Y registers on the stack. Note
that the registers are pulled in the reverse order from which they were pushed.
In most cases, the accumulator contents must always be pushed onto the stack before either X or Y
register is pushed because the X and Y pushes must be preceded by a TXA or TYA instruction, which
destroys the contents of the accumulator. Furthermore, if the processor status register is to be saved, it
must also be pushed onto the stack before either X or Y is pushed because both TXA and TYA affect
the processor status register’s Negative (N) and Zero (Z) flags.
Ver.98-01 32
Manual for 6502 Assembler
One reason for the wide popularity of the 6502 microprocessor is the flexibility it offers in
addressing. The 6502 has 13 addressing modes. We introduce the 13 addressing modes respectively, as
following:
Immediate Addressing
In immediate addressing, the operand resides in the second byte of the instruction. An immediate
operand is specified by placing a # prefix before the operand. For example,
LDA #$33
is an instruction that loads hexadecimal 33 (decimal 51) into the accumulator. All instructions that use
immediate addressing are two bytes long.
Absolute Addressing
Absolute addressing allows the direct addressing of any of the 65,536 memory locations in the
address space of the 6502. All instructions that use absolute addressing require three consecutive
memory locations for storage. The first byte is the op code of the instruction; the second and third bytes
are the low-order and high-order bytes of the operand address, respectively. For instance,
LDA $12C3
is an instruction that loads the contents of memory location $12C3 into the accumulator. If memory
location $12C3 contains hexadecimal 3C, the accumulator will contain hexadecimal 3C after the LDA
instruction is executed. The example instruction looks like these in memory:
Location Contents Description
nnnn $AD Op code for LDA with absolute addressing
nnnn+1 $C3 Low-order byte of address
nnnn+2 $12 High-order byte of address
As you can see, the instruction occupies three consecutive addresses. In other words, the instruction has
three bytes long. As an assembler rule, the absolute address doesn’t use any sign to mark usually.
Zero page addressing is a form of absolute addressing in which the 6502 accesses only the first 256
locations in memory. These are hexadecimal addresses 0000 through 00FF (decimal addresses 0
through 255). Because the high-order byte of a zero page address is always zero, instructions that use
zero page addressing are two-byte instructions; the first byte is the op code, the second byte is the low-
order byte of a zero page address (00 through FF). The 6502 microprocessor will treat a two-digit
operand as a zero page address. For example,
LDA $2A
Ver.98-01 33
Low-level Tooling System
This is a zero-page addressing mode, loading the contents of memory location 002A into the
accumulator. Except for two instructions, JMP (Jump) and JSR (Jump to Subroutine), all 6502
instructions that can use absolute addressing can also use zero page addressing. Considering the
inherent saving in both storage space and execution time, the zero page should be used, whenever
possible, to hold frequently accessed data. (“Zero page” instructions occupy one less byte in memory
and take one less cycle to execute than their “absolute address” counterparts.) The zero page is also
useful to store temporary data values.
Implied Addressing
The 6502 microprocessor has many instructions that don’t need any operand, such as setting or
clearing a bit in the processor status register, increasing or decreasing a register, or copying the contents
of one register into another. The 6502 receives enough information from the op code alone – and employ
what is called (appropriately) “implied addressing”. Some examples are:
Mnemonic Description
CLC CLear Carry flag.
DEX DEcrement the X register.
TAX Transfer Accumulator to X register.
All implied addressing instructions occupy one byte memory location.
Indirect absolute addressing is used by only one 6502 instruction – the Jump (JMP) instruction.
The JMP instruction loads the program counter with a new address at which the 6502 is to fetch its next
instruction. The JMP instruction can use either absolute addressing or indirect absolute addressing.
With absolute addressing, the operand of the JMP instruction is the destination address that is to be put
into the program counter. With indirect absolute addressing, the operand of the JMP instruction is the
address of the first of two memory locations that contain the 16-bit destination address. In other words,
the real 16 bits destination addresses are stored in memory, program should according to the operand of
the JMP to fetch them. It’ a rule that an indirect absolute operand is specified by enclosing it in
parentheses.
$0308 $AB
$0309 $02
$02AB
Program Counter
Fig. 1-2-3 Indirect absolute addressing
Ver.98-01 34
Manual for 6502 Assembler
For example,
JMP ($0308)
causes the program counter to be loaded with the low-order address contained in memory location
$0308 and the high-order address contained in memory location $0309. Fig. 1-2-3 illustrates this
example, with $02AB as the final (effective) address and with the instruction stored in memory location
$0110, $0111, and $0112.
If your destination is address $02AB, why not just use absolute addressing to store it in the
program counter? The answer is that indirect absolute addressing allows us to work with variable
destination addresses. For example, if the 6502 is installed in a system in which it must serve several
peripheral devices, an indirect absolute addressing JMP instruction can be used to access a sequence of
instructions appropriate to the peripheral that requires service.
We can prepare the series instructions for serving each peripheral device, and store them in various
locations of memory respectively. For each device, the series instructions are put together continually.
And then we choose the fixed consecutive two addresses, like $0308 and $0309, to store the begin
addresses of each device. Whenever we want to serve any peripheral device, we just execute the
instruction below:
JMP ($0308)
Because we can use other instructions to put the begin addresses of any device, which requires service,
into $0308 and $0309. In this case, the indirect absolute JMP instruction would always fetch the 16-bit
address from the same pair of memory locations, but the 6502 would change the contents of these
locations, depending on which peripheral device requires service. However, in absolute addressing
mode, the program just jumps to the unique address specified in operand.
In a data processing application, a single 6502 microprocessor might be accepting from operators
at several keyboards. In this case, the destination address that the 6502 is to jump to depend on which
keyboard the 6502 is accepting data from at any particular time. Input from keyboard No. 1 will be
stored in one place, input from keyboard No. 2 will be stored in another place, and so on. Indirect
absolute addressing also allows the effective address to be in RAM even when the program is in ROM
or PROM.
In absolute indexed addressing, the effective address of the operand is computed by adding the
contents of the X or Y register to the absolute address in the instruction. That is,
Effective address = Absolute address + X
or Effective address = Absolute address + Y
All absolute indexed instructions occupy three consecutive memory locations. The first location is for
operand, second and third locations are for absolute addresses – low-order byte is prior to the high-order
byte. The format of absolute indexed addressing is to attach a “X” or a “Y” to the address to specify
absolute indexed operands. For example,
LDA
$12C3 X
That is an absolute indexed LDA instruction. If the X register contains $05, the instruction loads the
contents of memory location $12C8 (i.e., $12C3 + $05) into the accumulator.
Ver.98-01 35
Low-level Tooling System
Absolute indexed addressing is especially useful for accessing data in a list. For this application,
you would use the starting address of the list as the operand of the instruction and use the index register
(X or Y) to store “displacement” - to specify the particular element in the list that you want to access.
For example, if the content of index register is $05 then you will access the 6th element in the list. If you
establish a loop in which X is incremented after each access, you can access a series of consecutive
elements in the list.
Zero page indexed addressing is to zero page addressing as absolute indexed addressing is to
absolute addressing. With zero page indexed addressing, the effective zero page address of the operand
is computed by adding the contents of the X or Y register to the zero page base address contained in the
second byte of the instruction. All zero page indexed instructions are two-byte instructions (one byte
less than their absolute-indexed counterparts). Attaching a “X” or a “Y” to the address specifies zero
page indexed operands. For example,
LDA $33 X
If the X register contains $05, the instruction loads the contents of location $0038 (i.e., $0033 + $05)
into the accumulator. Like absolute indexed addressing, zero page indexed addressing offers the
potential for list applications. By using zero page indexed addressing, the instruction requires only two
memory locations for storage, while absolute indexed addressing instructions require three memory
locations for storage.
One important point to stress that is the effective address is restricted to Page 0 (location 0 through
$FF). If the addition of the index register produces an address larger than $FF, the 6502 will disregard
any carry out of the low-order byte. In the preceding example, X is restricted to values of $CC (decimal
204) or less; X = $CC will produce an effective address of $FF, while X = $CD will produce a “wrap-
around” address of $00.
LDA($3E,X)
+ Êïåêóæäõ Âååóæôô
X $33
$0071 $C3
A $AA $0072 $12
Effective
Address = $12C3
DATA
$12C3 $AA
Ver.98-01 36
Manual for 6502 Assembler
If the X register contains $33, the instruction causes the 6502 to compute an address of $71 ($3E + 33)
and fetch the effective memory address from zero page location $71 (low address byte) and $72 (high
address byte). If memory location $71 contains $C3 and location $72 contains $12, the contents of
location $12C3 will be loaded into the accumulator. As you can see in Fig. 1-2-4.
Zero-page indirect indexed addressing combines the same two addressing modes as “zero-page
indexed indirect addressing”, but applies them in reverse order. We call the zero-page indexed indirect
addressing as “pre-indexing”, and zero-page indirect indexed addressing as “post-indexing”. Because in
zero-page indirect indexed addressing mode, the index is added to the 16-bit memory address after the
indirect addressing is performed.
Zero-page indirect indexed operands are of the form (aa), Y. For instance,
LDA
($3E) Y
If the Y register contains $33, the instruction fetch its base address from zero page locations $3E and
$3F. And, if location $3E contains $C3 and location $3F contains $12, the base address of the data
table is $12C3. The value of location $12F6 (i.e., $12C3 + $33) will be loaded into the accumulator.
Fig. 1-2-5 illustrates the example.
Zero-page indirect indexed addressing is used for accessing a certain known element in one of a
number of liked-structured data tables. For instance, this mode might be used in an instruction sequence
(like subroutine) that is shared by several users. Before using the zero-page indirect indexed instruction,
the users calling program stores a unique base address into the zero page operand location and the
consecutive location (like $3E/$3F in above example), so that the instruction can use the correct data
table.
Ver.98-01 37
Low-level Tooling System
A $AA
$12C3
Base Address
Relative Addressing
In relative addressing mode, the effective address is specified relative to the address of the next
instruction to be executed. That is, adding the current value of the program counter a positive or
negative displacement gets the effective address.
Adding a positive displacement will address a location following the current instruction (i.e., higher
in memory), and a negative displacement will address a location preceding the current instruction (lower
in memory). Relative addressing is used only by 8 branch instructions. Branch instruction makes
program control to transfer forward or backward if a certain condition is met; otherwise, execution
proceeds to the next sequential instruction. That is, we usually call them as “conditional jump
instructions”. For example, BCC NEXT
LDA #$33
The BCC instruction (Branch on Carry Clear) will cause CPU to branch to the instruction at label
“NEXT” if the carry bit is clear (reset). If the carry bit is set, the branch will not be performed and CPU
executes the LDA instruction.
All branch instructions occupy two bytes in memory, the first byte is op code and the second byte
contains the displacement. The displacement is limited to the range of +127 bytes (forward), to –128
(backward) from the branch instruction because the displacement is just 8 bits long.
Accumulator Addressing
The 6502 microprocessor has four instructions that allow shifting or rotating the contents of the
accumulator or a memory location one bit position to the right or to the left. If an “A” operand is
specified in these instructions, the CPU shifts or rotates the accumulator rather than the memory.
Accumulator addressing is an implied type of addressing and it occupies only one byte in memory.
ASL A
That’s an example of accumulator addressing. The instruction shifts the contents of accumulator to the
left by one bit position.
Ver.98-01 38
Manual for 6502 Assembler
The 13 addressing modes of the 6502 have been described completely. The Table 1-2-8
summarizes the addressing modes. In this table, “a” represents a hexadecimal address number.
Zero Page-zpg ÕThe second byte of the instruction is the zero page address.
Instruction: Op-Code zpg
+ zpg
Operand Address: Effective address
Õ
Zero Page Indirect Indexed-(zpg),y This addressing mode is often referred to as indirect, Y. The
second byte of the instruction is the zero page address and the contents of the zero page location are
added to the Y index register to form the effective address.
Instruction: Op-Code zpg
zpg
zpg
+ Y register
Operand Address: Effective address
Ver.98-01 39
Low-level Tooling System
Õ
Zero Page Indexed Indirect-(zpg,x) This addressing mode is often referred to as indirect, X. The
second byte of the instruction is the zero page address and is added to the X index register. The result
points to the 16-bit effective address.
Instruction: Op-Code zpg
zpg
+ X register
(address)
Operand Address: Effective address
Õ
Zero Page Indexed with X-zpg,x The second byte of the instruction is the zero page address and is
added to the X index register to form the 16-bit effective address.
Instruction: Op-Code zpg
zpg
+ X register
Operand Address: Effective address
g
Zero Page Indexed with Y-zpg,y The second byte of the instruction is the zero page address and is
added to the Y index register to form the 16-bit effective address.
Instruction: Op-Code zpg
zpg
+ Y register
Operand Address: Effective address
Õ
Absolute Indexed with X-a,x The 2nd and 3rd bytes of the instruction are added to the X register to
form the 16-bit effective address.
Instruction: Op-Code addrl addrh
addrh addrl
+ X register
Operand Address: Effective address
Õ
Absolute Indexed with Y-a,y The 2nd and 3rd bytes of the instruction are added to the Y register to
form the 16-bit effective address.
Instruction: Op-Code addrl addrh
addrh addrl
+ Y register
Operand Address: Effective address
Õ
Program Counter Relative-r This addressing mode, referred to as relative addressing, is used only
with the Branch instructions. If the condition being checked is met, the second byte (displacement) of
the instruction is added to the Program Counter, which has been updated to point to the Op Code of the
next instruction. The offset is a signed 8-bit quantity in the range from –128 to 127.
Õ
Indirect Absolute-(a) It’s used only by Jump instruction. The 2nd and 3rd bytes of the instruction form
an address pointer. The Program Counter is loaded with the first and second bytes at this pointer.
Instruction: Op-Code addrl addrh
Indirect Address: addrh addrl
Ver.98-01 40
Manual for 6502 Assembler
NOTES:(1) Page boundary, add 1 cycle if page boundary is crossed when forming address.
(2) Branch taken; add 1 cycle if branch is taken.
(3) Read-Modify-Write, add 2 cycles.
Ver.98-01 41
Table 1-2-10 6502 Instructions set summary
(Indirect), (Indirect), Zero-page, Absolute, Absolute, Zero-page,
Instructions Immediate Absolute Zero-page AC Implied Relative Indirect
X Y X X Y Y
Ver.98-01
Mne. Operation OP n # OP n # OP n # OP n # OP n # OP n # OP n # OP n # OP n # OP n # OP n # OP n # OP n # N V 1 B D I Z C Mne.
ADC A+M+C A
( 69 2 2 6D 4 3 65 3 2 61 6 2 71 5 2 75 4 2 7D 4 3 79 4 3 N V . . . . Z C ADC
AND A^M A
( 29 2 2 2D 4 3 25 3 2 21 6 2 31 5 2 35 4 2 3D 4 3 39 4 3 N . . . . . Z . AND
ASL C b 7 b0 0
' ' 0E 6 3 06 5 2 0A 2 1 16 6 2 1E 7 3 N . . . . . Z C ASL
BCC Jump if C=0 9D 2 2 . . . . . . . . BCC
BCS Jump if C=1 B0 2 2 . . . . . . . . BCS
CLI 0 (I 58 2 1 . . . . . 0 . . CLI
CLV 0 ( V B8 2 1 . 0 . . . . . . CLV
CMP A-M C9 2 2 CD 4 3 C5 3 2 C1 6 2 D1 5 2 D5 4 2 DD 4 3 D9 4 3 N . . . . . Z C CMP
CPX X-M EO 2 2 EC 4 3 E4 3 2 N . . . . . Z C CPX
CPY Y-M CO 2 2 CC 4 3 C4 3 2 N . . . . . Z C CPY
DEC M- 1 (M CE 6 3 C6 5 2 D6 6 2 DE 7 3 N . . . . . Z . DEC
DEX X -1 (X CA 2 1 N . . . . . Z . DEX
DEY Y -1 (Y 88 2 1 N . . . . . Z . DEY
EOR A (+) M (A 49 2 2 4D 4 3 45 3 2 41 6 2 51 5 2 55 4 2 5D 4 3 59 4 3 N . . . . . Z . EOR
INC M+1 ( A1 EE 6 3 E6 5 2 F6 6 2 FE 7 3 N . . . . . Z . INC
1-2-14 Summary of Instruction Set
INX X+ 1 (X E8 2 1 N . . . . . Z . INX
42
INY Y + 1 (Y C8 2 1 N . . . . . Z . INY
JMP Jump to location 4C 3 3 6C 5 3 . . . . . . . . JMP
JSR Jump to program 20 6 3 N . . . . . Z . JSR
LDA M ( A A9 2 2 AD 4 3 A5 3 2 A1 6 2 B1 5 2 B5 4 2 BD 4 3 B9 4 3 N . . . . . Z . LDA
LDX M ( X A2 2 2 AE 4 3 A6 3 2 BE 4 3 B6 4 2 N . . . . . Z . LDX
LDY M ( Y A0 2 2 AC 4 3 A4 3 2 B4 4 2 BC 4 3 N . . . . . Z . LDY
LSR 0 ( b7 b 0 C ( 4E 6 3 A6 5 2 4A 2 1 56 6 2 5E 7 3 0 . . . . . Z C LSR
NOP No operation EA 2 1 . . . . . . . . NOP
ORA AvM (A 09 2 2 0D 4 3 05 3 2 01 6 2 11 5 3 15 4 2 1D 4 3 19 4 3 N . . . . . Z . ORA
SEC 1 C
( 38 2 1 . . . . . . . 1 SEC
SED 1 D
( F8 2 1 . . . . 1 . . . SED
Õ
microprocessors will be reset when the system power is applied. Further, most microprocessors are
designed to allow the internal registers to be initialized at other times by an external signal RES
(Reset). We have just defined two separate conditions, reset at power-up time and restart at all other
times.
Interrupts and reset are functionally similar because they use vector pointers to determine the
memory address from which the next instruction will be fetched. The 6502 microprocessor uses
locations $FFFA through $FFFF to hold the whole vector pointers, and, they contain three sections g
c Locations $FFFA and $FFFB hold the vector pointers for the nonmaskable interrupt;
d Locations $FFFC and $FFFD hold the vector pointers for the reset, and
e Locations $FFFE and $FFFF hold the vector pointers for the maskable interrupt request.
1-3-1 Interrupts
Maskable interrupts ( IRQ ) are external signals which attempt to temporarily suspend the program
that is being executed by the microprocessor, and cause program control to be transferred to a
subroutine that is designed to serve that particular interrupt. Peripheral devices use interrupts to
“inform” the microprocessor that they have data to be input, or that they need data from the
microprocessor. This technique eliminates the need for the microprocessor to waste valuable execution
time polling the states of the peripheral devices of the system when none of the devices require servicing.
Non-maskable interrupts ( NMI ) are used to signal some condition that requires the immediate
attention of the microprocessor, such as a power failure. Peripheral devices request interrupt service
from the 6502 by activating the Interrupt Request ( IRQ ), and the critical situations (such as power
failure) force immediate service from the 6502 by activating the Non-maskable interrupts ( NMI ). The
“bar” over the IRQ and NMI signal names indicates that they are active low.
How can the 6502 “know” which peripheral devices in the system need service? Instinctively, you
can design the main program that can stop processing data and poll every device in the system in every
short period to check whether any device requires servicing. Obviously, this is very inefficient, and
processor will waste much time in polling. There is another way you can use; the 6502 has an
IRQ input that permits external devices to request servicing from the microprocessor. The
IRQ functions as the telephone bell and indicates to the 6502 microprocessor that some device in the
system is “calling”. Also, like a telephone bell, the IRQ can be ignored until the 6502 is prepared to
respond to it.
Ver.98-01 43
Low-level Tooling System
The IRQ Disable bit (I) in the processor status register determines whether or not the 6502 will
respond to an interrupt request on the IRQ line. The two instructions:
Instruction Description
SEI Set Interrupt Disable Bit
CLI Clear Interrupt Disable Bit
The SEI instruction sets the Interrupt Disable bit (I), which will cause the 6502 to ignore all
subsequent IRQ interrupt requests. The CLI instruction clears the Interrupt Disable bit (I), which will
cause an external interrupt request to be serviced as soon as it is sensed by the 6502. The 6502 initially
set the Interrupt request Disable bit (I) when power is applied.
Responding to an IRQ
If the IRQ Disable bit (I) is cleared and some external device activates the IRQ signal (pulls it low),
after the 6502 finishes executing the current instruction completely, then it will automatically initiate an
eight-cycle interrupt sequence. During this sequence, the 6502 pushes three bytes of “return”
information onto the stack (the high and low bytes of the program counter and the contents of the
processor status register). It then loads the contents of the dedicated IRQ vector low ($FFFE) and high
($FFFF) into the program counter. In the meantime, the 6502 also sets the IRQ Disable bit (I) to
temporarily “lock out” subsequent interrupt requests.
(A ) B e f o r e I R Q
S $C0
$AA $01C0
PC ($FFFF) ($FFFE) (P) $01C1
(PCL) $01C2
P nnnnn1nn (PCH) $01C3
©B ª After IRQ
Fig. 1-3-1 6502 responds to an IRQ
Ver.98-01 44
Manual for 6502 Assembler
Fig 1-3-1 summarizes how the 6502 responds to an IRQ, by showing both “before” and ‘after”
diagrams of the Stack Pointer (S), program counter (PC), the processor status register (P), and four
locations in the stack (here, assumed $01C0 to $01C3).
In the diagram of Fig. 1-3-1A, the Stack Pointer is pointing to the next free stack location
(assumed to be $01C3 for this example). The program counter contains the address of the next
instruction in the main program (high-address is PCH, low-address is PCL), and the “I” bit in the
processor status register is cleared to zero. In Fig. 1-3-1B, it is shown that following IRQ , the program
counter and processor status register are now on the stack, and the Stack Pointer is pointing to location
$01C0. Furthermore, the low-order and high-order bytes (PCL and PCH) of the program counter now
contain the contents of memory locations $FFFE and $FFFF, respectively, and the I bit has been set to a
1 in the processor status register. You can see that, the (I) bit of the processor status register is the only
one bit that was altered by this operation.
After responding to the IRQ , the program counter contains the starting address of a program
designed to serve IRQ-generated interrupts. This program is called an interrupt service routine (ISR).
The interrupt service routine must perform two functions:
c It must identify the device that generated the interrupt request (if there is more than one device in
system).
d It must perform the operation required by that device.
Generally, the ISR identifies that device by polling the status register of each device in the system,
to find out which device has its interrupt request bit set. Once the interrupting device is identified the
interrupt service routine (ISR) must fetch a new address - the starting address of a specified interrupt
routine for that interrupting device.
The 6502-compatible devices maintain their interrupt request bits in either bit 6 or 7 of a register,
so that the polling sequence can be performed with a series of BIT and branch instructions. Example 1-
3-1 shows a polling sequence for a system that contains four devices. Devices 1,2, and 4 can generate
only one interrupt request, and will indicate this request in bit7 of their respective status registers
(locations SDEV1, SDEV2, and SDEV4). Device 3 can generate two separate interrupt requests, and
indicate these requests in bits6 and 7 of its status register (location SDEV3). The interrupt status of
Devices 1, 2, and 3 in the system is queried with a BIT instruction, which loads the state of bit6 and 7
into the processor status register’s Overflow (V) and Negative (N) flag, respectively. For Devices 1
and 2, a BMI instruction determines whether or not the device has an active interrupt request. Device 3
requires two branch instructions (BMI and BVS) because this device is capable of generating either of
two separate interrupt requests. Device 4 requires no query, since it must have generated the interrupt
request if Device 1, 2, or 3 did not.
You should have noted that the polling sequence in Example 1-3-1 assigns priorities to the devices
in the system; Device 1 has the highest priority, Device 4 has the lowest priority. Although it seems that
the 6502 microprocessor needs a large amount of time to get to the Device 4 interrupt service routine,
due to a number of instructions that are executed before a Device 4 interrupt request can be serviced.
However, the polling takes only six cycles for Devices 1 and 2, and eight cycles for Device 3. Therefore,
the 6502 needs only 20 cycles (~ 5 usec) before it can service Device 4.
Ver.98-01 45
Low-level Tooling System
Instruction Description
RTI Return from Interrupt
This RTI instruction gets the processor status register and the program counter to be reinitialized
with their values before interrupt from the stack. Execution of the RTI instruction will automatically
(re-) enable IRQ interrupt requests, since the Interrupt Disable bit (I) of the processor status register
was clear when this register was pushed onto the stack.
The RTI instruction is quite similar to the RTS (ReTurn from Subroutine). Both instructions return
from a subroutine to the program from where the subroutine was called. For RTI, the call was made
automatically, by an externally generated interrupt requests.
For RTS, the call was made under software control by a JSR (Jump to SubRoutine) instruction.
The RTS and RTI instructions are implied-address instructions that occupy only one byte in memory
and require six cycles to be executed.
Ver.98-01 46
Manual for 6502 Assembler
The only difference between RTS and RTI is that RTS pulls two bytes of information from the
stack, whereas, RTI pulls three bytes of information from the stack (besides the low and high bytes of
the program counter, like RTS, also including the processor status register). In fact, if you had a
subroutine that needed to save the processor status register value before subroutine, you could use a
PHP (Push Processor Status on Stack) as the first instruction in the subroutine, and use an RTI, rather
than an RTS, as the return instruction for the subroutine.
The other interrupt of the 6502, Nonmaskable Interrupt ( NMI ), provides interrupts for high-
priority devices and events (such as a power failure) that cannot afford to wait during the time that the
interrupt requests are disabled. Unlike IRQ , NMI -generated interrupts cannot be masked out or
disabled; the 6502 will begin processing a NMI interrupt on completion of the currently executing
instruction.
NMI interrupt always has priority over IRQ interrupt that means if an interrupt request and a
nonmaskable interrupt occur simultaneously, the 6502 will process the nonmaskable interrupt. The
6502 performs an eight-cycle sequence for either type but, for the NMI , the vector pointer is fetched
from locations $FFFA (low-address byte) and $FFFB (high-address byte), rather than from locations
$FFFE and $FFFF (those for IRQ ). In fact, Fig. 1-3-1 also illustrates how the 6502 responds to NMI
as well, except that for the NMI , the post-interrupt value of the program counter would be ($FFFB)
and ($FFFA).
Since the NMI line is dedicated to serve high-priority events, it is important to know just how fast
the 6502 can be expected to respond to the interrupt. Let us find out by taking a “worst case”. The
worst case occurs if the NMI is activated just as the 6502 has fetched the op code of one of its longest
instructions – a seven-cycle instruction such as INC (Increment Memory) or DEC (Decrement Memory)
with absolute indexed addressing. The NMI interrupt will not be accepted until completion of this
instruction six cycles (6) later, at which time the 6502 will initiate an eight-cycle interrupt sequence. In
the eighth cycle of this sequence (8 – 1 = 7), the 6502 will fetch the op-code byte of the first instruction
in the interrupt service routine (ISR). This instruction can be either the input (LDA) or output (STA)
instruction that transfers data from or to the peripheral device, in which case, it will be executed in no
less than four cycles (4). Adding these execution cycle values (6 + 7 + 4 = 17), we see that with an
NMI interrupt, data can be transferred to or from a peripheral device in no more than 17 cycles (~ 4.25
usec).
1-3-4 Break
The Break (BRK) instruction is usually inserted at one or more points in a developed program
wherever you would like to halt the 6502 and check what your program has done to that point. When
BRK is executed, the 6502 sets the BRK Command flag (B) in the processor status register (P),
increments the program counter (PC) by one, and then pushes three bytes of information onto the stack
(the high and low bytes of PC and the contents of P register).
Ver.98-01 47
Low-level Tooling System
At this point, the 6502 loads the contents of the IRQ vector low ($FFFE) and high ($FFFF) into
the program counter.
Since the BRK instruction causes a vector to the same location as an IRQ -generated interrupt, the
IRQ interrupt service routine must include instructions that determine whether the routine is being
executed due to an external IRQ or due to a BRK instruction. The simplest way to make this
determination is to check the state of the BRK Command Bit (B) in the processor status register value
on the stack. If the B bit is a 1, the routine is being executed due to a BRK instruction; otherwise, the
routine is being executed due to IRQ .
Since BRK instructions are temporary instructions during software development, they must overlay
an existing instruction. BRK is a one-byte instruction, so it will just overlay the op code byte; if a multi-
byte instruction is overlaid with BRK, its operand byte(s) will remain intact. It will be no problem for
two-byte instruction because the program counter values on the stack (the return address) addresses the
second byte after the BRK instruction. If you want to overlay the op code of a three-byte instruction
with a BRK instruction, the interrupt service routine (ISR) will return to the third byte of the instruction
(the high-order byte of the operand), and the 6502 will attempt to execute the byte as an instruction op-
g
code. In this situation, you must code two temporary instructions into the program BRK to overlay
the op code and NOP instruction to overlay the third byte to prevent the 6502 from executing the third
byte as an instruction op-code.
1-3-5 Reset
The contents of the program counter determine the memory location from where the 6502 will fetch
the next instruction to be executed. How does the program counter receive its initial contents when
power is applied to the system? The signal that initializes the program counter and, thereby, initiates the
6502 operation, is an externally generated signal called RES (Reset). This signal is used to reset or
start the microprocessor from a power-down condition. Information can be neither written to nor read
from it, and the contents of the internal registers will be undefined when RES is held low (to ground),
the 6502 is in a disabled state.
After RES has reached to the high level, the 6502 will immediately initiate a six-cycle start
sequence. During this sequence, the 6502 sets the IRQ Disable bit (I) of the processor status register to
“lock out” external interrupts while the microprocessor is being initialized, and loads the contents of
memory locations $FFFC and $FFFD into the low-order and high-order bytes, respectively, of the
program counter. These two locations, $FFFC and $FFFD, must contain the address of the first
instruction to be executed by the 6502. This is the starting address of an initialization program. (Since
the contents of these locations must be preserved while the power is off, they must reside in ROM. In
fact, the initialization programs that these locations address must also reside in ROM.)
Ver.98-01 48
Manual for 6502 Assembler
Ver.98-01 49
Low-level Tooling System
The JSR instruction performs the “storing-return-address” and “begin-executing” functions (those
c d
are requirements and , above). The stored return-address is the address of the third byte of the JSR
instruction. (Clearly, this is not the address to which the return will ultimately be made, but this address
will be incremented upon return to provide the proper destination. This will be discussed in more detail
when we examine the RTS instruction.) Where is the return address stored? It is stored on the stack,
which means that the JSR instruction operates like the PHA and PHP push instruction. However, the
PHA and PHP instructions just push one byte of data onto the stack (the accumulator contents and the
processor status register contents, respectively), and the JSR instruction pushes two bytes onto the stack
Õ the two-byte address in the program counter. After storing the program counter on the stack, the JSR
instruction loads the program counter with the absolute address contained in its second and third bytes,
which transfers control to the starting address of the subroutine.
Ver.98-01 50
Manual for 6502 Assembler
The JSR instruction occupies three bytes in memory Õ one op-code byte and two subroutine
address bytes (the low-address byte and high-address byte, respectively). The subroutine address is an
absolute address in memory or the label of an absolute address, for assembler source code. The 6502
needs six cycles to execute the JSR instruction because of the stack operations involved.
Now, consider a typical jump to Subroutine instruction, JSR $0503, which is located in memory at
locations $0201, and $0203. Thus:
Memory location Instruction
$0201 JSR Õ
(e.g. the op code 20H)
$0202 $03
$0203 $05
: :
$0503 (First subroutine instruction)
Here, using a figure to describe the Stack Pointer (S), Program Counter (PC), and the Stack in
memory both before and after the instruction “JSR $0503”:
$AA $01C0
S $C3 $XX $01C1
$YY $01C2
PC $02 $01 $ZZ $01C3
$AA $01C0
S $C1 $XX $01C1
$03 $01C2
PC $05 $03 $02 $01C3
In the diagram of Fig.1-4-1A, the program counter is pointing to the first byte of the JSR
instruction ($0201) and the Stack Pointer is pointing to the next free location on the stack (here,
c
assumed $01C3). After the JSR $0503 instruction (Fig. 1-4-1B,) has been executed: The program
Õ d
counter contain the starting address of the subroutine $0503. The Stack Pointer is pointing to a
e
new “next stack location” ($01C1). And the two top bytes on the stack are the MSBY and LSBY
addresses of the third byte of the JSR instruction. As previously mentioned, the 6502 microprocessor
must return to the instruction that immediately follows the JSR instruction. For our example, the 6502
must return to the instruction that starts in location $0204.
The Return from Subroutine (RTS) instruction causes the 6502 to return from the subroutine to the
calling program (the program that contains the JSR instruction).
Ver.98-01 51
Low-level Tooling System
A RTS instruction is always the last instruction that is executed in a subroutine. The RTS
instruction occupies only one byte in memory, takes six cycles to execute, and affects no bits in the
processor status register.
The RTS instruction causes the 6502 to continue program execution at an absolute address that is
one greater than the address on the last two bytes of the stack. Recall that before loading the subroutine
address into the program counter, the JSR instruction pushed two addresses bytes onto the stack. These
were the least-significant address byte (LSBY) and the most-significant address byte (MSBY) of the
memory location that contains the high-address byte (the third byte) of the JSR instruction Õ it was
address $0203, in our example. To retrieve that address, the RTS instruction increments the Stack
Pointer ($C2, in the example), loads the LSBY address into the lower half of the program counter and,
then, increments the Stack Pointer again and, then, loads the MSBY address into the upper half of the
program counter. The program counter is then incremented so that it addresses the next instruction after
the JSR instruction.
There is an implied requirement that when a RTS instruction is executed, the Stack Pointer is
addressing the stack location used or established by the JSR instruction. Therefore, if any push
operations are performed in the subroutine, there must be an equal number of pull operations before the
RTS is executed.
Here, taking an example to look over how the JSR and RTS are used together. Example 1-4-1
shows the Jump to Subroutine instruction that was diagrammed in Fig. 1-4-1. The instruction JSR
$0503 is being used to call a subroutine that simply doubles the value in the Y register. The JSR
instruction starts in location $0201. The subroutine starts in location $0503 and ends in location $0508,
with the RTS instruction.
The 6502 microprocessor must return to the location that follows the JSR $0503 instruction. Since
the JSR instruction occupies three bytes in memory, the return will be to location $0204. Fig. 1-4-2
shows the configuration of the Stack Pointer (S), the Program Counter (PC), and the memory stack
before and after the RTS instruction is executed.
Ver.98-01 52
Manual for 6502 Assembler
$AA $01C0
S $C1 $XX $01C1
$03 $01C2
PC $05 $08 $02 $01C3
(A ) Before RTS
$AA $01C0
S $C3 $XX $01C1
$03 $01C2
PC $02 $04 $02 $01C3
©B ª After RTS
Fig. 1-4-2 RTS pulls an address from Stack
Of course, a subroutine may include one or more JSR instructions that call other subroutines. The
process of calling a subroutine from within a subroutine is called subroutine nesting. Example 1-4-2
shows the JSR and RTS instructions for a program in which subroutine SUB2 is called from within
subroutine SUB1 (i.e., SUB2 is nested within SUB1).
Nesting is usually described in terms of levels. An application like the one shown in Example 1-4-
2, in which the nesting extended only to the JSR to SUB2 (SUB2 did not call another subroutine) is said
to have one level of nesting. There is no reason, though, why SUB2 could not have called another
subroutine (SUB3), with SUB3 calling SUB4, and so on. Considering that each JSR instruction pushes
two address bytes onto the stack, only the capacity of the stack limits the amount of nesting. Since the
stack can utilize all 256 bytes of page one in memory, a 6502 program can have up to 127 levels of
subroutine nesting. However, very few applications will require nesting even approaching this limit
SUB1 SUB2
RTS
RTS
Ver.98-01 53
Low-level Tooling System
1-5-1 Assembler
2500AD 6502 assembler provides two operation modes, Prompt Mode and Command Line Mode.
You will learn how to use the two operation modes from examples presented in each section.
Under DOS prompt (pure DOS or DOS mode of Windows 95), typing “x6502” followed with the
entire path to run Assembler. Such as,
D:\Doc\Doc\tool\guide>C:\SOFT-DOS\X6502\X6502 (enter)
6502 Macro Assembler Copyright (C) 1990 by 2500AD Software Inc. Version 5.02a
Listing Destination (N, T, D, E, L, P, <CR> = N): D (enter)
Generate Cross Reference? (Y/N <CR> = No): (enter)
Ver.98-01 54
Manual for 6502 Assembler
And, you will get two files: DEMO1.OBJ DEMO1.LST. Here we list some portion of the
contents of the DEMO1.LST file…
If there is any syntax error in the source code, the error messages will be shown in the list file. For
an instance, LDY #$FFF is an instruction with a too large immediate value, so the error will be shown
out as below…
Ver.98-01 55
Low-level Tooling System
Using the example above, you can assemble a source code in “Command Line Mode” by typing…
D:\Doc\Doc\tool\guide>C:\SOFT-DOS\X6502\X6502 DEMO1 -D
The file types listed in table are frequently encountered when you use 2500AD 6502 assembler /
link. Those file types are…
Assembler
.asm Source code, input to the assembler
.obj Object file, output from the assembler
.lst Listing file
Linker
.obj Object file, input to the linker
.tsk Executable binary machine code file
.hex Intel Hex and Extended Intel Hex format file, output from linker
.dcf 2500AD high level debug control file
.sym Symbol table file, which includes symbols, labels and corresponding address
Load map file, which includes section range and the corresponding address for
.map
loading each section
Ver.98-01 56
Manual for 6502 Assembler
STORE_END:
JMP $
POWER_ON: ①
LDX #$FF ; STACK POINTER = $01FF
SET_SP ②
TXS ; HERE IS PROGRAM COMMENTS
MOVE_DATA: ③
LDY #0
LDA #<DATA_DB
STA DATA_ADDR_L
LDA #>DATA_DB
STA DATA ADDR H
Ver.98-01 57
Low-level Tooling System
[Example]:
DELAY1:
LDX #0
?LOOP1: n
DEX
BNE ?LOOP1 ①
?LOOP2:
LDY #10
DEY
BNE ?LOOP2
DELAY2:
LDY #0
?LOOP1: o
DEY
BNE ?LOOP1 ②
JMP ?LOOP2 ③
Description:
① Program control will branch to “?LOOP1” marked with . n
② Program control will branch to “?LOOP1” marked with . o
e The JMP instruction will cause a syntax error because “?LOOP2” local label is
not at local area. (Actually, the “?LOOP2” local label effective area is between
DELAY1 and DELAY2 global labels)
To load the high byte of a 16-bit value, use “>”(greater than mark). This allows bits 8
through 15 to be used as re-locatable byte value. To load the low byte of a 16-bit value,
use “<”(less than sign). This allows bits 0 through 7 to be used as re-locatable byte
value. In the above example, the address of label “DATA_DB” is $C027(③), you can
load low byte of the $C027 by using “<” (see ①), and you can load high byte of the
$C027 by using “>”(see ).d
Ver.98-01 58
Manual for 6502 Assembler
If a directive starting in column one must be prefixed by a decimal point (.), otherwise the
assembler treats it as a label. You can precede it with a decimal point no matter where it is in the line to
distinguish it as a directive clearly. Make an explanation in the following example:
DEMO1.ASM
.CHIP 6502 ①
.SYNTAX 6502 ②
.SYMBOLS ③
.OPTIONS DCH ④
.LINKLIST ⑤
W_RAM .SECTION PAGE0, RANGE $0 $7F, REF_ONLY ⑥
DATA_ADDR_L: DS 1 ⑦
DATA_ADDR_H: DS 1
ALABEL_DS: DS 10
P_ROM .SECTION OFFSET $C000, RANGE $C000 $FFF9
⑧
POWER_ON:
LDX #$FF
TXS
LDY #0
LDA #<DATA_DB
STA DATA_ADDR_L
LDA #>DATA_DB
STA DATA_ADDR_H
NEXT_BYTE:
LDA (DATA_ADDR_L),Y
CMP #$FF
BEQ STORE_END
STA ALABEL_DS,Y
INY
JMP NEXT_BYTE
STORE_END:
JMP $
LABEL_BLKB:
BLKB 10,$A5 ⑨
DATA_DB:
DB $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$FF ⑩
DATA_DW:
DW $0000,$0001,$0002,$0003,$0004,$FFFF ❶
IRQ_ISR:
RTI
NMI_ISR:
RTI
VECTAB .SECTION OFFSET $FFFA, RANGE $FFFA $FFFF ❷
DW IRQ_ISR
DW POWER_ON
DW NMI ISR
Ver.98-01 59
Low-level Tooling System
Description:
① Specify 6502 CPU instruction codes to be assembled.
② Declare the assembly language syntax is standard 6502 syntax.
③ Specify a symbol file to be generated for debugging.
f Specify a map file, high-level debug control file to be generated, and the output file format is in
Intel Hex format.
g Make the linker produces re-locatable list file. After link operation completed, the addresses in
list file will be changed to appropriate absolute addresses. Please refer to the next two examples:
If no LinkList declared, the addresses in list file are still the offset values in that section. Like,
13 0000 P_ROM .SECTION OFFSET $C000, RANGE $C000 $FFF9
14 0000 POWER_ON:
15 0000 A2 FF LDX #$FF
16 0002 9A TXS
With LinkList declaration, the addresses in list file are changed to the absolute addresses:
13 P_ROM .SECTION OFFSET $C000, RANGE $C000 $FFF9
14 C000 POWER_ON:
15 C000 A2 FF LDX #$FF
16 C002 9A TXS
⑥ Declare a section named W_RAM, which is located in zero-page. The range of the section is
$00~$7F, if you use the space over the range then the error message will appear in link. The
last “REF_ONLY” option is a reference only declaration that the section does not generate real
instruction codes to occupy spaces. Normally, just those sections that belonged to RAM will
declare “REF_ONLY”. Please note that the section name is not suffixed with colon (:).
i DS 1 (Define Storage) directive reserves one byte space for variables, but does not store a
value in the reserved area. This directive is used in RAM memory range. In the example below,
due to “DS 1” reserves 1 byte, so the address of “DATA_ADDR_H” will be $0001.
8 W_RAM .SECTION PAGE0, RANGE $0 $7F, REF_ONLY
9 0000 DATA_ADDR_L: DS 1
10 0001 DATA ADDR H: DS 1
⑧ Declare a section named as “P_ROM” that its start address is $C000 (offset $C000), and its
range is from $C000 to $FFF9 (RANGE $C000 $FFF9).
k Define 10 bytes with identical value - $A5, see the following example:
30 C01A 4C 1A C0 JMP $
31
32 C01D LABEL_BLKB:
33 C01D BLKB 10,$A5
34
35 C027 DATA_DB:
Ver.98-01 60
Manual for 6502 Assembler
$C01A stores JMP $ machine code Consecutive 10 bytes for $A5 from $C01D
⑩ DB (Define Byte) directive declares the values followed are stored in byte size. Please refer to
the list file below:
35 C027 DATA_DB:
36 C027 00 01 02 03 04 DB $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$FF
05 06 07 08 09
FF
n DW (Define Word) directive declares the values followed are stored in word size. Please refer
to the list file below:
38 C032 DATA_DW:
39 C032 0000 0100 0200 DW $0000,$0001,$0002,$0003,$0004,$FFFF
0300 0400 FFFF
❷ Start a new section named “VECTAB”, and specify its start address as $FFFA. This section is
declared for composing the interrupt vector table of 6502 CPU.
❸ Ending the assembly process to here.
DEMO2.ASM
FIVE_TIME
.CHIP 6502
.SYNTAX 6502
.SYMBOLS
.OPTIONS DCH
.LINKLIST
.INCLUDE MAC.INC ①
ADD_COUNT EQU 6 ②
.IFDEF FIVE_TIME ③
SUB_COUNT = 5 ④
.ELSE
SUB_COUNT = 4
.ENDIF
Ver.98-01 61
Low-level Tooling System
MAC.INC
ADD: .MACRO RESULT,OP1,OP2 ⑥
CLC
LDA OP1
ADC OP2
STA RESULT
.ENDM ⑦
Ver.98-01 62
Manual for 6502 Assembler
Description:
① Include “MAC.INC” file into the DEMO2 file as a portion of source code by using “INCLUDE
directive”.
② Equate label “ADD_COUNT” to “6”.
③ Declare a conditional assembly. Assemble the source code between .IFDEF directive
and .ELSE directive if “FIVE_TIME” symbol already defined; otherwise, assemble the source
code between .ELSE and .ENDIF directives.
④ Declare EQU directive is equivalent to “=”.
⑤ Using macro definition (here, “ADD” macro) to improve the readability of source code.
⑥ Define a macro named “ADD”. Please note that the macro name suffixed with colon (:) and use
“.MACRO” to specify it as a macro.
⑦ End of macro.
DEMO3.ASM
.CHIP 6502
.SYNTAX 6502
.SYMBOLS
.OPTIONS DCH
.LINKLIST
Ver.98-01 63
Low-level Tooling System
IRQ_ISR:
RTI
NMI_ISR:
RTI
Description:
① Start a new section named “BANK0”, and specify it as an indirect section. We declared it as an
indirect section to serve the purpose of multi-ROM-bank. Since the addressing range of 6502
CPU is limited to 64K bytes, we need build some bank-switching mechanism in the single chip
we developed. For the different banks, their addresses mapped to 6502 CPU are same. The
indirect section allows overlapped ROM data, so we can use this feature to serve as bank data
definition.
② Start a new section named “BANK1”, and specify it as an indirect section. You can see that its
addresses overlap on BANK0.
③ After an indirect section declared, the zero-page section declaration should be more complete in
form. You can see the declaration of zero-page section is different from that appeared in the
prior example.
1-5-2 Linker
2500AD 6502 linker provides four operation modes: prompt mode command line mode data
file mode and enhanced data file mode. We just like to describe the first three modes here, and we also
take some practical examples to aid description.
Under DOS prompt (pure DOS or DOS mode of Windows 95), typing “link” followed with the
entire path to run Linker. Such as,
D:\Doc\Doc\tool\guide>C:\SOFT-DOS\X6502\LINK
Ver.98-01 64
Manual for 6502 Assembler
2500 A.D. Linker Copyright (C) 1990 by 2500AD Software Inc. Version 5.03d ①
Input Filename: DEMO1 (enter) ②
Input Filename: (enter) ③
Description:
① Show the version and copyright of the Assembler.
② Require .OBJ file to be linked (here, we use DEMO1 file for instance).
③ Assign another .OBJ file to be linked if necessary or press (enter) to bypass.
④ Assign the output filename. It’ll use the same name of input file if you don’t assign, and the
extension name depends on the definition in options block.
⑤ Please give the library name if you have used, or press (enter) to bypass.
⑥ Link option. It has same effect as OPTIONS directive in source code. Press (enter) to use the
options specified in source code as default, or assign new options to replace it. If you want to
generate a binary executable file, for example, input the “X” option here. However, if you have
used the indirect section, the “X” parameter will cause errors in link.
Under DOS prompt (pure DOS or DOS mode of Windows 95), typing “link with –C parameter” in
entire path, to run Link in “Command Line Mode”. Such as,
D:\Doc\Doc\tool\guide>C:\SOFT-DOS\X6502\LINK -C DEMO1
DEMO1.LNK
DEMO1 ①
②
③
④
DCH ⑤
Ver.98-01 65
Low-level Tooling System
Description:
① The string in this row is corresponding to the first input string in Prompt mode. (Input
Filename)
② The string in this row is corresponding to the second input string in Prompt mode. (Input
Filename)
③ The string in this row is corresponding to the third input string in Prompt mode. (Output
Filename)
④ The string in this row is corresponding to the fourth input string in Prompt mode. (Library
Filename)
⑤ The string in this row is corresponding to the fifth input string in Prompt mode. (Options)
After a text file edition completed, typing “link with that filename” in entire path under DOS
prompt (pure DOS or DOS mode of Windows 95) to run Link. Such as,
D:\Doc\Doc\tool\guide>C:\SOFT-DOS\X6502\LINK DEMO1
Ver.98-01 66
Manual for 6502 Assembler
Ver.98-01 67
Low-level Tooling System
Easy to use windowed interface with pull-down menu, dialog box, functions / hot keys, mouse
support, and context sensitive help.
Each window can be sized, moved, added or removed.
Save software setup including window layout, set breakpoints, watch variables, trigger…etc. to
editable text file.
Please contact us if any of the above items is missing from your package.
Warning:
Running RICE65 without an installed mouse will cause the program to crash.
Ver.98-01 68
Manual for 6502 Assembler
Power Jack Found on the right side of the emulator, the power jack provides
connection to the enclosed 9V-power adapter.
DB-25 Connector The DB-25 connector on the left of the emulator is used to connect to the PC
host via the enclosed parallel extension cable. This cable has connection on all
25 pins.
DB-15 Connector The DB15 connector is used for connecting the external probe cable for logic
trace, break or trigger functions.
POWER LED The POWER LED is on whatever power is applied to RICE65. It blinks when
power is initially supplied to the system during the power up self-test.
RDY STATUS LED This LED shows the status of the RDY pin (pin2) of the 65(C)02 processor.
The LED will be on when the pin is low which is the normal state for the
microprocessor. When this LED is off, the 65(C)02 will be disabled and this
indicates something is wrong with the target.
Emulation Cable RICE65 can be operated with or without being connected to a target. If a target
is present, the gray emulation cable connects the RICE65 emulator to the target
application under test. The emulation cable ends in a 40-pin dual-in-line plug
with pin1 indicated by the line red on the cable.
The 8-pin socket marked “EXT XTAL” allows users to plug in a crystal and provide an exact
oscillator frequency not available internally to run the application. The crystal can be plugged into
Ver.98-01 69
Low-level Tooling System
sockets as shown below. If an oscillator input signal is used, please connect that to any of the four
sockets to the right.
Ver.98-01 70
Manual for 6502 Assembler
Jumpers
The PB-65(C)02 Probe Card has been installed inside RICE65 to emulate the 6502 or 65C02
processor core. The probe is connected to the RICE65 base via socket and header pins. The probe card
carries the 6502 or 65C02 processor for emulation. There are two jumpers on the probe card:
c JP1 FRZCTL
This jumper is just used for 65C02 processor-based products. The “Freeze Control” jumper is
used to set pin35 to a low logic level when the emulator is in halt mode. It can then be used to
freeze external peripherals, such as timer, during emulation.
d JP2 EXTMEM
The “External Memory” jumper is used to set pin35 to a low logic level when the processor is
accessing external memory.
e JP3 +5V
The “+5V” jumper, when enabled, will provide a 5V (100mA) output to the VDD pin of the
emulation plug. You can use this output to drive your target if it consumes less than 100mA.
The External probe cable has twelve logic probes and is connected to the emulator via a 15-pin
connector. Clips on the first eight cables, using standard electronic color coding (brown to gray as for 1
to 8), are for external trace inputs. When connected to the target application, these 8 clips register the
real-time logic status of those points during program execution.
Ver.98-01 71
Low-level Tooling System
Captured data are automatically stored in the real-time trace buffer. The functions of the other four
logic clips are assigned as follows:
Ver.98-01 72
Manual for 6502 Assembler
Unless the +5V jumper (JP3) on PB-65(C)02 is enable (see 2-2-3), the +5V from the emulator has
been isolated and a separate power source is needed for the target system. Please follow these sequences
when powering up the hardware and reverse them when powering down to prevent damage to the
emulator.
c Plug emulation cable to target.
d Apply power to host PC.
e Apply power to RICE65 base unit.
f Apply power to target system.
g Plug the parallel extension cable into the emulator.
Before you begin to use the RICE65 software, it is recommended you make a backup copy. The
disk provided is not copy protected and a backup copy can be made using the DISKCOPY command.
Prepare a blank (either formatted or unformatted) disk, place Program Disk in drive A and type the
following at the DOS prompt.
Follow the instructions on screen and copy all files from the Program Disk (source) to the blank
disk (target). Place the original disk in a safe place and proceed with the installation procedure.
Make a new directory RICE65 and copy all files from the diskette (placed in drive A) to the new
directory.
C:\>MD RICE65 [Enter]
C:\>CD\RICE65 [Enter]
C:\RICE65>COPY A:*.* [Enter]
It is recommended to add the RICE65 directory to the PATH statement in the Autoexec.bat file
and work in the directory where your working files (like .ASM or C source files, .INC or .H header
files), reside.
PATH C:\;C:\DOS;C:\RICE65;
This way, you can call up RICE65 anywhere. Remember to restart the computer or run the
Autoexec.bat file again for the new path to take effect.
Ver.98-01 73
Low-level Tooling System
RICE65 helps you to develop and test 65(C)02 based applications by locating error and finding the
cause of the error. It does these by slowing down program execution so you can examine the state of the
program at any given spot. You can even test new values in different variables to see how they affect
the program. Specific functions that aid in this debugging process are given below:
Stepping Execute the program one instruction or multiple instructions at a time and
watches if the program is behaving the way it should.
Stepping over Call Execute the program one instruction at a time, but stepping over any
subroutine calls. This function speeds up debugging by stepping over
subroutine that you are sure to be error-free.
Viewing Open a special window to show the state of the program from various
perspective: source file, program memory, variables and special registers.
Setting Breakpoints Control where the program stops running to examine the program’s status.
Real-time Tracing Capture external data from the circuit and aids in debugging hardware. When
working with the breakpoint system, it records all executed instructions prior to
the break.
Changing Replace the current value of a variable with a new value and see its effect on
the program.
Watching Isolate program variables and keep track of their changing values as the
program runs.
You can use these functions to dissect your programs into discrete blocks, confirming that each
block works before moving to the next. In this way, you can burrow through the program, no matter
how large or complicated, until you find where the bug is.
Ver.98-01 74
Manual for 6502 Assembler
It is necessary to have a mouse installed on the system, otherwise the program will not operate
properly. To use a mouse, make sure it is properly connected and the mouse driver loaded before you
start the program. Only the left button of your mouse is used for most of the time except for during the
Run mode, pressing the right button will stop the program running.
To make selections with the mouse, point to the object and click the left button. When sizing or
moving windows, hold down the left button and drag the mouse to a new location, release the left button
to confirm the selection.
If you have added the RICE65 directory in the PATH statement in the Autoexec.bat file, you can
run RICE65 from anywhere by typing one of the followings:
RICE65’s main screen contains a global menu bar at the top of the screen, a Configuration Bar
and a Status / Key Usage Line at the bottom. Three default windows are opened at start, the Source
Window, Register Window and Program Memory Window.
Familiarize yourself with the menu functions by clicking on each pull down menu and look at each
function. The following elements of the RICE65 screen will be described next.
Menus
Dialog Boxes
Windows
Configuration Bar
Status / Key Usage Line
Ver.98-01 75
Low-level Tooling System
File View Run Break Watch Trace Config Options Help Source
Program Memory
0000 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 ……………………
0010 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 ……………………
0020 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 ……………………
0030 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 ……………………
0040 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 ……………………
0050 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 ……………………
2-3-4 Menu
The RICE65 has a convenient menu system accessible from a menu bar running along the top of
the screen. The main menu is always available except when a dialog box is active. A pull down
functional menu is available for each item on the menu bar. Through these menus, you can:
Execute a command.
Access a submenu indicated by the menu item followed by a submenu icon (>>).
Open a dialog box indicated by a menu item followed by a dialog box icon (…).
Ver.98-01 76
Manual for 6502 Assembler
If a command is followed by an ellipsis (…), it means more information must be provided before
the command is executed. You provide this information in a dialog box, which appears when you issue
the command. Dialog boxes can contain one or more of the following items:
Item Description
(*) Radio button Radio buttons offer a set of toggles; only one option can be
chosen. Use the arrow keys to move between the choices and press
[Spacebar] to select.
Push button Push buttons are “shadowed” text, which pass commands to the dialog
box. The OK button exits the dialog box without changing the current
settings.
List box A list box contains a list of items from which you can choose. A
typical list box is one to select the file to be debugged under File |
Open File…command.
Ver.98-01 77
Low-level Tooling System
You navigate around a dialog box by pressing [Tab] or [Shift]-[Tab] key that moves the cursor
from one item to the next. Within sets of radio buttons, use the up / down arrow keys to select the
setting and press [Spacebar] to confirm the selection. To choose a push button, tab to it and press
[Enter]. If you have a mouse, just click the item you want to choose. To cancel the dialog box, click the
Cancel button.
2-3-6 Windows
RICE65 displays all information and data in windows. Some windows are for display only while
others allow you to modify their contents. You can open most windows using commands in the View
Menu.
When RICE65 starts, the Source Window, Register Window and Program Memory Windows will
be opened by default. No matter how many windows are opened, only one window is active at a time.
The active window has an intense white border around it and a title of a different color. If your windows
are overlapping, the active window is the topmost one. The Mode Window at the upper right hand
corner also displays the name of active object. Followed are the different types of windows you can
open from the View Menu.
Displays the instruction codes in program memory in hex and ASCII formats. You can change the
value of the registers by just typing over it. To do so, first press [F4] or [Tab] until Program Memory is
the current window; then use the arrow keys to highlight the field to be edited and type in the new value.
The new values will be updated in the Source Window, ASM Window and in the Emulator.
Program Memory
0000 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 ……………………
0010 – 48 65 6C 6C– 6F 20 57 6F – 72 6C 64 21 – 20 20 20 00 Hello World!
0020 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 ……………………
0030 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 ……………………
0040 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 ……………………
0050 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 – 00 00 00 00 ……………………
The Program Memory Window can be enlarged to display more registers. Before doing so, it is
recommended to change the display to 43 / 50 line under Options | Display options. During stepping,
only data in range 0 – 1FF and the visible range in the Program Memory Window will be updated. This
ensures stepping to be more responsive.
Source Window
The Source Window consists of breakpoint and trigger point indicators, line number, program
counter, op code and the source codes or disassembled codes of the program you are debugging.
Ver.98-01 78
Manual for 6502 Assembler
You can move around the window using arrow keys or clicking the scroll bar with a mouse. A
triangular cursor marks the next executable line. If the Source Window does not display the original
source lines, this means RICE65 cannot locate the ASM file in the current directory.
Source <C:\rice65\as.asm>
00033 org 0C000h
00034 ;
. . 00035 C000 – A2 – FF start: ldx #ffh
. . 00036 C002 – 9A txs
B . 00037 C003 – A9 FF LDA #FFH
. . 00038 C005 – 85 00 STA in_port
. T 00039 C007 – A9 00 lda #0
. T 00040 C009 – 85 – 02 STA DIRP2
00041
. . 00042 C00B – EA NOP
. . 00043 C00C – 85 70 sta have_line
. . 00044 C00E – 85 71 sta buf_index
Breakpoint Indicator
ASM Window
ASM code
The ASM Window displays the disassembled
codes for the object codes. When debugging in C, C003 – A9 FF LDA #FFh
C005 – 85 00 STA 00h
users can open this ASM Window to display the
C007 – A9 00 LDA #00h
corresponding disassembly codes. The highlighted C009 – 85 02 STA DIRP2
line in the ASM Window corresponds to the C line C00B – EA NOP
in the Source Window. C00C – 85 70 STA have line
Register Window
Displays the current contents of the program counter, the Processor Status (P or PS) register, the
Accumulator (A), the X and Y Index registers and the Stack Pointer Register
(SP). The values are displayed in both hex and binary formats. You PC C003
can change the hex value of the registers by typing over them. To edit NV1BDIZC
the codes, use the arrow keys to highlight the field and type in the P B5 10110101
A FF 11111111
new value.
X FF 11111111
Y FF 11111111
Stack Window SP FF
Displays the stack memory from 0 to 100x1FF in program memory of the 65©02. This window
can be sized to display the desired stack locations.
Stack
01E0 – 0 0 0 0 0 0 0 0 – 0 0 0 0 0 0 0 0 – 0 0 0 0 0 0 0 0 – 0 0 0 0 0 0
00
Ver.98-01 79
Low-level Tooling System
Watch Window
Displays the name, address and Hex value of the watch variables Watch
you define for specific viewing. You can add variables to the Watch Buf_index <0071> = 0000
Window using the [Ctrl]-[W] hot key. Watch variables can also be Fail <C0AE> = 46
found in the Program Memory Window in registers as defined by Have_line <0060> = 00
the user. Followed is a sample Watch Window.
Displays the contents of the 8K*24-bit circular trace buffer board which records the real-time
executed instructions. The most recent instruction is found at the bottom of the buffer. The buffer
contains:
Line number.
Data bus content or captured data on the eight external probes.
Instruction cycle.
Address.
Op code.
The source or disassembled code.
Trace Buffer
Line Bus Cycle Address Instruction-code comments
0001 FF 3 C02C – A5 70 lda have_line ; check
0002 00 2 C02E – EA NOP
0003 F0 2 C02F – F0 E4 beq wait ; not do
0004 78 6 C015 – EE F0 01 wait: INC TTTA
0005 DC 4 C018 – AD F0 01 LDA TTTA
0006 DC 2 C01B – D0 0A BNE WAIT1
0007 EE 6 C027 – 20 90 C0 WAIT1: JSR TTLP
0008 C0 3 C090 – 48 TTLP: PHA
0009 DC 2 C091 – 70 0F BVS OVERFLOW
Trace Buffer
Line 8 7 6 5 4 3 2 1 Cycle Address Instruction-code
0001 1 1 1 1 1 1 1 1 3 C02C – A5 70 lda have_line
0002 1 1 1 1 1 1 1 1 2 C02E – EA NOP
0003 1 1 1 1 1 1 1 1 2 C02F – F0 E4 beq wait
0004 1 1 1 1 1 1 1 1 6 C015 – EE F0 01 wait: INC TTTA
0005 1 1 1 1 1 1 1 1 4 C018 – AD F0 01 LDA TTTA
0006 1 1 1 1 1 1 1 1 2 C01B – D0 0A BNE WAIT1
0007 1 1 1 1 1 1 1 1 6 C027 – 20 90 C0 WAIT1: JSR TTLP
0008 1 1 1 1 1 1 1 1 3 C090 – 48 TTLP: PHA
0009 1 1 1 1 1 1 1 1 2 C091 – 70 0F BVS OVERFLOW
Ver.98-01 80
Manual for 6502 Assembler
You can scroll through the buffer using the arrow keys or by clicking the vertical bar with a
mouse. The contents can also be saved to a text file using the File | Save >> Trace Buffer…command.
Users can stop capturing data but keep the processor running once the buffer is full. This is
achieved through the Break | Set Breakpoints…| More Break >> Stop on Trace Buffer Full function.
The Cycle Counter Window displays instruction cycle and elapse time information. The execution
time is based on the clock source specified under the OSC Frequency dialog box. You can reset the
clock to zero, start or stop the clock anytime by clicking the corresponding button.
Cycle Counter
Verify Window
The Verify Window displays the verification errors when comparing the contents of the program
memory inside the emulator against those in the memory buffer. If there is no error, the message “No
verify Error” will appear.
Verify Window
Once you have opened these windows, you can move, re-size or close them with commands from
the System Menu or via their respective hot keys.
Moving Windows
You can easily move the onscreen windows around using the [Shift]-[F3] key. First, make the
window you want to move active by pressing the [F4] key and then press [Shift]-[F3]. When the
window changes to have a thick border, use the arrow keys to move the window around. Press [Enter] to
confirm the change. If you have a mouse, click on the title bar and drag the mouse to define a new
location. Release the mouse button to confirm the change.
Ver.98-01 81
Low-level Tooling System
You can cycle through windows on screen by pressing [F4] and [Shift]-[F4] keys. If you have a
mouse, you can activate a window by clicking inside it.
Sizing Windows
To size a window, use the [Alt]-[F3] key. After making the window active, press [Alt]-[F3]. Once
the border of the window changes, use the arrow keys to resize the active window. Press [Enter] to
confirm the change. If you have a mouse, click and drag the lower right corner to resize the window.
Release the button when done.
NOTE: Some windows cannot be sized while some can only be sized in one direction.
Closing Windows
When you are through working with a window, e.g. Trace Buffer or Program memory Window,
you can close it by selecting System | Close Window command or press the [Alt]-[F4] hot key
combination. If you have a mouse, click the inverted triangle at the top left corner of the window to
close it.
Re-opening Windows
You can re-open a closed window by specifying it under the View Menu.
You can use the System | Restore command to repaint the screen the way the program was initially
started with only four default windows: Source, Register, Data Memory and Stack Windows.
The Configuration bar is located towards the bottom of the screen. It displays the source of the
oscillator (OSC) to run the target application, status (HALT/RUN/WAIT) of the emulator processor
and the current program counter.
The status line is located at the bottom of the RICE65 screen. When the menu system or a dialog box is
active, the status line provides information on the highlighted item.
Ver.98-01 82
Manual for 6502 Assembler
When one of the windows is the active screen object, the status line provides at-a-glance keystroke
summary on the different emulation controls.
Getting context-sensitive help anywhere within the RICE65 program is simple. Select the desired
menu option and then pressing the [F1] key. You will see a brief description of the feature in the Help
dialog box. To exit, simply press the [Esc] key or click the Exit button.
You can learn a lot by working your way through the menu system and pressing [F1] at each
command to get a brief description of what it does. Select Index button in the dialog box to see and
access a list of items with help information available.
Ver.98-01 83
Low-level Tooling System
RICE65.EXE The main executable program for the RICE65 system. Type RICE65 or
RICE65 <filename> to start the program. The second option runs the
RICE65 program and loads the specified hex file to the Source Window. It also
loads the setup file by the same root name with a .SET extension if found in the
same directory.
RICE65.MSG/NDX Files containing help information and help index to the RICE65 software.
Use an editor of your choice to create the application program. Currently, RICE65 only support
source-level debugging for 2500AD assembler and compiler and WDC / Zardoz Assembler. Once you
get a successful compilation, the 2500AD will generate the HEX (Intel Hex), DCF and SYM files used
by RICE65 for source level debugging.
To start RICE65, simply type RICE65 at the DOS prompt followed by the optional name of the
program, and press [Enter].
RICE65 will load the source program to the Source Window if the .HEX, .ASM, .DCF and .SYM
files are found in the current directory. When only the .HEX file is found, the file will be disassembled
and loaded into the Source Window. When no file by such name is found, RICE65 will load a blank
disassembled file.
RICE65 supports both internal and external oscillator for the 65C02 processor from one of the
following sources:
an external crystal plugged inside the “EXT XTAL” socket of the RICE65 board. Make sure to
jumper JP3 and one of JP1 or JP2 for the speed range. See page 6 for more information.
an external oscillator input connected to the PHI2 (pin-37) of the target processor.
from the internal clock frequencies provided by the RICE65 system, at 8MHz, 4MHz, 2MHz, …,
31.25KHz.
Ver.98-01 84
Manual for 6502 Assembler
You can always select the internal clock and specify an appropriate frequency to walk through the
codes, even without the presence of the target application.
To select oscillator source, press [Ctrl]-[F] or go to Config | OSC Frequency dialog box as shown
below where you can specify the oscillator source for the clock and frequency for the internal source.
Use the [Tab] key to cycle among the different fields listed below:
clock source Use the up/down arrow key to select and then press [Spacebar] to confirm.
External Frequency This is used to calculate elapse time in the Cycle Counter Window. Enter the
value in KHz in the edit box.
Internal Frequency When the list box is active, use the up/down arrow key to scroll through the
list and select the desired frequency. Press [Tab] to exit to another field.
OSC Frequency
Oscillator Source:
( ) External
(*) Internal
8000.000
4000.000 OK
2000.000
1000.000 Cancel
250.000
52.500
31.250
If you have a mouse, just click the item you want to choose. Select OK to accept the settings and
Cancel to cancel the changes.
Real-time Execution
Ver.98-01 85
Low-level Tooling System
These commands run the processor until encountering breakpoint or user interruptions. During
real-time execution, the contents of the registers will not be retrieved or updated until the processor is
halted.
Non-real-time Execution
2-4-5 Breakpoints
A breakpoint is a condition in which the processor halts program execution when a certain criterion
is met. RICE65 can be programmed to halt in the following ways:
Allows users to halt the processor when the program counter equals certain values. Note that the
processor breaks only after the valid instruction has been executed.
There is also a Multiple Break function which halts program execution after a break address has been
executed up to 2047 times.
One of the external probes on RICE65 is Break Input. It is used to halt the processor when the line
sees a rising or falling edge.
Users can program the emulator to halt whenever the 8K real-time trace buffer is full. This break
will automatically be in force when forward trace option is enabled.
Multiple Break
Found under the Break | Set Breakpoints>>More Break menu, this allows users to halt the
processor after an instruction at a set breakpoint has been executed a particular number of times.
Ver.98-01 86
Manual for 6502 Assembler
Found under the Break | Data Capture Break… menu, this function allows the processor to halt
when the value in the captured address matches the specified value. A mask value can also be entered
for special bit comparison. NOTE: When the oscillator speed is above 1MHz, the Multiple Break and
Data Capture Break may execute several more instructions prior to breaking.
Once the user has defined an address range for read only memory, the processor will halt whenever
the referenced address is being written to.
The 8K by 24-bit trace buffer is a circular buffer which continuously captures the following data,
with the most recent information stored at the bottom of the buffer.
line number
data bus content or captured data on the eight external probes (via the Options | Trace Options
menu),
instruction cycle
address
opcode, and
the source or disassembled code (via the Options | Trace Options menu).
The trace-buffer will automatically records the above data as program codes are executed. You can
also specify special tracing under the Trace | Set Trace Range… Menu.
Backward Trace
This is the default trace mode, saving all executed instructions in the 8K buffer and throwing away
old ones. The last executed instruction will be found at the bottom of the buffer. It is not necessary to
input an address range for this trace.
You are required to enter the Start and End address for this option. The emulator will clear the
buffer upon reaching the Start, start-capturing data until the End address at which a breakpoint has
been set internally. To view the data, use the Upload Trace command.
In this option, the processor will keep running while data within the address range will be
repeatedly captured to the buffer. You can also enter multiple address ranges to be traced.
Ver.98-01 87
Low-level Tooling System
To do so, go the Break | Set Trigger Points Menu and select the addresses as trigger address and
then enable “Real-time Trace” in the Trace | Set Trace Range Menu.
Forward Trace
The Forward Trace will start capturing data from the Start address and the processor will break if
the trace buffer is full. This prevents the Start Address from being overwritten by the circular buffer.
Note that if the Start Address is within a loop and keeps repeating, only one instance will be saved to
the trace buffer. The processor will keep running. In such case as the buffer is not full to cause a break.
Working together with the breakpoint system, the trace buffer contains valuable information for
debugging.
When RICE65 initially starts, only the Source Window, Register Window and Program Memory
Window are opened. You can open additional windows via the View Menu to aid in debugging.
To customize RICE65, open the windows you need, size them and place them in any location you
feel helpful with your debugging. Set desired breakpoints, trigger points, watch variables, etc. To save
the setup, select Options | Save Setup.., and press [Enter] to use the proposed filename.SET filename.
Since the setup file shares the same root name as the object file, the layout will be restored
whenever the object file is opened. This allows you to quickly resume the debugging session the way
you left it.
The setup of the debugging environment is saved in an editable text file in the current working
directory. You can edit this file using any editor.
[Port]
LPT=0x378
Delay=1
[Processor]
MCU=65C02
Osc=1
Freq=2
KHZ=4000.000
[Code]
File=demo65.hex
Trace=1
Ver.98-01 88
Manual for 6502 Assembler
[Window]
Program=0 5 0 22 40
Source=1 1 0 14 34
Register=1 1 55 18 66
Stack=0 1 72 4 79
Watch=0 3 62 10 79
Trace=0 1 17 21 77
Asm=0 29 0 36 29
[Display]
Line=0
Tabsize=8
Speaker=0
[Break]
Num=0
Trigger=0
Buffer Full=0
BufferStop=0
MultipleBreakFlag=0
MultipleBreakCount=0
[Data_Capture]
Flag=0
Address=0xD400
Mask=0xFF
Compare=0x45
[Trig]
Num=0
[Watch]
Num=0
[Trace]
Trace_Range=0
Begin=0x0000
End=0x0000
[Update_Memory]
Num=0
Ver.98-01 89
Low-level Tooling System
[External_Memory]
Num=0
[ReadOnly_Memory]
Num=0
Ver.98-01 90
Manual for 6502 Assembler
The Open File… command loads a program from disk to debug and downloads it to the emulation
memory of the RICE65 hardware. Select from the pop-up list box (with an automatic *.Hex filter) the
program to debug. The program must be an Intel Hex file with an .HEX extension.
RICE65 supports source level debugging on different assembler compilers. Please refer to
Appendix A for more details.
To load a file, go to File | Open File… or press [Ctrl]-[O] to access the Open File dialog box. The
list box will display files with HEX extension in the current directory. The first file in the list box will
be highlighted. Use the up/down arrow key to highlight the file to be opened and press [Enter]. The
selected file will be loaded in the Source Window and program memory downloaded to the emulation
memory of the RICE65 hardware.
Open File
Filename: A2.HEX
C:\RICE65\
OK Cancel
To change directory, press [Tab] to highlight the list box for Dirs/Drives and select the new
directory desired.
Ver.98-01 91
Low-level Tooling System
2-5-2 Save>>
The Save>> command leads to a submenu through which you can save the contents of the
followings to disk in the current directory:
trace buffer
disassembled code
program memory
Press the highlight character or move the highlight bar to select the option and press [Enter]. You
are prompted for the name of the file in the upcoming dialog box. Enter the complete filename
including the file extension, if desired.
The Download Program command lets you download the hex codes from the program memory
buffer into the emulation memory inside the RICE65 hardware for debugging.
The Upload Program command allows you to upload a specified range of program memory from
the emulator memory or external memory into the program memory buffer which can be viewed in the
Program Memory Window.
To read from External Memory, first set the memory range under the “Option | Set Memory
Range..” menu.
Start: 0000
End: FFFF
OK Cancel
At the dialog box, enter the Start and End address, press [Tab] to or click the OK button to exit. If
the specified address range is within the external memory range defined as previously discussed, the
data will be read from external memory in the target.
This command compares the data in the specified address range from the emulator or external
memory to the program memory buffer. If there is error, the Verify Window will be opened, else, the
message “Verify Program Pass” will appear. You can then press [Enter] to exit.
Ver.98-01 92
Manual for 6502 Assembler
Start: 0000
End: FFFF
OK Cancel
The command leads to a submenu with different file operations regarding the external memory:
Open File
Download External Memory
Upload External Memory
Open File
This command leads to the Open File dialog box where user can specify a hex file to be loaded into
the external memory buffer in the PC.
This command downloads a specified range of data, which is in the external memory buffer of the
PC, to the memory in the target application. Use the [Tab] key to go to the different fields.
Download External Memory
OK Cancel
Enter the Target Start address where the data will reside in the target application. This address
does not have to match the Buffer Start address, which is the beginning address for the data to be
downloaded to the target. The Buffer End address provides the lower bound of the data to be
downloaded to the target.
To accept the address range for download, press [Tab] to OK and exit.
This command transfers a specified range of external memory from the target to the internal memory
inside the emulator.
Ver.98-01 93
Low-level Tooling System
This upload is necessary in order to debug the program via stepping or setting breakpoints. Enter
the Start and End addresses at the dialog box and click OK to exit.
Start: 0000
End: FFFF
OK Cancel
NOTE:
When debugging codes uploaded from external memory, make sure to open the ASM window as
RICE65 only supports disassembled code debugging for external memory.
The New Directory command lets you set a new current drive and/or directory by prompting you
for the new drive and/or directory name. The prompt is initialized to the current drive and directory.
Enter any logical drive and directory path to overwrite the existing one. You can use this command to
examine the current drive and directory settings.
The DOS shell command starts a DOS command processor so that you can type commands exactly
as you were at the normal DOS prompt. When you have finished entering DOS commands, type “exit
“ to return to the ICE program.
The memory for your program image is still resident in the RAM. Therefore, there may not be
enough memory to run another large program.
The Quit to DOS command returns control to DOS. The memory for your program image is freed, and
any open file handles are closed.
Ver.98-01 94
Manual for 6502 Assembler
Displays the instruction codes in program memory in hex and ASCII (display only) formats. You
can change the hex value of the registers by just typing over it. To do so, first press [F4] or [Tab] until
Program Memory is the current window; then use the arrow keys to highlight the field to be edited and
type in the new value. The new values will be updated in the Source Window, ASM Window and in the
Emulator.
The Program Memory Window can be enlarged to display more registers. Before doing so, it is
recommended to change the display to 43/50 line under Options | Display options.
Program Memory
The data in the Program Memory Window can be either be from the internal program memory
buffer or external memory, depending on the definition under the Options | Set Memory Range... menu.
In order to be more responsive during stepping, only the following portions of the entire 64K memory
will be updated
data in range 0-1FF
data in the visible range in the Program Memory Window, this depends on the size of the window
data within the “Update Memory Range” defined under the Options | Set Memory Range menu.
The Source Window command opens a window to show the source file of the debugged program.
If there is no valid debug file (see Appendix A), this window shows disassembled codes rather than the
source listing.
In the following source window, you will find breakpoint (B) and trigger (T) identifiers, line
number, program counter and opcodes.
Ver.98-01 95
Low-level Tooling System
Source <C:\rice65\as.asm>
A triangular mark always points to the next program counter or executable statement as indicated
by the PC field in the Register Window. Users can also scroll through the codes with the arrow keys and
bring the cursor (highlight bar) to any desired location. To move between the pages, use the [PgUp],
[PgDn], [Home] or [End] keys.
NOTE:
The Source Window will go blank when encountering an invalid program counter. When this happens,
check if you have specified the correct device type and if the program flow is correct.
The window will also be blank if you are debugging codes uploaded from external memory. In such a
case, open the ASM Window to see the referenced codes during debugging.
The ASM Window command opens a window, which displays disassembled codes when debugging
in C. When first, opened, the window is blank and will be updated upon the next emulation step. The
highlighted line in the ASM Window corresponds to the same instruction highlighted in the Source
Window.
ASM Code
C003-A9 FF LDA #FFh Open this window if you are
C005-85 00 STA 00h debugging codes uploaded from
C007-A9 00 LDA #00h external memory.
C009-85 02 STA DIRP2
C00B-EA NOP
C00C-85 70 STA have_line
Ver.98-01 96
Manual for 6502 Assembler
Displays the current contents of the program counter, the Processor Status (PS) register, the
Accumulator (A), the X and Y Index registers and the Stack Pointer (SP). You can change the hex
value of the registers by typing over them. To edit the codes, use the arrow keys to highlight the field
and type in the new value.
Register
PC C003
NV1BDIZC
PS B5 10110101
A FF 11111111
X FF 11111111
Y FF 11111111
SP FF
Displays the stack memory of the 65C02. This window can be sized to display the desired stack
locations.
Stack
01E0-00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
01F0-00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
The Watch Window command opens a Watch window displaying the values of watch variables
you defined using the Add Watch... Command. You can define watch variables only if a valid SYM file
is available.
Watch
buf_index<0071>=0000
fail<C0AE>=46
have_line<0060>=00
The Cycle Counter Window displays instruction cycle and elapse time information. The execution time
is based on the clock source specified under the OSC Frequency dialog box. You can reset the clock to
zero, start or stop the clock anytime by clicking the corresponding button.
Ver.98-01 97
Low-level Tooling System
Cycle Counter
Displays the contents of the 8Kx24-bit circular trace buffer board which records the real-time
executed instructions. The most recent instruction is found at the bottom of the buffer. The buffer
contains:
line number
data bus content or captured data on the eight external probes,
instruction cycle
address
opcode, and
the source or disassembled code.
Trace Buffer
Line Bus Cyc Addr Instruction Code
0001 FF 3 C02C-A5 70 lda have_line ;check
0002 00 2 C02E-Ea NOP
0003 F0 2 C02F-F0 E4 beg wait ;not do
0004 78 6 C015-EE F0 01 wait: INC TTTA
0005 DC 4 C018-AD F0 01 LDA TTTA
0006 DC 2 C01B-D0 0A BNE WAIT1
0007 EE 6 C027-20 90 C0 WAIT1: JSR TTLP
0008 C0 3 C090-48 TTLP: PHA
0009 DC 2 C091-70-0F BVS OVERFLOW
Trace buffer showing data bus contents
Trace Buffer
Line 8 7 6 5 4 3 2 1 Cyc Addr Instruction Code
0001 1 1 1 1 1 1 1 1 3 C02C-A5 70 lda have_line
0002 1 1 1 1 1 1 1 1 2 C02E-Ea NOP
0003 1 1 1 1 1 1 1 1 2 C02F-F0 E4 beg wait
0004 1 1 1 1 1 1 1 1 6 C015-EE F0 01 wait: INC TTTA
0005 1 1 1 1 1 1 1 1 4 C018-AD F0 01 LDA TTTA
0006 1 1 1 1 1 1 1 1 2 C01B-D0 0A BNE WAIT1
0007 1 1 1 1 1 1 1 1 6 C027-20 90 C0 WAIT1: JSR TTLP
0008 1 1 1 1 1 1 1 1 3 C090-48 TTLP: PHA
0009 1 1 1 1 1 1 1 1 2 C091-70-0F BVS OVERFLOW
Trace buffer showing external captured data
Ver.98-01 98
Manual for 6502 Assembler
You can scroll through the buffer using the arrow keys or by clicking the vertical bar with a
mouse. The contents can also be saved to a text file using the File | Save>>Trace Buffer... command.
Users can stop capturing data but keep the processor running once the buffer is full. This is
achieved through the Break | Set Breakpoints... | More Break>>Stop on Trace Buffer Full function.
The Verify Window displays the verification errors when comparing the contents of the program
memory inside the emulator against those in the memory buffer. If there is no error, the message “No
Verify Error” will appear.
Verify Window
ADDR DEVICE BUFFER
1004 00 01
3F00 1A AA
2-6-10 Search...
Unlike search functions from text editor, the Search function in RICE65 is based only on
information available in the SYM file. So search pattern is limited to address labels, program counters,
line numbers and instruction codes.
Search
Search Pattern: (*) Hexadecimal integer
( ) Decimal integer
( ) ASCII string
OK Cancel
The Search dialog box, as shown here, allows users to specify a data string to be searched in the
Source Window, Trace Buffer Window or Program Memory Window.
Input the data to be searched in the Search Pattern field and specify the format of the data: hex,
decimal or ASCII. Then specify the window to be searched and key for the search. Tab to OK to start
the search.
Ver.98-01 99
Low-level Tooling System
Examples
The Next Match command searches for the next match of the search string you specified in the
Search dialog box. This function applies to searching a repeated opcode inside the Trace Buffer and
Program Memory Windows but not to labels.
Ver.98-01 100
Manual for 6502 Assembler
The Run Menu contains different emulation control functions to execute your program. These
frequently used options can all be accessed globally via hot function keys.
The Reset Processor command resets the processor hardware. During the RESET conditions, the
interrupt mask flag is set, the decimal mode is cleared and the program counter is loaded with the restart
vector from location FFFC (low byte) and FFFD (high byte).
The Go from Reset command executes your program from the reset condition continuously until
either a breakpoint is encountered, or the program is interrupted with a keyboard or mouse entry.
2-7-3 Go
The Go command executes your program from the current Program Counter continuously until
either a breakpoint is encountered, or the program is interrupted with a keyboard or mouse entry.
2-7-4 From…
The From... command executes your program from the current Program Counter or new program
counter until it reaches the temporary breakpoint you specified in the dialog box. Note that the address
you specify may never be reached, depending on program logic.
Program Counter
From Program Counter: C000
To Break Address:
Go OK Cancel
The Go from Cursor commands executes your program from the instruction line at the cursor
position.
Ver.98-01 101
Low-level Tooling System
To select the new instruction line, press [F4] until the Source Window is active or click inside the
window. Click on the selected line or use the Up/Down arrow key to bring the highlight bar to the new
line to start the processor. To start running from this new program counter, press [Shift]-[F7].
2-7-6 To Cursor/Here
The To Cursor/Here command executes your program up to the currently highlighted source or
instruction line. Note that the address you specify may never be reached, depending on program logic.
The Single Step command executes a single instruction statement of your program. So if you press
[F8] three times, RICE65 will execute three statement. Single stepping allows you to examine register
data after each instruction.
If you are stepping codes uploaded from external memory, make sure to open the ASM Window to
display the referenced codes.
The ASM Single Step command executes a single machine instruction of your program. This is the
same as single step if your source code is in assembly language. When debugging in C, you can easily
switch between single step (in C) and ASM step by using the [F8] and [Sift]-[F8] keys.
The Step over Call command executes a single statement of your program and skips over any
function call. If the next executable statement is a function CALL instruction, pressing [F9] will step
over the subroutine being called (but fully executing it) and return to the line of the function.
This command is useful if you have stepped through enough of a function to determine that it is
working properly, and you wish to execute the rest of it without interruption.
The Return to Caller command is the same as single stepping except when inside a procedure or
function, this command will execute the rest of the procedure and return to the instruction of the
function.
2-7-11 Animate
The Animate command is a self-repeating Single Step command. Instructions are executed continuously
until a key is pressed. The RICE65 program displays changes to reflect the current program state
between each trace, which allows you to watch the flow of control in your program.
Ver.98-01 102
Manual for 6502 Assembler
The Animate Speed... command prompts you for the ate of delay at which instructions step.
Select the corresponding radio button for the speed desired or select user-defined speed. Press [Tab] to
OK and exit.
If you select user-defined speed, RICE65 will bring up a dialog box. Input the number from 0.1 to
99.9. Again, press [Tab] to OK and exit.
Animate Speed
Animate Speed
( ) Slow
(*) Medium
( ) Fast
( ) User-defined Speed
OK Cancel
When user-defined speed is selected, enter the relative delay time from 0-99 in the dialog box as
shown below. The actual speed depends on the speed of the PC host.
OK Cancel
Ver.98-01 103
Low-level Tooling System
Users can halt the processor at a specific or a range of program address within program memory.
RICE65 has a 12-clip Logic Probe. One of the clips is an External Break Input. The RICE65
software can be programmed to break when the External Break Input line sees a rising or falling edge. If
enabled, the processor will halt whenever the external break signal is latched. Users can specify to latch
the External Break Input on one of the followings:
Falling Edge
Rising Edge
To specify the External Break Trigger, go to the Break | Set Breakpoints>More Break>> dialog box.
RICE65 has an optional 8Kx24-bit ”circular” trace buffer, which logs real-time data. When the
buffer is full, new data will continuously be logged to the buffer starting at the very beginning. Users
can specify to halt the processor whenever the trace buffer is full, that is, when the trace buffer has
captured 8K data. This break will automatically be in force when forward trace option is enabled.
Found under Set Breakpoints>More Break>> menu, this allows users to halt the processor after an
instruction at a set breakpoint has been executed a particular number of times.
Found under the Break | Data Capture Break... menu, this function allows the processor to halt
when the value in the captured address matches the specified value. A mask value can also be entered
for special bit comparison.
NOTE: When the oscillator speed is above 1MHz, the Multiple Break and Data Capture Break may
execute several more instructions prior to breaking.
Ver.98-01 104
Manual for 6502 Assembler
Once the user has defined an address range for read only memory, the processor will halt whenever
the referenced address is being written to.
Access the Break Menu at any time by pressing the [Alt]-[B] hot key. The menu has several
options to let you add, delete, modify, toggle and clear breakpoints. Set breakpoints are marked with a
“B” rather than a “.” in the first column of the Source Window. You can also enable External Break
Input via the Break Menu.
This command leads to the Set Breakpoint” dialog box which allows you to add, delete, modify or
clear all breakpoints. Each breakpoint can be a specific address or an address range. Enter the address
range in the Start and End fields, tab to the Add button and press [Enter] to add. The addresses will
appear in the list box.
Set Breakpoints
Set Break Range:
Start:
End:
Modify
Clear All
More Breaks>>
OK Cancel
To disable a set break address, press [Tab] to highlight the list box. Use the up/down arrow key to
highlight the address range and press [Enter]. The “√“ mark will turn into “x”, indicating the disabled
status. To delete a set break address, tab to the list box, use the up/down arrow key to highlight the
range and press [Tab] to Delete and then press [Enter]. The address will be removed from the list box.
To modify an address range, highlight the range in the list box. Press [Tab] to Start and End fields
and input the new values. Press [Tab] again to Modify, press [Enter] and the specified range will be
updated.
Ver.98-01 105
Low-level Tooling System
Clicking the More Break >> button in the “Set Breakpoint” dialog box will bring up the “More Break”
dialog box as shown below.
More Break
External Break Trigger:
(*) Falling Edge
For Multiple Break Count,
( ) Rising Edge you can enter any integer
from 1- 2047.
Trace Buffer:
[ ] Break when Trace Buffer Full
Multiple Break:
Multiple Break Count:
[ ] Enable Multiple Break Function
OK Cancel
The More Break dialog box allows you to set up the External Break condition, either on rising or
falling edge, as well as to enable break upon trace buffer is full. It also allows you to specify the
multiple break count. Use the [Tab] key to select groups and within groups, use the up/down arrow keys
to select option. To confirm the selection, press the [Spacebar].
NOTE: For multiple breaks, the program may overrun some extra instructions and not break at the
exact location when the oscillator frequency is over 1Mhz.
The Toggle Breakpoint command provides a quick and easy way to set or clear a breakpoint
without going through a dialog box. By simply pressing the [F2] key, users can set the currently
highlighted source line in Source Window to be a break address. To clear a set breakpoint, press [F2]
again. A “B” in the first column of the Source Window indicates set breakpoints.
The Clear All Breakpoints command removes all previously defined breakpoints. Use this
command when you want to continue debugging your program but no longer want it to stop at any
previous set breakpoint locations.
The Data Capture Break... command allows you to setup the real-time conditional break. If the
data inside the Data Capture Address equals to the compare value ANDed with the mask value,
RICE65 will generate a break to halt the processor.
Ver.98-01 106
Manual for 6502 Assembler
Data Capture
Capture Address: 0000
Mask Value: FF
Compare Value: 00
[ ] Enable Data Capture Function
OK Cancel
Input the value in the Capture Address and press [Tab] to go to the next fields. Press [Spacebar] to
enable the function and press [Tab] to OK and exit.
NOTE: Since the Data Capture and Cycle Counter functions share the same hardware, the Cycle
Counter Function will be disabled when the Data Capture Function is enabled and vice versa.
This sets the Start and Stop Address for the Cycle Counter and provides the execution time when
running codes between the addresses. When the Start Address is reached, the cycle counter will be
cleared and started until the Stop Address is encountered. the counter will then stop and display the
elapse time in the Cycle Counter Window.
Cycle Counter Address
OK Cancel
The Set Trigger Points... command allows you to setup the trigger output address ranges. When an
instruction is qualified for trigger output, the trigger output line on the external logic probes generates a
positive pulse. This line can be used to:
trigger an oscilloscope when the processor executes an instruction at a particular address
trigger other logic or instruments
Ver.98-01 107
Low-level Tooling System
connect to the External Break Input (BRK) of another RICE65 to provide cross triggering on
multiple emulators. In this case, the processor in the other emulator will halt.
NOTE: To halt the processors in both emulators, connect the Break Output line of Emulator1 to the
External Break Input line of Emulator2. Emulator1 will halt and send a break signal to Emulator2,
halting its processor.
This command leads to the “Set Trigger Points” dialog box. It allows users to input a specific
address or an address range for trigger outputs. Enter the address range in the “Start” and “End” fields,
tab to the Add button and press [Enter] to add. The address will appear in the list box. To disable a
trigger address, press [Tab] to highlight the list box. Use the up/down arrow key to highlight the address
range and press [Enter]. The “√” mark will turn into “x”, indicating the disabled status.
Set Trigger Points
Set Address Range:
Start:
End:
Modify
Clear All
OK Cancel
To delete a trigger address, tab to the list box, use the up/down arrow key to highlight the range
and press [Tab] to Delete and then press [Enter]. The address will be removed from the list box.
To modify an address range, highlight the range in the list box. Press [Tab] to the “Start” and “End”
fields and input the new values. Press [Tab] again to Modify press [Enter] and the specified range will
be updated.
It is much easier to move around the dialog box with a mouse. Just click on any item with the left
mouse button instead of pressing [Tab] to cycle through the different elements. Trigger points are
indicated by a “T” rather than a “.” in the second column of the Source Window.
The Set Trigger Points can also be used with the Real-time Trace function to save interested address
ranges to the trace buffer. Set the address in the Set Trigger Points dialog box as described and then go
to Trace | Set Trace Range and enable “Real-time Trace”.
The Clear All Triggers command removes all previously set trigger points. All trigger output indicators
“T” in the Source Window will turn to “.”.
Ver.98-01 108
Manual for 6502 Assembler
The Add Watch... command places the variable on the watch list displayed in the Watch Window
and continuously updates its value. The command leads to an Add Watch dialog box where you can
select available variables from a symbol list to watch.
Add Watch
Add OK Cancel
First, use the Up/Down arrow key to highlight the variable to be watched. Press [Tab] to specify
data type and then press [Tab] to Add. Repeat the same procedure to specify more variables. When
ready, press [Tab] to the OK button and exit.
The Delete Watch.. command leads to the dialog box where you can remove watch variables from the
Watch Window. Highlight in the list box the variable to be removed, press [Tab] to go to the Delete
button and press [Enter]. To clear all the watch variables, press [Tab] to highlight the Clear All button
and press [Enter].
Watch Variable
Watch Variable: eos
eos Delete
have_line
inp_buffer Cancel
Clear All
Ver.98-01 109
Low-level Tooling System
The Clear All Watches command removes all watch variables from your program. The contents of
the Watch Window will be cleared once the command is issued.
The Modify Memory command allows you to read (inspect) or write (modify) the contents of
Program Memory. It leads to the dialog box as shown below.
Modify Memory
Address:
Data:
Data Format:
(*) Hex
( ) Dex
( ) Binary
( ) ASCII
Read Write
The Modify function can also be achieved by typing the new value directly in the appropriate window.
Ver.98-01 110
Manual for 6502 Assembler
line number
data bus content or captured data on the eight external probes (via the Options | Trace Options
menu),
instruction cycle
address
opcode, and
the source or disassembled code (via the Options | Trace Options menu).
The trace buffer will automatically records the above data as program codes are executed. You can
also specify special tracing under the Trace | Set Trace Range... Menu. Working together with the
breakpoint system, the trace buffer contains valuable information for debugging.
The Read Trace Buffer command uploads the trace buffer data from the RICE65 hardware and
displays them in the Trace Buffer Window. The circular trace buffer can hold up to 8Kx24-bit of
information and 8K instructions. The last executed line is highlighted with a “>“ mark for easy
reference.
The Trace Buffer can be set to record either Data Bus Contents or logic states captured from the
eight external probes as illustrated below:
Trace Buffer
Ver.98-01 111
Low-level Tooling System
Trace Buffer
Line 8 7 6 5 4 3 2 1 Cyc Addr Instruction Code
0001 1 1 1 1 1 1 1 1 3 C02C-A5 70 lda have_line
0002 1 1 1 1 1 1 1 1 2 C02E-Ea NOP
0003 1 1 1 1 1 1 1 1 2 C02F-F0 E4 beg wait
0004 1 1 1 1 1 1 1 1 6 C015-EE F0 01 wait: INC TTTA
0005 1 1 1 1 1 1 1 1 4 C018-AD F0 01 LDA TTTA
0006 1 1 1 1 1 1 1 1 2 C01B-D0 0A BNE WAIT1
0007 1 1 1 1 1 1 1 1 6 C027-20 90 C0 WAIT1: JSR TTLP
0008 1 1 1 1 1 1 1 1 3 C090-48 TTLP: PHA
0009 1 1 1 1 1 1 1 1 2 C091-70-0F BVS OVERFLOW
The Clear Trace Buffer command clears the contents of Trace Window and reset the trace pointer.
The Set Trace Range... command lets you set the program counter address to begin capturing real-
time data in the trace buffer. You are prompted for the Start and End trace address in the pop-up dialog
box.
Trace Range
Trace Address Range
Start: 0000
End: 0000
OK Cancel
This is the default trace mode, saving all executed instructions in the 8K buffer and throwing away
old ones. The last executed instruction will be found at the bottom of the buffer. It is not necessary to
input an address range for this trace.
Ver.98-01 112
Manual for 6502 Assembler
You are required to enter the Start and End address for this option. The emulator will clear the
buffer upon reaching the Start, start-capturing data until the End Address at which a breakpoint has
been set internally. To view the data, use the Upload Trace command.
In this option, the processor will keep running while data within the address range will be
repeatedly captured to the buffer. You can also enter multiple address ranges to be traced. To do so, go
the Break | Set Trigger Points Menu and select the addresses as trigger address and then enable “Real-
time Trace” in the Trace | Set Trace Range Menu.
The Forward Trace will start capturing data from the Start address and the processor will break if
the trace buffer is full. This prevents the Start Address from being overwritten by the circular buffer.
Note that if the Start Address is within a loop and keeps repeating, only one instance will be saved to
the trace buffer. The processor will keep running. In such case as the buffer is not full to cause a break.
Ver.98-01 113
Low-level Tooling System
2-11-1 Configuration...
The Configuration... command leads to the “Configuration” dialog box where users can specify the
device to be emulated.
Configuration
Device:
(*) 65C02
( ) 6502
OK Cancel
If you have a mouse, just click the item you want to choose. Select OK to accept the settings and
Cancel to cancel the changes.
The OSC Frequency... command allows users to specify the source of the oscillator for emulation.
OSC Frequency
Oscillator Source:
( ) External
(*) Internal
8000.000
4000.000 OK
2000.000
1000.000
250.000 Cancel
52.500
31.250
Ver.98-01 114
Manual for 6502 Assembler
When external source is selected, users need to connect a crystal or provide an oscillator input to
the “EXT XTAL” socket on the RICE65 motherboard (please refer to page 6). The frequency input is
for the cycle counter to calculate elapse time.
For internal source, users can select from a range of available frequencies, from 31.25KHz to
8MHz as show in the list box.
Within the dialog box, use the up/down arrow key to select oscillator source and press [Spacebar]
to confirm. To specify the frequency for the internal source, press [Tab] to go to the list box and use the
up/down arrow key to scroll through the list and then press [Enter] to select the frequency and exit.
If you have a mouse, just click the item you want to choose. Select OK to accept the settings and
Cancel to cancel the changes
The LPT Port... command lets you override the default setting on the parallel port address detected
by the RICE65 program. You can specify 378h, 278h or 3BCh. Use the arrow key to pick an alternate
port address and press [Spacebar] to confirm. Tab to OK and exit.
OK Cancel
An incorrect LPT port will cause communication error and incorrect emulation results. If you get a
warning message, make sure:
the parallel adapter cable is properly connected to the parallel port and to the RICE65 unit
power is supplied to the RICE65 unit which undergoes the power-up self test properly (the LED
blinks several times)
The Driver Time-delay constant enables RICE65 to work with fast PC if it fails communication. In
such a case, enter a constant from 5 to 50, in increments of 5 and then 100 to 500, in increments of 50.
If the RICE65 fails to communicate with your PC, please contact our support teams.
Ver.98-01 115
Low-level Tooling System
The Display Option... command allows you to select the number of lines to display on screen, the
setting of the PC speaker and to specify the tab size in the Source Window. The tab size is a decimal
field and you can enter a value up to 20. The default setting is 8.
Display Options
Screen Line: PC Speaker
(*) 25 (*) On
( ) 43/50 ( ) Off
Tab Size: 8
OK Cancel
NOTE:
The System | Restore command does not reset the screen line to 25. It only restores the screen to
the way the program starts, that is, with the Source, Program Memory and Register as the three open
windows.
The Trace Option... command allows you to specify if the trace buffer would contain disassembled
or source codes and the capture data from the Data bus or from the 8 external probes.
Trace Options
OK Cancel
To select, press [Tab] to select among the two groups and the buttons. Within each group, use the
Up/Down arrow keys to select and press [Spacebar] to confirm. Once selection is made, press [Tab] to
OK and press [Enter] to exit.
Ver.98-01 116
Manual for 6502 Assembler
This command sets the different memory range for debugging. It leads to the dialog box as shown
below.
Memory Address Range
Clear All
OK Cancel
To set Memory Range, enter the Start and End address in the Edit box, click the desired Memory
Type and click the Add button. The Memory Type is initialized as U, X and R in the list box.
In the dialog box above, address 1001 to 101F is set as Read-only memory while address 2100 and
2200 is set as both Updated Memory and External Memory. That is, RICE65 will fetch data from
external memory for range 2100 and 2200 and also update their value in the Program memory window
for each single step. To modify memory range, highlight the range in the list box, click the different
Memory Type and/or change the Start/End address. When done, click the Modify button.
To temporarily disable a range, highlight the range in the list box and press [Enter]. The check
mark will change to a cross (x), indicating the disable status.
The Update Memory Range is the address range in program memory, which will be updated after
each Run command. Besides the Update Memory range, RICE65 will also update the program memory
from 0 to 0x1FF and the visible range in the Program Memory Window after each Stepping or Go
command.
Ver.98-01 117
Low-level Tooling System
The External Memory Range is the address range of the external memory, such as I/O mapping
memory. If the external memory range is set, RICE65 will fetch the data from external memory for
those address location.
The Read-Only Memory Range is the address range in program memory to be read-only so that the
data inside those address locations will not be destroyed.
If this is defined, RICE65 will halt when the program tries to write to this address range.
Fill Cancel
Enter the Begin and End address of the memory block and then the new value, which is used to fill
the locations. Press [Tab] to Fill and [Enter] to exit. The new value will be updated in the Program
Memory Window if the range is with the Update Memory, from 0-1FF or within the visible range.
The Save Setup... command saves the RICE65 debug environment settings to an editable text file.
You are prompted for the filename. You can enter any name but are recommended to use the same root
name as the corresponding object file with a .SET extension. This enables the setup to be restored
whenever you load the object file to debug.
Ver.98-01 118
Manual for 6502 Assembler
The Restore Setup... command allows you to load a setup file previously saved using the Options |
Save Setup... command.
Ver.98-01 119
Low-level Tooling System
Appendix A
RICE65 currently supports source level debugging on assembler and C compiler from 2500AD.
More assemblers/compilers will be supported in the future. Please contact Advanced Transdata or
NOVATEK Microelectronics Corp. for more details.
2500AD Assembler/Compiler
Both .lnk files have specified the options: map, high level, Intel hex. Please refer to the 2500AD
manuals.
WDC/Zardox Assembler
For the WDC/Zardox assembler, RICE65 uses the WDC/Zardox symbol format for source level
debugging. Make sure to use the following command when compiling:
If only a hex file is available, the file will be disassembled and displayed in the Source Window.
Ver.98-01 120