Page 2 of 2
Posted: Mon Jul 10, 2006 5:45 am
by tokumaru
random wrote:I'm having trouble understanding how the program counter and relative addressing works in relation with JMP and the various branch functions.
Well, you don't
have to understand that. Unless you are programming an emulator, then you have to.
If you want to make NES games, you can trust that the 6502 will do the right thing, it always does. When branching, you don't have to worry about relative displacement, you just use a label. It's up to the assembler to convert the labels to the signed value that represents the displacement.
Posted: Mon Jul 10, 2006 2:40 pm
by random
Yet more questions...
How exactly does the stack pointer work and what does it do? I'm getting different definitions from different docs.
While looking through some homebrewed games for the NES I'm noticing headers, ".org" seems to be common to a lot of them. The 6502 stuff I'm reading doesn't mention it at all. Naturally, I'm asking: what do they do and how do they work? Also limited information on these.
Additionally while looking through the same games, I'm seeing things like the following:
1) SOME_NAME = SOME_MEMORY_ADDRESS_OR_NUMBER
2) SOME_NAME dc.b
3) SOME_NAME ds.b
And strange (well I haven't seen it in the docs) subroutine stuff like:
4) SOME_NAME:
5) .SOME_NAME
6) SOME_NAME subroutine (following this would sometimes include the .SOME_NAME form)
Of course, again, none of the docs I'm reading explain stuff like this. I can only guess that the different subrountine forms are personal preference or something (different syntax maybe?).
Thank you for any help.
Posted: Mon Jul 10, 2006 3:42 pm
by tepples
tokumaru wrote:If you want to make NES games, you can trust that the 6502 will do the right thing, it always does. When branching, you don't have to worry about relative displacement, you just use a label.
Unless you're trying to troubleshoot "branch too far" errors and your assembler doesn't automatically convert a BNE to a BEQ around a JMP, or if you're trying to troubleshoot cycle timing errors in your raster effect.
random:
The "stack" is an area of memory from $0100 to $01FF. When you "push" something, the byte is written to the address at the current value of the stack pointer, and then the stack pointer goes down by 1. (There are only 8 changeable bits in the 6502's stack pointer; if it is currently at $0100, it wraps to $01FF.) When you "pull" something, the stack pointer goes up by 1 (wrapping from $01FF to $0100), and then the byte is read.
- PHA and PHP are one push; PLA and PLP are one pull.
- JSR is two pushes, and RTS is two pulls.
The .org pseudoinstruction sets the current address. This tells the assembler where your code is supposed to be loaded into memory, so that labels will be assigned correctly.
The next question (examples 1 through 6) discusses the various ways of assigning labels, or compile-time constant values. Much of this depends on the specifics of your assembler; only your examples 1 and 5 are valid in CA65.
- name = expression
Assigns the label 'name' to equal the value of expression. Assemblers have different limitations as to what in the expression is allowed to be unknown at compile time (e.g. labels found in other modules). - name:
Assigns the label 'name' to equal the current address. - name: lda #0
Assigns the label 'name' to equal the address at the start of the instruction. - name: .byte 1, 2, 3, 4, 5
Assigns the label 'name' to equal the current address, and then places bytes of value $01, $02, $03, $04, and $05 here. Some assemblers use .dcb (define constant byte) instead of .byte. - name: .res 8
Assigns the label 'name' to equal the current address, and then places 8 bytes of "unimportant" value. Useful when the current address is in RAM and you're trying to knock out space for a variable.
Read the CA65 manual for details.