Index
6502 Software Development Kit

v. 1.0 BETA  -  ©1996 by Valerio Gionco

6502SDK is an integrated development environment for writing and testing machine language code for 65xx based machines.

The kit includes:

-	multi-file text editor;

-	assembler with macro capabilities;

-	project manager;

-	software emulator for the processor, that allows you to run and trace your code, set breakpoints, watch variables and memory, ...

-	a disassembler for object code;

- 	some other stuff I won't discuss here.

... and all that is FREE!.  If you have a Commodore 64, a VIC-20, an old Apple, or any other machine and you still spend time programming them, you'll save a lot of time.

The integrated assembler supports macros with parameters and local labels, file inclusion, N-level forward referencing, and all what I was able to imagine. (However, only 6502 documented  opcodes are supported.

Assembly language

Editor

Emulator

Object disassembler

Memory dump

Register window

Stack

Variable watch

Legal stuff

Acknowledgments

Contacting the Author

Commodore 64 and VIC-20 are trademarks of Commodore Electronics Ltd.

Apple is a trademark of Apple Computers Ltd.


Assembly language
6502 assembly language.

Syntax

Opcodes

Operands

Directives

Scope rules


Assembly syntax

Each line of code must be a statement, in the form:

[label] opcode [operand] [comment]

or may consist in:

-	a processor directive

-	a pre-processor directive (always starting with '#' )

-	a macro call;

-	a comment, a label or a blank line.

Labels are identifiers followed by ':'.  Note that labels are symbols whose value is assigned at compile time: you are allowed to use them anywhere.

Comments begin with ';' and terminate with the line.

Example:

;the following lines are valid

lda	#$00	;this is a valid line

rts	;this is another valid line

; this is a comment

;

label1: jmp $ff00  ;this is a line with label

label2:

label3:

inx	   ;note that 'label2' and 'label3' have the same value.

inc	label1  ;WITHOUT ':' !!!!

rts

Note:	I'm sorry, but you MUST put a ':' before labels. I don't like this myself (in fact the first version of the assembler used the label alone) but there was a problem: I had no way do distinguish between a label and a wrong-typed opcode. For instance, if you write "RTZ" instead of "RTS", the effect is to eliminate the instruction (that might cause catastrofic effects) because the assembler thinks "RTZ" to be a label.


Assembly opcodes
6502 Assembly opcodes

Currently, the assembler only supports 6502 documented opcodes. Opcodes may be either in capital letters or not (the assembler is always case-insensitive for opcodes).

Note that you already are supposed to know 6502 assembly language.

Valid opcodes are:

ADC  AND  ASL  BCC  BCS  BEQ  BIT  BMI  BNE  BPL

BRK  BVC  BVS  CLC  CLD  CLI  CLV  CMP  CPX  CPY

DEC  DEX  DEY  EOR  INC  INX  INY  JMP  JSR  LDA

LDX  LDY  LSR  NOP  ORA  PHA  PHP  PLA  PLP  ROL

ROR  RTI  RTS  SBC  SEC  SED  SEI  STA  STX  STY

TAX  TAY  TSX  TXA  TXS  TYA


Assembly operands

The operand must be:

-	the A register (as in  ASL A )

-	a constant expression. (as in LDX $1000 )

-	a constant expression and the X or Y register, following the addressing rules for the 6502 (as in LDX $1000,X )

All expressions MUST resolve to a constant in compile time, and may be surrounded by parentheses to indicate indirect addressing.

Allowed addressing modes vary from instruction to instruction.  Here is a complete list of modes:

nn :	8-bit constant

nnnn :	16-bit constant

mode	example	bytes used

immediate	LDA #nn	2

absolute	LDA nnnn	3

page zero	LDA nn	2

accumulator	ASL A	1

implied	RTS	1

indexed indirect	LDA (nn,X)	2

indexed	LDA (nn),Y	2

page zero, X	LDA nn,x	2

page zero, Y	STX nn,y	2

absolute, X	LDA nnnn,x	3

absolute, Y	LDA nnnn,y	3

indirect	JMP (nnnn)	3

relative	BNE (nnnn)	2


Assembly expressions
Expressions

Expression must resolve to constants at compile time.  You are not allowed to write expressions like n=3*A (where A is the accumulator register), because this makes no sense.

Numeric constants are assumed to be:

-	Hexadecimal if beginning with '$' ;

-	Octal if beginning with '@'

-	Binary if beginning with '%'

-	Decimal otherwise.

To assign an expression to a symbol, simply use the EQU directive or the '=' sign:

n  EQU  3*$100

is equivalent to:

n  =  3*$100

You can use expressions in every place you should put a constant operand. For example, you can write:

addr_l	equ	$1000

addr_h	equ	addr_l+1

ncycles	equ  10

value	equ	%01001011

label1:	ldx	ncycles *2

sta  (addr_l),X

dex

sta	(addr_h),X

dex

bne	label1

Note that label1 is a label (and is followed by ':' ), and addr_l, addr_h, ncycles, value  are symbolic constants (NOT followed by '':' ).

Operators

8- and 16-bit operations

Forward references


Assembly operators
Operators

You can use the following operators:

arithmetic operators:	+

-

*

/

logical operators:

|	bitwise OR

&	bitwise AND

!	bitwise NOT

others:

<	low byte

>	high byte

You can also use parentheses to override operator precedences.


8- and 16-bit operations

The constants you calculate can only be 8- and 16-bit wide. A numeric constant N is assumed to be 8-bit wide if  (and only if! ):

N<256 and length(N)<=8	for binary (%) numbers;

N<256 and length(N)<=4	for octal (@) numbers;

N<256 and length(N)<=2	for hex ($) numbers;

N<256 	for decimal numbers.

So, if you want to write a lda to location $0020 using 16-bit addressing mode, you must write

lda $0020

instead of

lda $20

Character constants are always 8-bit.

The width of operation results is:

for arithmetic operators:	always 16 bit;

for bitwise AND (&) and OR (|)	8 bit if both operands are 8-bit; 16 bit otherwise;

for bitwise NOT (!)	the same of the operand;

for <  and  >	8 bit.

Note that all calculations are made with UNSIGNED numbers, and you must take care about overflows and underflows.

Note also that if the size of a forward-referenced operand is unknown, the assembler forces it to be 16 bit because he needs to calculate instruction widths immediately. So, if you want to force an operand to be 8-bit wide, you must use the '<' operator to take only the low byte.


Forward references

Symbolic constants may be forward-referenced. This means that you can build an expression making use of other constants that are yet undefined.

For example, the following code is correct:

label4:	nop

lda	#$00

sta	const2

rts

const2	equ	const3+1

const3	equ	<label4

Be careful not to create circular references inside your code :

var1	equ	var2+1

var2	equ	10*var3

var3	equ	var1	;<--- ERROR: var1 depends from var3!!

The only exception to the use of forward references is the ORG directive.


Directives

Assembler directives:

ORG

DB, DW and DD

EQU and '='

Preprocessor directives:

#include

#macro ... #endm


ORG directive

Before assembling your code, you must specify the start address for object using the ORG directive:

org [startaddress]

where startaddress must be a known constant (no forward references!).

If you dont't use the ORG directive, the compiler provides for you a default start address.


DB, DD and DW directives
DB, DW and DD directive

Those directive reserve some space at the current location:

DB	argument [, argument, ...,argument]

assembles a byte for each entry in the argument list;

DW	argument [, argument, ...,argument]

assembles a word for each entry in the argument list, in low-high order;

DD	argument [, argument, ...,argument]

assembles a word for each entry in the argument list, in high-low order;

For example:

ORG	$1000

DB	$12, $34, $45, $67

DW	$1234, $5678

DD	$9876, $8877

generates the following object code:

$1000>   12 34 45 67 34 12 78 56 98 76 88 77

The DB directive also allows to assemble ASCII strings, one byte for character. For example:

DB "abcdefg"

writes in memory the string "abcdefg".  You can also used mixed syntax, like:

DB "String", 'c', h', 'a', 'r', $10, %0100100, @67


EQU and '='

You can use EQU or '=' to define symbols. The syntax is

symbol  EQU  expression

or

symbol  =  expression

where symbol must be a valid symbol ( A-Z, a-z, 0-9 , not beginning with a digit). The maximum length for a symbol is 32 characters.

You can use forward-referenced expressions (see forward reference).


#include directive

You can include another file inside your code by writing:

#include "filename"

When the assembler finds this directive, it starts assembling the included file, then it gets back to the main file. File inclusion can be nested one inside another with a maximum depth of 10 levels. Be careful to avoid circular inclusions.


Macro processing

The assembler allows macro definitions. Note that a macro is NOT a procedure, and its code is copied in every point the macro is instanced. Macro is just a lexical operation that substitutes the macro call with his body.

The syntax for defining a macro is:

#macro [ [param1 [, param2, ..., paramN] ] ]

[body of the macro]

#endm

The macro may have N parameters param1,...,paramN that you can use to pass a string to the macro. Not that parameters are strings: they are copied "as they are" inside the code.

The names defined inside a macro are local names, and cannot be used outside the macro itself. If a name in a macro is equal to an external name, the local name takes precedence over the external one.

You are always allowed to call a macro inside a macro definition, but macros cannot call themselves. You also cannot call a macro that has not been defined yet.

Example:

;macro without parameters

#macro black

lda #$00

sta $d020

sta $d021

#endm

;macro with 3 parameters

#macro addition[op1, op2, result]

lda op1

clc

adc op2

sta result

#endm

;now let's call the macros:

org $c000

black

addition [$20, #$10, var];  var = $20 + #$10

rts

;holds space for the result

var	db 0


Scope rules for identifiers
Scope rules for identifiers.

Remeber the following rules:

An included file is part of the main file. Identifiers defined and/or used in the included files follow the same rules of those in the main file.

Identifiers defined outside macros can be used anywhere in the file;

Identifiers defined inside a macro can only be used inside the macro itself;

Maybe in a future I will add external names declarations.


The editor

For editing a source file, you can use an external text editor or the internal editor. The internal editor has some limitations, but it allows to compile the source code directly, by pressing  ALT+F9.

The internal text editor cannot manage files larger than 32K (but you can use #include to join files) and allows standard cut-copy-paste operations.


The emulator

6502SDK includes a software emulator for 6502 processor. Emulating a processor via software is not a difficult job, but it's necessary a complete knowledge on how the whole thing works.

There are still a lot of obscure points in 6502 (for me, at least). For example:

How does decimal mode works exactly, especially when operands are NOT valid BCD numbers?

When the processor encounters an undocumented opcode, what it really happens? Somebody says that newer (CMOS) versions of 6502 ignore those opcodes and execute NOP instead. But do they fetch operands or not?

I have a Commodore 64 with a 6510. Do 6502 instructions (and bugs...) are the same of the 6510?

I didn't want to build a perfect emulator. So I didn't care about undocumented opcodes and I tried to emulate some 6510 bugs, hoping that 6502 would behave in the same way.

The emulator includes a 64K memory, the registers and an object code interpreter.  The stack doesn't need to be emulated because in real 6502 it is located in main memory (from $0100 to $ 01FF). Maybe one day I'll add the emulation code for 6510 I/O port located in $0000 - $0001.

You are allowed to do everything you might need to test and debug your code:

step-by-step execution;

breakpoints insertion;

register value change (including ALL registers and flags);

RESET, IRQ, NMI simulation;

variables inspection, and so on...


The object disassembler
The object disassembler/debugger.

The disassembler allows to examine assembler code for programs resident in the emulator memory. You can also follow the program flow in step-by-step execution (F7) and place breakpoints (by double-clicking with the mouse on the line where you want the breakpoint to be set or eliminated).

Note that disassembling an object code sometimes gives ambiguous results. For example, if you have the following source code:

ADDRESS	 CODE        OBJECT

$1000:     LDA #$A2    A9 A2

$1002:     STA $60EA   8D EA 60

and you disassemble it from $1001 instead of $1000, you will find the following code:

$1001:     LDX #$8D    A2 8D

$1003:     NOP         EA

$1004:     RTS         60

The actual position of the Program Counter is marked with '>>', and breakpoints are evidenced in red. You can use the vertical scrollbar to move the disassembling window.

When the disassembler finds a byte that does not represents a valid opcode, it marks it with '???'.


The memory dump
Memory dump

You can watch what happens to memory in the Memory window. This window allows you to examine memory (in hexadecimal and ASCII).

Unprintable ASCII characters are represented with '.' .

You can perform some operations (like Fill, Copy, Go To...) with the right mouse button.


The registers window
Registers window

This window allows you to read and modify the contents of 6502 registers.


The stack window
Stack window

In this window you can see the contents of the stack area. The line at the top of the window is the one pointed to by SP.

Note that, for 6502, stack area is always from $0100 to $01FF.


The watch window
Watch window

6502SDK allows you to observe the value of your variables. In the watch window you can see a list of your watch expressions, the corresponding memory location and the value stored in the location.


Legal stuff

The program is free software: you can copy it freely (you are welcome to do so!) but you CANNOT make money out of it. Be warned: if you'll ask money for this software I'll get VERY MAD! (ah, ah...).

If you use the program, you are asked to send a postcard to my address (see "contacting the Author) just to track the spreading of 6502SDK.

You should have received a copy of the GNU General Public License along with this program: here you can find all the legal stuff I cannot write.

Here are reported GNU warranty disclaimers:

    NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY

FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN

OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES

PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED

OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF

MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS

TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE

PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,

REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING

WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR

REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,

INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING

OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED

TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY

YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER

PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE

POSSIBILITY OF SUCH DAMAGES.


Acknowledgements

The integrated assembler of 6502SDK has been written using GNU programs FLEX and BISON, included in DJGPP compiler distribution. Thanks to Robert Corbett and Richard Stallman (for BISON) and to Vern Paxson (for FLEX).

Some notes about 65xx decimal mode have been released on the Net by:

-  John West (john@ucc.gu.uwa.edu.au)

-  Marko Mäkelä    (msmakela@kruuna.helsinki.fi)

Thanks also to Ville Muikkula for C64CONNECT (the fastest utility to transfer data from/to a C64 I've ever tried) and to Wolfgang Lorentz and Miha Peternel for PC64 and C64S.


Contacting the Author

You can send E-mail to s74454@cclix1.polito.it but I think will be deleted in a future (perhaps before 1998).

You can send postcards (but also letters, money, food, wine, everything...) to:

Valerio Gionco

26, viale Europa

14022 Castelnuovo Don Bosco (Asti)

ITALY