Jan 3, 2012

Subroutine

Introduction
Subroutine is a set of instructions within a large program that perform a specific task. Subroutine is coded such that it can be invoked repeatedly from anywhere in the program including other subroutines, and then returns and continues the execution at the next instruction after the invoke instruction. The sequence of execution involving subroutine is illustrated in Figure 1.


Instructions to call a subroutine are bsr (branch subroutine) and jsr (jump subroutine). When bsr and jsr instructions are executed, the return address is saved in the stack and stack pointer (SP) is decremented by 2. Bothbsr and jsr, the operand is specified by using a label (relative addressing mode). The label specify the location of the subroutine in the program. In addition to relative addressing mode, operand of jsr instruction can be specified by using direct, extended, indexed and indexed indirect addressing modes. Program control returns to the main program by using rts. Return address is pop from the stack onto the PC and increment the SP by 2. Program execution continues at the address restored from the stack.

There are issues that require consideration when implementing subroutines.
  1. Passing parameters
  2. Returning results
  3. Saving CPU registers
  4. Local variables

Parameter Passing and Results Returning
Subroutine might requires values from main program (caller) for its computation. Results of the computation might need to be returned to the main program. In fact, it is a common practice to write a subroutine with a specific purpose of computing one or more results whose values are determined by the parameters passed by the caller. Passing parameters may be implemented by using CPU registers, the stack or defining global memories. Parameters are pushed into the stack for example before the subroutine is called. Similar operation is performed when returning results to the main program. The results are placed in CPU registers before the subroutine complete its execution.

Saving CPU Registers
Subroutine may use CPU registers to hold values for its computation. However the values it the CPU registers may also be used by the caller. If the values are not preserved when a subroutine is called, the result computation of the caller will be incorrect. Therefore the CPU registers must be saved before a subroutine is executed. Either the caller or subroutine is responsible for saving the registers. Stack is used to save the registers.

Local Variables
Subroutine may require memory locations to hold temporary values for its computation. These memory locations are available and accessible by the subroutine thus it is called local variables. Allocating local variables are done by using leas instruction. To allocate n local variables, the instruction is written as

leas -n,SP

SP is the base register which hold the base address and n is the offset. Before subroutine complete its execution, the local variables are deallocated.

leas n,SP


The following program shows an example of program with a subroutine.


i     equ    0
c     equ    1
N     equ    2
      org    $1510
arr1  dc.b   $11,$22,$33,$44
      org    $1530
arr2  dc.b   $55,$66,$77,$88,$99,$AA

      org    $2000
      lds    #$2000
      ldx    #arr1 ; parameter passing (index register X)
      ldaa   #4 ; parameter passing (accumulator B)
      jsr    tb7 ; call subroutine tb7

      ldx    #arr2
      ldaa   #6
      jsr    testb7
      ...
      swi

; Subroutine begin
tb7   leas   -3,sp ; allocate 3 local variables
      clr    c,sp ; init c
      clr    i,sp ; init i
      staa   N,sp ; init N/get value of N
loop  ldab   i,sp
      cmpb   N,sp
      beq    exit
      ldaa   b,x
      bita   #$80 ; test bit 7 for zero
      bne    skip ; tested bit 7 are not zero, don't count (skip)
      inc    c,sp
skip  inc    i,sp
      bra    loop
exit  ldab   c,sp ; result returning (accumulator B)
      leas   3,sp ; deallocate local variables
      rts;     ; return to main program
; Subroutine end
      end

Index register X and accumulator A are used for parameter passing while accumulator B is used to return the result to the caller. Three local variables are allocated by the subroutine.