It is currently Mon Oct 23, 2017 1:58 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: JSR
PostPosted: Mon Aug 14, 2017 3:37 pm 
Offline

Joined: Fri Aug 04, 2017 4:32 pm
Posts: 7
Location: Atlanta, Georgia
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


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Mon Aug 14, 2017 3:44 pm 
Offline
Formerly WheelInventor

Joined: Thu Apr 14, 2016 2:55 am
Posts: 910
Location: Gothenburg, Sweden
Edit: The following statement was corrected by quitust. Leaving it for the sake of intact history.
The good news is that it's up to you. You can use a literal address (absolute addressing) or point to one (indirect addressing)


http://www.obelisk.me.uk/6502/addressing.html

Unlike BASIC, 6502 machine language doesn't do much 'hidden' stuff for you.

_________________
http://www.frankengraphics.com - personal NES blog


Last edited by FrankenGraphics on Mon Aug 14, 2017 4:26 pm, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Mon Aug 14, 2017 4:12 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 10:59 pm
Posts: 1390
FrankenGraphics wrote:
The good news is that it's up to you. You can use a literal address (absolute addressing) or point to one (indirect addressing)

http://www.obelisk.me.uk/6502/addressing.html


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.


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Mon Aug 14, 2017 4:24 pm 
Offline
Formerly WheelInventor

Joined: Thu Apr 14, 2016 2:55 am
Posts: 910
Location: Gothenburg, Sweden
Ah yes. JMP, not JSR. Pardon me, late night here.

_________________
http://www.frankengraphics.com - personal NES blog


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Mon Aug 14, 2017 9:19 pm 
Offline

Joined: Wed Nov 30, 2016 4:45 pm
Posts: 89
Location: Southern California
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 addr instruction 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:
Code:
                         ; Start with function (an even number) in X.
        LDA  TABLE+1,X   ; Read high address byte from the actual table, and
        PHA              ; push it.  Low byte comes next, below.
        LDA  TABLE,X     ; Be sure to make the table reflect start addresses
        PHA              ; minus 1, since RTS increments the address by 1.
        RTS              ; RTS does the absolute indexed indirect jump.

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 .

_________________
http://WilsonMinesCo.com/ lots of 6502 resources


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Mon Aug 14, 2017 9:42 pm 
Offline
User avatar

Joined: Sat Jul 12, 2014 3:04 pm
Posts: 936
Of course, you probably want to JSR into what Garth wrote to give you a return address therefrom.


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Mon Aug 14, 2017 10:26 pm 
Offline

Joined: Wed Nov 30, 2016 4:45 pm
Posts: 89
Location: Southern California
Myask wrote:
Of course, you probably want to JSR into what Garth wrote to give you a return address therefrom.

(as stated in my last few words right before the listing)

_________________
http://WilsonMinesCo.com/ lots of 6502 resources


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Mon Aug 14, 2017 11:57 pm 
Offline

Joined: Tue Feb 07, 2017 2:03 am
Posts: 248
and the table needs to contain the address-1 you want to call

so .word myFunc-1,otherFunc-1

although it is more efficient to split the table into hi/lo and save the asl
Code:
                         ; Start with function in X.
        LDA  TABLE_hi,X  ; Read high address byte from the actual table, and
        PHA              ; push it.  Low byte comes next, below.
        LDA  TABLE_lo,X  ; Be sure to make the table reflect start addresses
        PHA              ; minus 1, since RTS increments the address by 1.
        RTS              ; RTS does the absolute indexed indirect jump.
TABLE_lo .byte <(myFunc-1),<(otherFunc-1)
TABLE_hi .byte >(myFunc-1),>(otherFunc-1)
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 ;)


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Tue Aug 15, 2017 12:16 am 
Offline

Joined: Wed Nov 30, 2016 4:45 pm
Posts: 89
Location: Southern California
Oziphantom wrote:
and the table needs to contain the address-1 you want to call

(as also stated in my comments)

Quote:
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 ;)

Thanks.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Tue Aug 15, 2017 12:24 am 
Offline

Joined: Tue May 28, 2013 5:49 am
Posts: 809
Location: Sweden
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.


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Tue Aug 15, 2017 12:34 am 
Offline

Joined: Tue Feb 07, 2017 2:03 am
Posts: 248
Garth wrote:
(as also stated in my comments)
Fair I missed it, my bad.
Garth wrote:
Quote:
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.
if you are doing LDX #4 JSR JmpOnX, just do JSR XXXX


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Tue Aug 15, 2017 12:53 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10067
Location: Rio de Janeiro - Brazil
Oziphantom wrote:
if you are doing LDX #4 JSR JmpOnX, just do JSR XXXX

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.


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Tue Aug 15, 2017 1:00 am 
Offline

Joined: Wed Nov 30, 2016 4:45 pm
Posts: 89
Location: Southern California
Pokun wrote:
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.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Tue Aug 15, 2017 1:05 am 
Offline

Joined: Wed Nov 30, 2016 4:45 pm
Posts: 89
Location: Southern California
Oziphantom wrote:
if you are doing LDX #4 JSR JmpOnX, just do JSR XXXX

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.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources


Top
 Profile  
 
 Post subject: Re: JSR
PostPosted: Tue Aug 15, 2017 1:36 am 
Offline

Joined: Tue Feb 07, 2017 2:03 am
Posts: 248
tokumaru wrote:
Oziphantom wrote:
if you are doing LDX #4 JSR JmpOnX, just do JSR XXXX

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.
Code:
given
mCallFunctionTable .macro
   lda \1.hi,\2
   pha
   lda \1.lo,\2
   pha
   rts
.endm

mMakeFunctionTable .macro   
lo .byte <(\@)-1   
hi .byte >(\@)-1   
.endm

you then have
.mCallFunctionTable  myTable,x
myTable .mMakeFunctionTable myFunc,myOtherFunc,someOtherFunc,newFunc
This gives you the same readability as not splitting it, but spares you from having to remember to make everything even and +2 in places.

Typically you want to keep a list of defines in sync with the functions you call, so if you extract the functions into a assembler variable, you can interleave it with the defines like so
Code:
.var vEntFuncs = []
kEntsUpdateFunctions .block
 still = 0
 vEntFuncs ..= [entStandStill]
 walkLeft = 1
 vEntFuncs ..= [entWalkLeft]
 walkRight = 2
 vEntFuncs ..= [entWalkRight]
 jump = 3
 vEntFuncs ..= [entJump]
 fall = 4
 vEntFunc ..= [entFall]
 death = 5
 vEntFunc ..= [entDeath]
.bend
...
...
...

dispatchEntStateX
.mCallFunctionTable  myTable,x
myTable .mMakeFunctionTable vEntFunc


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 3 guests


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

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group