6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 8:42 am

All times are UTC




Post new topic Reply to topic  [ 15 posts ] 
Author Message
PostPosted: Sat Jan 13, 2024 5:35 am 
Offline

Joined: Thu Apr 26, 2012 4:54 pm
Posts: 7
Hoping someone will explain what I'm missing in understanding how indirect JMPs work. For example:

Code:
target     =$85

.org $200

LDA #0
STA target
LDA #10
STA target+1
...
JMP (target)
...
$1000 .WORD real_destination     ; say real_destination is located at $2500
...
real_destination: ...

The way I read the 6502 programming books, what should happen when the
Code:
JMP (target)
is
executed is the CPU looks to where target is pointed (real_destination), and JMPs to real_destination. When
I run that code in the simulator though, it JMPs to target, i.e. $1000 and tries to execute whatever is there,
which crashes the program b/c it's an address, not valid machine code.

However, if I put a $6C (indirect JMP opcode) in front of target and change
Code:
JMP (target)
to
Code:
JMP target-1
it works the way I understand it should - the address JMPed to is real_destination.
What am I getting wrong?


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 13, 2024 6:18 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8544
Location: Southern California
I think what you're looking for is a double indirect.  There's no native instruction to give you that; but you can use self-modifying code to efficiently get things like double indirects and double indexing.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 13, 2024 6:51 am 
Offline

Joined: Thu Apr 26, 2012 4:54 pm
Posts: 7
I'm trying to figure out how to get rid of the need for W in a FORTH system without using JSR to get into DOCOL or making it completely subroutine threaded. Thinking about your answer, I realize double indirection is what I'm looking for - just didn't know what it's called. I also understand now why fig-FORTH puts a $6C right in front of W and then NEXT does a JMP W-1 instead of just doing a JMP (W). Hmmm... if I put NEXT in zp I might not need double indirection.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 13, 2024 7:21 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8544
Location: Southern California
That exact thing is addressed in the middle of the page I linked to.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 13, 2024 7:43 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
glockr wrote:
Hoping someone will explain what I'm missing in understanding how indirect JMPs work. For example:

Code:
target     =$85

.org $200

LDA #0
STA target
LDA #10
STA target+1
...
JMP (target)
...
$1000 .WORD real_destination     ; say real_destination is located at $2500
...
real_destination: ...

The way I read the 6502 programming books, what should happen when the
Code:
JMP (target)
is
executed is the CPU looks to where target is pointed (real_destination), and JMPs to real_destination. When
I run that code in the simulator though, it JMPs to target, i.e. $1000 and tries to execute whatever is there,
which crashes the program b/c it's an address, not valid machine code.

However, if I put a $6C (indirect JMP opcode) in front of target and change
Code:
JMP (target)
to
Code:
JMP target-1
it works the way I understand it should - the address JMPed to is real_destination.
What am I getting wrong?


I think you are making the mistake in assuming that TARGET is the actual subroutine. In ITC Forth, TARGET is also an indirect address.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 13, 2024 4:30 pm 
Offline

Joined: Thu Dec 28, 2023 8:19 am
Posts: 21
Hi,
to make double indirect jump the simplest way should be :

- call your code that calculate final address
- push computed final address into stack (in just order..)
- RTS (that return to pointed address)


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 13, 2024 5:30 pm 
Offline

Joined: Sun Oct 15, 2023 1:37 pm
Posts: 10
Not sure that I understand your issue but there's a "bug" with the indirect JMP.

It works properly only if the low/high bytes of the pointing adress are on the same page.

JMP ($C0FF) will not fetch the effective jumping adress from $C100 but from $C000.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 13, 2024 7:59 pm 
Offline

Joined: Thu Dec 28, 2023 8:19 am
Posts: 21
lightbeing wrote:
Not sure that I understand your issue but there's a "bug" with the indirect JMP.

It works properly only if the low/high bytes of the pointing adress are on the same page.

JMP ($C0FF) will not fetch the effective jumping adress from $C100 but from $C000.


Correct, simple use it on zero page.. but is only indirect ..

But what do you are searching for?
JMP indirect outside zpage?
JMP double indirect?

Anyway with direct use of stack you can JSR or JMP to any location..


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 13, 2024 8:06 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8544
Location: Southern California
maurice6502 wrote:
Hi,
to make double indirect jump the simplest way should be :

- call your code that calculate final address
- push computed final address into stack (in just order..)
- RTS (that return to pointed address)

Be careful:  If you do it that way, you need to use the target address minus 1, because RTS increments it before execution begins at the new address.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 13, 2024 8:09 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8544
Location: Southern California
lightbeing wrote:
Not sure that I understand your issue but there's a "bug" with the indirect JMP.

It works properly only if the low/high bytes of the pointing adress are on the same page.

JMP ($C0FF) will not fetch the effective jumping adress from $C100 but from $C000.

That bug exists in the original NMOS versions of the 6502.  This bug, and all others, were fixed with the 65c02 (ie, CMOS), and does not exist in any of the CMOS versions.  See all the differences at http://wilsonminesco.com/NMOS-CMOSdif/ .

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 13, 2024 8:40 pm 
Offline

Joined: Thu Apr 26, 2012 4:54 pm
Posts: 7
I'm going to try this later (when I finish the honey-do list my wife just gave me). I'll have to change DOCOL too, but I think SEMIS can stay the same. Don't really want to use a JSR then pop and adjust the return pointer :)
Code:
;
;$95   NEXT:      LDA IP
;$97            CLC
;$98            ADC #2
;$9A            BCC NNINC
;$9C            INC IP+1
;$9E   NNINC      STA IP
;$A0            JMP (**)
;$A1   IP         $adL $adH
;


Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 14, 2024 3:33 am 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
glockr wrote:
Hoping someone will explain what I'm missing in understanding how indirect JMPs work. For example:

Code:
target     =$85

.org $200

LDA #0
STA target
LDA #10
STA target+1
...
JMP (target)
...
$1000 .WORD real_destination     ; say real_destination is located at $2500
...
real_destination: ...


The way I read the 6502 programming books, what should happen when the
Code:
JMP (target)
is executed is the CPU looks to where target is pointed (real_destination), and JMPs to real_destination.


The direct jump loads the two byte address operand and it becomes the new execution address. The indirect jump loads the two byte vector operand and then loads the two byte address located where the vector is pointing.

So if you have a set of 16 indirect vectors at $0300-$0332, you can "JMP ($0306)" to jump to the address that is stored as the third vector in that list.

Now, if you have a direct threaded Forth, you can have the instruction pointer "IP" as the vector for the indirect jump, and still use it as a zero page pointer for words like "LIT", by putting the indirect JMP opcode in front of the IP vector and jumping to it:

Code:
JMPIP = <base address in ZP>
IP = JMPIP+1
IPH = IP+1

SETUPIP: LDA #$6C
        STA JMPIP
        LDA #$FF
        STA IP
        LDA #$FC
        RTS
...

NEXT:
        INC IP
        BEQ +
        INC IP
        BEQ ++
        JMP JMPIP
+       INC IP
++      INC IPH
        JMP JMPIP
...



Quote:
When I run that code in the simulator though, it JMPs to target, i.e. $1000 and tries to execute whatever is there, which crashes the program b/c it's an address, not valid machine code.


Exactly. You have the address of "target", which is $0084, as the operand. Rather than jumping to $0084, it loads what is contained AT $0084, the address $1000, and jumps there instead.

What you seemed to have wanted is a DOUBLY indirect jump, that loads the operand, loads the vector that it points to, and uses THAT to load the address to jump to, and the 65C02 doesn't have one.

Quote:
However, if I put a $6C (indirect JMP opcode) in front of target and change
Code:
JMP (target)
to
Code:
JMP target-1
it works the way I understand it should - the address JMPed to is real_destination.

What am I getting wrong?


Nothing is wrong: if you put a $6C in front of target, then the indirect jump loads the following operand address as the location that holds the address to jump to, so $1000 is used as a vector, with the contents as the address. If you had put $20 in front of target, then the direct jump would have simply jumped to the address at target, as the indirect JMP (target) had done before.


Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 14, 2024 3:09 pm 
Offline
User avatar

Joined: Sun Nov 01, 2020 10:36 am
Posts: 37
Location: Tatooine
When executing a JMP (nn) the cpu goes to the address nn and nn+1, takes the two bytes there and puts them on the PC (in other words nn and nn+1 contain the address of the next instruction to be executed).

Possibly what you want to do is simply:

Code:
JMP ($1000)

or alternatively:

Code:
lda $1000
sta target
lda $1000+1
sta target+1
...
jmp (target)


Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 14, 2024 9:05 pm 
Offline

Joined: Thu Apr 26, 2012 4:54 pm
Posts: 7
BB8 wrote:
When executing a JMP (nn) the cpu goes to the address nn and nn+1, takes the two bytes there and puts them on the PC (in other words nn and nn+1 contain the address of the next instruction to be executed).

Possibly what you want to do is simply:

Code:
JMP ($1000)

or alternatively:

Code:
lda $1000
sta target
lda $1000+1
sta target+1
...
jmp (target)


That's what I wanted. My mistake was confusing names and addresses. So when I wrote
Code:
target     =$AE
...
LDA #$12
STA target
LDA #$1F
STA target+1
JMP(target)

the intention was a JMP to whatever address target pointed at, 6C 1F 12 but I should have realized
it was assembling (as it should) to 6C AE 00. I understand it now thanks to the explanations here :)


Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 14, 2024 9:13 pm 
Offline

Joined: Wed Jan 03, 2007 3:53 pm
Posts: 64
Location: Sunny So Cal
glockr wrote:
Hoping someone will explain what I'm missing in understanding how indirect JMPs work. For example:

Code:
target     =$85

.org $200

LDA #0
STA target
LDA #10
STA target+1
...
JMP (target)
...
$1000 .WORD real_destination     ; say real_destination is located at $2500
...
real_destination: ...



Gonna ask a stupid question: did you mean #10 or #$10?

_________________
Machine room: http://www.floodgap.com/etc/machines.html


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC


Who is online

Users browsing this forum: drogon and 15 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: