Do the JSRs in 6502 assembly set the PC to a function's address or the address of a function pointed to in a table high in memory? Like are the two bytes after the JSR the next address the PC needs to be for the function to begin or no?

I've learned in assembly and BASIC functions typically declared at the bottom and are then indexed by a function table. I wanted to make sure that was the same for NES programs because I don't think the JSR's next two bytes are used to address the subroutine called

Maybe you're thinking of the JMP instruction, which gives you the choice between absolute and indirect.

NekadZut wrote:

Do the JSRs in 6502 assembly set the PC to a function's address or the address of a function pointed to in a table high in memory? Like are the two bytes after the JSR the next address the PC needs to be for the function to begin or no?

JSR has exactly one addressing mode: absolute, where the two bytes after the opcode specify the address of the function you are going to start executing.

_________________Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

The 65816 has a JSR (addr,X), which is what you want. Unfortunately it's not on the 6502.

A little closer, a workaround for the 6502's lack of a JSR (addr) (although still not suitable for a table) is self-modifying code, where instead of writing the address to a separate variable, you write it to the operand field of the JSR addrinstruction itself, ie, to bytes 2 and 3 of the 3-byte instruction. This of course assumes that the code is in RAM, not ROM.

Ok, so what about a table? The 65c02 (CMOS) has a JMP (addr,X), and you can JSR to this JMP instruction. It still takes additional cycles, and it's not available on the NMOS 6502. You can however simulate the JMP (addr,X) this way on the NMOS 6502, and then JSR to this routine:

Note that the RTS in this case is not being used as a return from subroutine, but as an indirect jump to the desired subroutine! This method does not require any variables, and both the code and the table can be in ROM. This is in chapter 5 of the 6502 stacks treatise indexed at http://wilsonminesco.com/stacks/index.html .

although it is more efficient to split the table into hi/lo and save the asl

If X always gets loaded from a constant, then it won't matter, because the constant will always be even. But it would matter if you have more than 128 table entries, since 129 or more would need more than 8 bits of index the way I showed it.

Quote:

if your using an assembler with NES in the name you probably need to use LOW(), HIGH() instead of <, or >, and yes the brackets are important

One of the new instructions in Hudson's 65C02 derivative the Hu6280, is the BSR - Branch to Subroutine instruction. Doesn't seem too useful since the subroutine must be close to the branch, but I guess it can be used in relocatable code since branches are relative.

although it is more efficient to split the table into hi/lo and save the asl

If X always gets loaded from a constant, then it won't matter, because the constant will always be even. But it would matter if you have more than 128 table entries, since 129 or more would need more than 8 bits of index the way I showed it.

Of course you wouldn't do it exactly like that, but you could have object states represented exclusively by even numbers, for example. As long as there's no overhead in keeping the indices even, not splitting the addresses results in slightly more readable/maintainable code without any performance sacrifices.

One of the new instructions in Hudson's 65C02 derivative the Hu6280, is the BSR - Branch to Subroutine instruction. Doesn't seem too useful since the subroutine must be close to the branch, but I guess it can be used in relocatable code since branches are relative.

BSR can be simulated, even with a 16-bit offset, but it's very, very inefficient on the 6502.

I've toyed with the idea of relocatable code for the '02; but as inefficient as it is to make the code itself relocatable, it's even worse with data. I discuss it in chapter 12 of the stacks treatise, at http://wilsonminesco.com/stacks/where-am-I.html . I would still like to have an "Aha!" moment where I find there's a trick that has been hiding from me; but I think it's appropriate to just admit that the 6502 is not suited to relocatable code. It's not totally incapable of it though, nor does every application need to wring maximum performance out of the processor. We sometimes accept compromises in performance to get another desired benefit. This particular section of the stacks treatise is only musings on my part which hopefully will give someone ideas.

I don't remember if I've ever used a table of subroutine addresses in 6502; but there can be OS situations where you might want to be able to keep the index as a constant whose name is descriptive of an OS function for example, and then the OS can get updated and addresses can change without having to change the programs that use them.

Of course you wouldn't do it exactly like that, but you could have object states represented exclusively by even numbers, for example. As long as there's no overhead in keeping the indices even, not splitting the addresses results in slightly more readable/maintainable code without any performance sacrifices.

Fair, but I feel that creates a lot more work, as now your data tools, have to use evens, all your code has to work in evens, if you ever do an inx, you have to remember to inx, inx. I would suggest a better way to solve the problem is to fix it with the assembler.

Who is online

Users browsing this forum: No registered users and 2 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum