Page 187 - DCAP210_INTRODUCTION__TO_MICROPROCESSORS
P. 187
Unit 13: Subroutines
Notes
Subroutine History
Language support
In the (very) early assemblers, subroutine support was limited. Subroutines were not explicitly
separated from each other or from the main program, and indeed the source code of a
subroutine could be interspersed with that of other subprograms. Some assemblers would
offer predefined macros to generate the call and return sequences. Later assemblers (1960s)
had much more sophisticated support for both in-line and separately assembled subroutines
that could be linked together.
Self-modifying code
The first use of subprograms was on early computers that were programmed in machine
code or assembly language, and did not have a specific call instruction. On those computers,
each subroutine call had to be implemented as a sequence of lower level machine instructions
that relied on self-modifying code. By replacing the operand of a branch instruction at the
end of the procedure's body, execution could then be returned to the proper location
(designated by the return address) in the calling program (usually just after the instruction
that jumped into the subroutine).
Subroutine libraries
Even with this cumbersome approach, subroutines proved very useful. For one thing they
allowed the same code to be used in many different programs. Morever, memory was a very
scarce resource on early computers, and subroutines allowed significant savings in program
size.
In many early computers, the program instructions were entered into memory from a punched
paper tape. Each subroutine could then be provided by a separate piece of tape, loaded or
spliced before or after the main program; and the same subroutine tape could then be used by
many different programs. A similar approach was used in computers whose main input was
through punched cards. The name "subroutine library" originally meant a library, in the literal
sense, which kept indexed collections of such tapes or card decks for collective use.
Return by indirect jump
To remove the need for self-modifying code, computer designers eventually provided an
"indirect jump" instruction, whose operand, instead of being the return address itself, was the
location of a variable or processor register containing the return address.
On those computers, instead of modifying the subroutine's return jump, the calling program
would store the return address in a variable so that when the subroutine completed, it would
execute an indirect jump that would direct execution to the location given by the predefined
variable.
Jump to subroutine
Another advance was the "jump to subroutine" instruction, which combined the saving of the
return address with the calling jump, thereby minimizing overhead significantly.
In the IBM System/360, for example, the branch instructions BAL or BALR, designed for
procedure calling, would save the return address in a processor register specified in the
instruction. To return, the subroutine had only to execute an indirect branch instruction (BR)
through that register. If the subroutine needed that register for some other purpose (such as
calling another subroutine), it would save the register's contents to a private memory location
or a register stack.
Contd. ...
LOVELY PROFESSIONAL UNIVERSITY 181