JSR          JSR Jump to new location saving return address           JSR

  Operation:  PC + 2 to Stack, (PC + 1) -> PCL          N V - B D I Z C
                               (PC + 2) -> PCH          . . . . . . . .

  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Absolute      |   JSR $FFFF           |   $20   |    3    |    6     |
  +----------------+-----------------------+---------+---------+----------+

 65816 Extensions:

  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  | (Abs.Ind.,X)   |   JSR ($FFFF,X)       |   $FC   |    3    |     6    |
  +----------------+-----------------------+---------+---------+----------+
   See also: JSL

What it does: Jumps to a subroutine anywhere in memory. Saves the PC (Program Counter) address, plus three, of the JSR instruction by pushing it onto the stack. The next RTS in the program will then pull that address off the stack and return to the instruction following the JSR.

Major uses: As the direct equivalent of BASIC's GOSUB command, JSR is heavily used in ML programming to send control to a subroutine and then (via RTS) to return and pick up where you left off. The larger and more sophisticated a program becomes, the more often JSR will be invoked. In LADS, whenever something is printed to screen or printer, you'll often see a chain of JSRs performing necessary tasks: JSR PRNTCR: JSR PRNTSAJSR PRNTSPACEJSR PRNTNUM:JSR PRNTSPACE. This JSR chain prints a carriage return, the current assembly address, a space, a number, and another space.

Another thing you might notice in LADS and other ML programs is a PLA:PLA pair. Since JSR stuffs the correct return address onto the stack before leaving for a subroutine, you need to do something about that return address if you later decide not to RTS back to the position of the JSR in the program. This might be the case if you usually want to RTS, but in some particular cases, you don't. For those cases, you can take control of program flow by removing the return address from the stack (PLA:PLA will clean off the two-byte address) and then performing a direct JMP to wherever you want to go.

If you JMP out of a subroutine without PLA:PLA, you could easily overflow the stack and crash the program.