6502 assembly language is one of my greatest unfinished projects from yesteryear. I dabbled in it, but never fully grasped it’s complexity at the time. I think primarily because I had been cutting my teeth in Basic and honing my logic programming skills. At the time I wasn’t ready for assembly, though I wanted to be.
Now, I set out to complete my understanding and ability to program the 6502 micro processor in assembly, specifically on the Atari 8 bit computer. Is this useful in todays world? Maybe not, but I imagine some of the concepts are transportable to other computer languages, skills, or computer hardware. Or maybe I’ll use the new fangled skills to create a Homebrew game. We’ll see!
As I start into learning 6502 assembly I first looked into how the processor works and what it is capable of, in conjunction with actual assembler syntax. To do this I’ve been reading the Boot Camp articles published by A.N.A.L.O.G magazine throughout the 1980’s (with the bulk of them written by Tom Hudson), and the book Atari Roots by Mark Andrews published in 1984. If I reach into other material later, I’ll be sure to mention it.
6502 Basics
The 6502 can access 65532 (64K) memory locations. 16 bit addresses are stored in 2 bytes using little endian encoding which is storing the least significant byte in the smallest address (the low byte, followed by the high byte). To find a 16 bit address, you take the second (high) byte, multiply it by 256, then add the low first (low) byte.
There are 56 instructions the 6502 understands. I’ll cover the list and what they do later. At the most basic level each instruction to the processor requires an mnemonic opcode (instruction) and an operand (parameter value), though not all opcodes require operands.
Registers
Registers are used to exchange data between the program and the processor. The 6502 has 6 registers with the 6th being being used to denote 7 discreet bits or flags. The registers are described here:
Accumulator (A)
Used for arithmetic and data manipulation.
X Index (X)
Y Index (Y)
Hold indexes, counters, and offsets or temporary storage.
Program Counter (PC)
Used internally by the 6502 to keep track of what instruction is being executed. Actually 16 bits.
Stack Pointer (SP)
Used internally by the 6502 to keep track of stack.
Status (P)
This one is actually referenced by bit. One bit, 5 is not used. Bit order is: NV-BDIZC. The 7 used bits are described here:
7) Sign (N) is 0 when a result is positive, and 1 if negative.
6) Overflow (V) is 1if either bit 6 or bit 7 of an arithmetic operation is TRUE, but not if both are TRUE.
5) Unused.
4) Break (B) is 1 when a BRK is executed.
3) Decimal (D) set to 0 to use binary arithmetic, or 1 for decimal.
2) Interrupt (I) enables and disables system interrupts.
1) Zero (Z) is 1 when an operation returns a 0 result, otherwise it is 0.
0) Carry (C) holds carries from rotate, shift, and add operations. Its is also used as borrow flag for subtraction.
Addressing
There are 13 addressing modes. This is part of what makes the 6502 a versatile processor. Not all these modes are available to all instructions. They are described here:
Absolute: $nn
The operand is a memory location, not a literal value. The value at the memory location is used by the instruction.
Absolute Indexed: $nn,X or $nn,Y
The value of the register specified (X or Y) is added to the address specified ($nn) for the instruction to determine the final address used by the instruction.
Accumulator
Performs an operation on a value stored in the 6502 processor’s accumulator. Instructions that can use accumulator addressing mode are ASL, LSR, ROL, and ROR.
Implicit
Instruction opcode only, operand forbidden. Instructions that can use implicit addressing mode are BRK, CLC, CLD, CLI, CLV, DEX, DEY, INX, INY, NOP, PHA, PHP, PLA, PLP, RTI, RTS, SEC, SED, SEI, TAX, TAY, TSX, TXA, TXS, and TYA.
Immediate: #n
The operand is a literal value, not a memory location. requires the # symbol. Hex numbers can be used by preceding with $ like #$0A. Instructions that can use immediate address mode are ADC, AND, CMP, CPX, CPY, EOR, LDA, LDX, LDY, ORA, and SBC.
Indexed Indirect: ($n,X)
Uses a page 0 address offset by the value of the X register to find another page 0 address (a) where a and a+1 are used to find a final address. Primarily used for tables.
Indirect Indexed: ($n) ,Y
Uses the address stored at n and n+1, added to the value of the Y register to find a final address. Primarily used for tables and more prevalent than Indexed Indirect mode.
Indirect: ($nn)
Uses the contents of the 16 bit address found at address nn. Only used by one instruction, JMP.
Relative
Used by condition branching instructions to shift program execution to a new memory location. Instructions than can use relative addressing mode are BCC, BCS, BEQ, BNE, BMI, BPL, BVC, BVS.
Zero Page: n
The operand is a single byte, always a memory location in page 0, in the range 0 ($00) to 255 ($FF). The value at the memory location is used by the instruction. Similar to absolute addressing but limited to single byte addresses in page 0. Instructions that can use zero page addressing are ADC, AND, ASL, BIT, CMP, CPX, CPY, DEC, EOR, INC, LDA, LDX, LDY, LSR, ORA, ROL, ROR, SBC, STA, STX, and STY.
Zero Page, X: $nn, X
Just like the Absolute Indexed X mode except the address used must be in page 0. Instructions that can use the zero page X addressing mode are ADC, AND, ASL, CMP, DEC, EOR, INC, LDA LDY, LSR, ORA, ROL, ROR, SBC, STA, and STY.
Zero Page, Y: $nn, Y
Just like the Zero Page X mode except it can only be used with two instructions, which are LDX and STX.
Stack
The stack is a block of memory used by the processor for temporary data storage but can also be carefully used by user written programs. Its LIFO, Last In First Out. In other words when adding a value to the stack, the previous stack value is inaccessible until the last value is removed from the stack.
A good example would be the 6502 encountering a subroutine instruction. It stores the current program execution address on the stack, starts processing instructions from the subroutine address, then when the subroutine ends returns reads the value on the stack to know where to resume program execution, then removes the address from the stack.
Thats all for this time. Back to reading!
Like this:
Like Loading...