Subroutines                                                                   Register-reference

The power of a computer is realized in the execution of subroutines. Given a minimal set of hardware implemented instructions, subroutines can be used to perform repetitive operations (including operations that effectively replace hardware) and extend the functionality of the computer. The basic idea is to branch to the subroutine saving the return address in the first cell of the subroutine, execute the subroutine sequentially, and as a last step in the subroutine branch unconditionally with an indirect memory reference (using the the address stored in the first cell of the subroutine). In this manner, the subroutine can be called from any location and when done return back to the calling location to continue program execution.

What has to be saved in the first cell of the subroutine?

A program "knows" the location of the next instruction by the contents of the PC. This is what must be stored in the first cell of the subroutine.

How does the subroutine then begin execution at the next cell of the subroutine (the one following the first cell where the calling program's PC is stored)?

In order for the next instruction to be executed to be the second cell (line) of the subroutine, the value stored in the PC has to be updated with a value that is one more than the value in the AR (where the calling program's PC is stored). This is accomplished by incrementing the AR and storing this incremented value in the PC.

How does the subroutine return control to the calling program?

The last line of a subroutine places the contents of the subroutine's first line in the PC so the next fetch operation begins right where the calling program left off. This is accomplished by an indirect BUN. BUN merely places the contents of AR into PC, but an indirect BUN will first (in the second decode step) update the AR with the contents of memory -that memory location pointed to by the lower three nibbles of the instruction.

Steps to Add a Subroutine to Your Program

  1. BSA to the first line of the subroutine.
  2. Fill in the steps of the subroutine from the second line on.
  3. In the last step, indirect BUN with the lower three nibbles being the first line of the subroutine.

Subroutine to Subtract

To subtract with only an ADD command the subtrahend must first have the two's complement algorithm applied to change the sign, then this number is added to produce a subtraction. The two's complement algorithm is complement and add one (CMA, INC). Hardware could be added to perform this operation (as in Week 7, AddSubOvrFlowFlag.cct) or software in the form of a subroutine could be used. The following program implements such a subroutine in order to subtract 4,66010 from 17,76710 to get 13, 10710 (12 bit addresses and 16 bit instructions/data are all written in hexadecimal):

200 PC start This Program Subtracts 123416 from 456716
11 Number of words to follow
04F 0000 Return_Address
050 7200 CMA
051 7020 INC
052 C04F BUN
104 1234 DATA
105 4567 DATA
200 2104 LDA
201 504F BSA
202 1105 ADD
203 3106 STA
204 7001 HLT

Program Execution 

Show all the state changes during the balance of program execution at the corresponding time step in Table 1. You may or may not need all of the rows in Table 1. Use the column whose heading is Phase to keep track of which phase (FETCH, DECODE, or EXECUTE) of the instruction cycle is currently being executed. Table 1

After you have completed Table 1, check your answers:

  1. Phased -This step gives the big picture and provides a self check on possible errors either in this or subsequent steps.

  2. Fetched -Two clock cycles: first AR¬ PC, then IR¬ M[AR], PC¬ PC+1

  3. Decoded -One clock cycle, possibly two: first D0..D7¬ Decode IR(12..14), AR¬ IR(0..11), I¬ I(15),
                      then if I = 1 and D != 7: AR¬ M[AR] (reload the AR with the address stored in memory).
                     Note: if D = 7, the instruction is either register-reference or input-output.

  4. Executed