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.