What are Subroutines?

Subroutines are programs that are used by other routines to accomplish a particular task. A subroutine can be called from any point within the main body of the micro-program. Frequently, many micro-programs contain identical sections of code. Microinstructions can be saved by employing subroutines that use common sections of microcode.

For example, the sequence of micro-operations needed to generate the effective address of the operand for instruction is common to all memory reference instructions. This sequence could be a subroutine that is called from within many other routines to execute the effective address computation.

Micro-programs that use subroutines must have a provision for storing the return address during a subroutine call and restoring the address during a subroutine return. This may be accomplished by placing the incremented output from the control address register into a subroutine register and branching to the beginning of the subroutine.

The subroutine register can then become the source for transferring the address for the return to the main routine. The best way to structure a register file that stores addresses for subroutines is to organize the registers in a last-in, first-out (LIFO) stack.

The instruction that transfers program control to a subroutine is known by different names. The most common names used are called subroutine, jump to the subroutine, branch to the subroutine, or branch and save the address.

A call subroutine instruction consists of an operation code together with an address that specifies the beginning of the subroutine.

The instruction is executed by performing two operations are as follows −

  • The address of the next instruction available in the program counter (the return address) is stored in a temporary location so the subroutine knows where to return.
  • The control is transferred to the beginning of the subroutine. The last instruction of every subroutine commonly called return from a subroutine transfers the return address from the temporary location into the program counter. This results in a transfer of program control to the instruction whose address was originally stored in the temporary location.

A subroutine call is implemented with the following micro-operations −

SP ← SP − 1It can decrement the stack pointer.
M[SP] ← PCIt is used to push the content of the PC onto the stack.
PC ← Effective AddressIt can transfer control to the subroutine.

If another subroutine is called by the current subroutine, the new return address is pushed into the stack, and so on. The instruction that returns from the last subroutine is implemented by the micro-operations −

PC ← M[SP]It is used to pop the stack and transfer it to PC.
SP ← SP + 1It can increment the stack pointer.

By using a subroutine stack, all return addresses are automatically stored by the hardware in one unit. The programmer does not have to be concerned or remember where the return address was stored.

A recursive subroutine is a subroutine that calls itself. If only one register or memory location can save the return address, and the recursive subroutine calls itself, it ends the previous return address.

This is undesirable because vital information is destroyed. This problem can be solved if different storage locations are employed for each use of the subroutine while another lighter-level use is still active.

When a stack is used, each return address can be pushed into the stack without destroying any previous values. This solves the problem of recursive subroutines because the next subroutine to exit is always the last subroutine that was called.