Things I’ve learnt about the 6502 so far:
- Memory in the range $0000-$00FF is called “zero page” memory. This can be accessed much faster than any other memory because the addresses are all 8-bit. This means that the 8-bit CPU can process the address in one go, instead of needing to process the second byte in a 16-bit address.
- Memory in the range $0100-$01FF is used as the stack (this is why most of the programs I’ve seen so far locate themselves at address $0200 - it puts them past both the valuable zero page RAM and the unpredictable system stack).
- Memory in the range $FFFA-$FFFF is used by the three interrupt commands.
- The CPU supports several different addressing types (about 13, I think), all of which are far too tedious to detail here.
One thing I haven’t found out is how to get the memory address of a label. Say we have to following code:
.ORG $0200 ;Locate asm at $0200 CODE JSR LOAD ;Jump to LOAD subroutine BRK ;Stop running LOAD LDY #$1 ;Load 1 into Y register LDA ($30),Y ;Load data in 1st byte after address in $30 into acc RTS ;Return from subroutine LIST .DB #$20 ;Define a list of bytes .DB #$04
At the label “CODE”, before the subroutine jump, I want to load the address of the list into memory address $30. That way, my “LOAD” subroutine is completely generic. I can define as many lists as I like (each with different labels, natch), and I can call the “LOAD” subroutine on any of them as long as I load the list’s start address into $30. I’d expect to be able to do this with the commands:
LDA LIST ;Load the address of list into the accumulator STA $30 ;Store accumulator into address $30 LDA LIST+1 ;Load other byte of address into acc STA $31 ;Store accumulator into address $31
The bytes are probably the wrong way around as the little-endian-ness hasn’t quite sunk in yet. Anyway, that doesn’t work - what happens here is that LIST is treated as an absolute memory address (a pointer), and the first LDA command loads the first list item into the accumulator (in C terms, it automatically dereferences the pointer and gives me the data). There doesn’t seem to be any way to get at the actual address of the list. So how am I going to make my generic list subroutine? I have no idea. I imagine it involves more reading.
(A few minutes later)
Oh, no - it’s actually quite easy. At least, it is in the “6502 Simulator” Windows program I’m using to code with. The code should look like this:
LDA #<LIST ;Load low byte of LIST into acc STA $30 ;Store low byte at address $30 LDA #>LIST ;Load high byte of LIST into acc STA $31 ;Store high byte at address $31
Prefixing a label with a hash turns it into an immediate number instead of an absolute memory address (ie. we can get the memory address instead of treating it as a pointer and retrieving the data pointed to by the label). Using the greater than/less than symbols allows us to extract individual bytes from the 16-bit address.