From Computer History Wiki
Jump to: navigation, search

A subroutine (or function or procedure) is a block of code (either in the source code, or in the object code) to which control can be transferred so that the code block can perform some desired common operation; when it is done doing so, control returns to the 'caller' of the subroutine.


In the very earliest days of computing, a subroutine was simply a written-out sequence of instructions to perform some common operation (e.g. multiply, on machines which did not have a 'multiply' instruction). The programmer wishing to use that subroutine had to insert a copy of those instructions in their program, at the point at which it was desired to perform that operation.

If the same operation needed to be performed at several different places in the program, thereby necessitating several copies of the code sequence, this was obviously inefficient of space in main memory, particularly crucial in early machines which had very small main memories.

It thus became desirable to allow one copy of the instruction sequence to be shared; to do this, a calling sequence was defined, using existing instructions, where the address to go back to upon completion was stored in a known location, before the subroutine was entered. One copy of the subroutine could thus be 'shared' among multiple uses.

Eventually hardware support (in the form of a special instruction) was added to simplify calling sequences, although the first versions were often crude. E.g. in the Whirlwind computer, the subroutine calling sequence used two instructions, 'Sub-Program' and 'Transfer Address': the first saved the current PC in the accumulator, and jumped to the subroutine; the second stored the address in the accumulator in the address field of an instruction, usually a 'jump' instruction at the end of the subroutine.

(The PDP-10 instruction set contains a 'fossil' from this era: the 'JSA' instruction, which saves information in the first word of the subroutine, and starting execution at the second word.)

Calling sequences were also expanded, to allow arguments to be passed, so that a given subroutine had more flexibility (i.e. one would not need two, slightly difference, copies.)

Calling sequences which stored arguments, and the return point, in fixed locations cannot be used recursively, so eventually the modern practise, of storing both arguments and the return point on a stack, came into use.