James:
I don't think that we've addressed your question. The answer is that there is no way to know the address of the last JMP. The address of the last JSR is on the processor stack with an offset. I expect the offset to the actual opcode to be the return address on the stack -3. For JSR, the return address points to the first byte of the instruction following the JSR instruction. Since the JSR is a three byte instruction, the return address is the address of the JSR opcode + 3.
Accessing the value of the return address of a JSR instruction on the stack is pretty straight forward. There are several elements of the technique used to access that return address. First, the stack pointer, S, is always pointing to the first free location on the stack. Second, is to use pre-indexed absolute addressing mode, i.e. abs,X. Since S is an 8-bit register, any addition using S to calculate an address will be performed modulo 256. In other words, it will stay within the stack page.
Thus, the first step is to capture the stack pointer in the X index register. The second is to determine how many bytes relative to the current stack pointer (which points to first free location on the stack) is the value in which you are you are interested. For example, if you have not pushed any values onto the stack on entry into the DISP_QUOTE subroutine Garth gave in in his example, the low byte of the return address is 1 byte above the current stack pointer, and the high byte of the return address is 2 bytes above the current return address. If any registers have been pushed on the stack, then you'll have to take that into account.
To pull the return address from the stack and move it to a zero page location you do something like the following: (The following code assembles without errors, but has not been tested. Use only as an example of the technique for accessing values on the processor stack.)
Code:
org $0
ds 254
pString ds 2 ; Zero page location holds return address
; which is a pointer to the string to display
org $0200 ; Beginning of RAM
Start: jsr Disp_Quote
db 25, "Press CONTINUE when ready"
Next: brk
align 8
; On entry all registers preserved on stack
;
; Stack lays out as follows
;
; S+1 A
; S+2 X
; S+3 Y
; S+4 P
; S+5 Return Lo
; S+6 Return Hi
;
; Assume S = $80 and that its value is captured in X using tsx, then the
; address $105,x will yield $0185, which is S+5 in the stack page
;
; At completion of this routine, return address on stack should point to Next
Disp_Quote: php ; Save all registers
phy
phx
pha
tsx ; Capture current stack pointer in X
lda $105,x ; Read return address low from the stack
sta pString ; Store in low byte of zp pointer
lda $106,x ; Read return address high from the stack
sta pString+1 ; Store in high byte of zp pointer
lda (pString) ; load count into X
tax
ldy #$01 ; load index to first character in string
Disp_Lp: lda (pString),y ; load character into address
jsr put_ch ; output character
iny ; increment character index
dex ; decrement character counter
bne Disp_Lp ; loop until all characters sent to output
tsx ; capture S in X
clc ; prepare to offset the return address
lda (pString) ; load string length into A
adc $105,x ; add offset to low byte of return address
sta $105,x ; store adjusted low byte of return address
lda #0 ; prepare to adjust high byte of return address
adc $106,x ; add carry out of low byte adjustment
sta $106,x ; store adjuste high byte of return address
pla ; restore registers
plx
ply
plp
rts ; return from Disp_Quote routine
; Example output routine
put_ch: sta $F400 ;
rts