Page 189 - Introduction to Microcontrollers Architecture, Programming, and Interfacing of The Motorola 68HC12
P. 189
166 Chapter 6 Assembly Language Subroutines
variables, or the caller's saved registers is as easy as access to local variables. You are
really using the extended local access technique regardless of the variations.
Although BSR is the most efficient instruction to call subroutines, its 8-bit offset
limits it to call subroutines within -128 to +127 locations of the instruction after that
BSR instruction. The JSR instruction with program relative addressing can be used for
subroutines that are outside that range. Both instructions are position independent. This
means that if the BSR or JSR instruction and the subroutine itself are in the same ROM,
the subroutine will be called correctly wherever the ROM is placed in memory. The JSR
instruction using direct or indirect addressing does not have this property and, because of
this, should be avoided except for one case.
The one exception is where the subroutine is in a fixed place in memory. A monitor
or debugging program is a program used to help you step through a program to find
errors in it. These programs are often in ROM at fixed addresses in memory to allow the
reset mechanism (that is executed when power is first turned on) to work correctly,
Calling a subroutine of the monitor program from outside of the monitor program
should be done with a JSR instruction, using direct or indirect addressing, because,
wherever the calling routine is assigned in memory, the subroutine location is fixed in
absolute memory, not relative to the address of the calling routine. The simple statement
that all subroutines must be called using BSR or JSR with program relative addressing
to make the program position independent is wrong in this case.
A variation of the calling mechanism uses computed addresses, computed in an
index register, say X, and loaded from there into the program counter using JSR 0, X.
One place where this calling mechanism is used is to call a subroutine with many entry
points. In this situation, we need to have a standard means to call these different entry
points that does not change if the subroutine is modified. If this is not done, a subroutine
modification to fix a bug may cause a change in the calling routine because the entry
point it used to jump to is now at a different location. This is another example where
fixing an error in one part of a program can propagate to other parts of the program,
making the software very difficult to maintain. The solution is to have standard places to
call that contain the appropriate jumps to the correct entry points.
ASLB
ASLB ; Multiply contents of B by 4
LDX #SUB
JSR B, X ; Jump to ith entry point
Figure 638. Calling the ith Subroutine for Figure 6.37
The standard places are at the beginning of the subroutine, so that their locations
will not be affected by changes in the subroutine. These places contain LBRA
instructions that jump to the proper entry point. The LBRA instructions are always the
same length regardless of whether or not the entry point may be reached by a BRA.
When LBRA instructions are used, the standard places to jump are always some
multiple of three bytes from the beginning of the subroutine. An example will make this
clearer. Suppose a subroutine SUB to interface to a printer has three entry points, SUBO,
SUB1, and SUB2. We call SUBO before we use the printer to initialize it, we call SUB1
to output a character to it, and we call SUB2 after we use the printer to turn it off. The