|Welcome To the Dark
Side!... I grew up with the Amstrad
CPC, and I started learning Assembly with the Z80, however as my
experience with Z80 assembly grew, I wanted to start learning about
other architctures, and see how they compared!
The 6502, and it's varients powered many of the biggest systems from the 80's and 90'... From the ubiquitous C64... to the Nintendo Entertainment System, as well as the BBC Micro, PC-Engine and Atari Lynx... even the Super Nintendo used a 16 bit varient of the 6502 known as the 65816
The 6502's origins are somewhat odd, a cost reduced version of the 8-bit '6800' (which was the predecessor to the venerable16-bit 68000)... the 6502 sacrificed some functions for a cheaper unit price, which allowed it such wide support... the 6510 which powered the C64 had a few added features...
A later version, the 65C02 added more commands (Used in systems like the Apple IIc and the Atari Lynx) ... and HudsonSoft made a custom version of the 65C02 with even more features, called the HuC6280 and exclusively used in the PC Engine
All these CPU variants are 8 bit, and the basic 6502 command set works in the same way on all these sysems, and it's that instruction set we'll be learning in these tutorials...
These tutorials will be written from the perspective of a Z80 programmer learning 6502, but they will not assume any prior knowledge of Z80, so if you're starting out in assembly, these tutorials will also be fine for you!
The 65C02 die
you want to learn 6502 get the Cheatsheet!
it has all the Z80 commands, and useful info on the CPC, Spectrum and
It will give you a quick reference when you're stuck or confused - and it's what the author used to develop ChibiAkumas!
Print it in color at high resolution on 2 sides of A4 for maximum performance!
probably think 64 kilobytes doesn't sound much when a small game now
takes 8 gigabytes, but that's 'cos modern games are sloppy,
inefficient, fat and lazy - like the basement dwelling losers
who wrote them!!!
6502 code is small, fast, and super efficient - with ASM you can do things in 1k that will amaze you!
will use a symbol to denote a hexadecimal number, some use $FF or #FF
or even 0x, but this guide uses & - as this is how hexadecimal
represented in CPC basic
All the code in this tutorial is designed for compiling with WinApe's assembler - if you're using something else you may need to change a few things!
But remember, whatever compiler you use, while the text based source code may need to be slightly different, the compiled "BYTES' will be the same!
|Digit Value (D)||128||64||32||16||8||4||2||1|
|Our number (N)||1||1||0||0||1||1||0||0|
|D x N||128||64||0||0||8||4||0||0|
|128+64+8+4= 204 So %11001100 = 204 !|
|If you ever get confused, look
at Windows Calculator, Switch to
'Programmer Mode' and it has binary and Hexadecimal view, so
change numbers from one form to another!
If you're an Excel fan, Look up the functions DEC2BIN and DEC2HEX... Excel has all the commands to you need to convert one thing to the other!
|Equivalent Byte value||255||254||253||251||246||236||206||2||1|
|Equivalent Hex Byte Value||FF||FE||FD||FB||F6||EC||CE||2||1|
these number types can be confusing, but don't worry! Your Assembler
will do the work for you!
You can type %11111111 , &FF , 255 or -1 ... but the assembler knows these are all the same thing! Type whatever you prefer in your ode and the assembler will work out what that means and put the right data in the compiled code!
|Compared to the Z80, two things are apparent about the
the stack pointer is only 8 bit... and secondly we have very few
The way the Stack pointer works is simple... the stack is always positioned beween $0100 and $01FF... Where xx is the SP register, the stack pointer will point to $01xx
The 'solution' to the lack of registers is special addressing options... the first 256 bytes between &0000 and &00FF are called the 'Zero Page', and the 6502 has many special functions which allow data in this memory range to be quickly used with the accumulator and other functions as if they were 'registers'!
|Mode||Description||Sample Command||Z80 Equivalent||effective result|
|Implied / Inherant||A command that needs no paprameters||SEC||SEC (set carry)||SCF|
|Relative||A command which uses the program counter PC with and offset nn (-128 to +127)||BEQ #$nn||BEQ [label] (branch if equal)||JR Z,[label]|
|Accumulator||A command which uses the Accumulator as the parameter||ROL||ROL (ROtate bits Left)||RLCA|
|Immediate||A command which takes a byte nn as a parameter||ADC #$nn||ADC #1||ADC 1||&nn|
|Absolute||Take a parameter from a two byte memory address $nnnn||LDA $nnnn||LDA $2000||LD a,(&2000)||(&nnnn)|
|Absolute Indexed||Take a parameter from a two byte memory address $nnnn+X (or Y)||LDA $nnnn,X||LDA $2000,X||(&nnnn+X)|
|Zero Page||Take a parameter from the zero page address $00nn||ADC $nn||ADC $32||(&00nn)|
|Zero Page Indexed||Takes a parameter from memory address $00nn+X||ADC $nn,X||ADC $32,X||(&00nn+X)|
|Indirect||Take a parameter from pointer at address $nnnn...
if $nnnn contains $1234 the parameter would come from the address at $1234
|JMP ($1000)||LD HL,(&1000)
|Pre Indexed (Indirect,X)||Take a paramenter from pointer at address $nnnn+X
if $nnnn contains $1234, and X contained 4 the parameter would come from the address at $1238
|ADC ($nn,X)||ADC ($32,X)||((&00nn+X))|
|Postindexed (Indirect),Y||Take pointer from address $nnnn, add Y... get the
parameter from the result
if $nnnn contains $1234, and Y contained 4, the address would be read from $1234... then 4 would be added... and the parameter would be read from ther resulting address
|ADC ($nn),Y||ADC ($32),Y||((&00nn)+Y)|
|12345||(16384)||decimal memory address|
|$||$4000||(&4000)||Hexadecimal memory address|
|6800 command||Meaning||6502 alternative|
|ADD #5||ADD a number without carry||CLC (Clear carry for add)
ADC #5 (Clear carry)
|SUB #5||Subtract a number without carry||SEC (Clear carry for sub)
SBC #5 (Clear carry)
|NEG||convert positive value in Accumulator to negative value in Accumulator||EOR #255 (XOR/Flip bits)
SEC (Clear carry)
ADD #1 (add 1)
|SWAP A||Swap two Nibbles in A||ASL (shift left - bottom bit zero)
ADC #$80 (pop top bit off)
ROL (shift carry in)
ASL (shift left - bottom bit zero)
ADC #$80 (pop top bit off)
ROL (shift carry in)
|INC (inc de)||DEC (dec de)||ADD (add bc to hl)||SUB|
| INC z_E
| INC z_E
| lda z_l