Page 174 - Introduction to Microcontrollers Architecture, Programming, and Interfacing of The Motorola 68HC12
P. 174

6.2 Passing Parameters                                               151

            The first method is that of passing parameters through registers, which is preferred
        when the number of parameters is small. We will also use this method to illustrate the
        idea of a calling sequence. See Figure 6.15. Suppose that the calling routine, the
        program segment calling the subroutine, puts a copy of the vector V into registers A and
        X and a copy of the vector W into registers B and Y, where, as.before, the low byte of a
         16-bit register contains the 8-bit element. Both components of each vector are 1-byte
        unsigned numbers. Assume that the dot product is returned in accumulator D, a
        subroutine DOTPRD that performs the calculation is shown in Figure 6.15a. The
        instructions in the calling routine shown in Figure 6.15b cause the subroutine to be
        executed for vector V equal to (2,6) and vector W equal to (7,3). Notice that the values
        in A and B have been changed by the subroutine, because an output parameter is being
        returned in D. The sequence of instructions in the calling routine that handles the
        placement of the input and output parameters is termed the calling sequence. In our
        calling sequence we have, for convenience, assumed that constant input parameters are
        given to DOTPRD while the output parameter in D is copied into the global variable
        DTPD. These constants and the global variable could just as easily have been stacked
        local variables for the calling routine.
            To emphasize that a calling sequence is in no way unique, suppose that the calling
        routine has vectors that are pairs of 8-bit local variables on the stack, labeled LV and LW,
        as offsets to the stack pointer. To compute the dot product of LV and LW, execute the
        calling sequence in Figure 6.15c.
            We have, for simplicity, omitted the binding, allocation, and deallocation of the
        local variables of the calling routine. The point of this second example is to stress that
        any calling sequence for the subroutine DOTPRD must load copies of the vectors for
        which it wants the dot product into X and Y and then call DOTPRD. It must then get the
        dot product from D to do whatever it needs to do with it. From a different point of view,
        if you were to write your own version of DOTPRD, but one that passed parameters in
        exactly the same way, your version could not directly access the global variable LV used
        in the calling sequence in Figure 6.15. If it did, it would not work for the catling
        sequence in Figure 6.14c.
            Parameters are passed through registers for most small subroutines. The main
        limitation with this method of passing parameters is that there are only two 16-bit
        registers (you do not pass parameters in the stack pointer SP register itself), two 8-bit
        registers, and a few condition code bits. Although this limits the ability of the 6812 to
        pass parameters through registers, you will, nevertheless, find that many, if not most, of
        your smaller subroutines will use this simple technique.
            The next technique we discuss is that of passing parameters through global
        variables. We include it because it is used in small microcomputers like the 6805, but
        we discourage you from using it in larger machines like the 6812. It is easy to make
        mistakes with this technique, so much so that most experienced programmers avoid this
        method of passing parameters when other techniques are available. Figure 6.16 shows a
        coat hanger diagram that illustrates how incorrect results can occur when parameters are
        passed with global variables. Notice in particular how subroutine B writes over the vaiue
        of the global variable passed by the calling routine to subroutine A, so when subroutine
        A performs the load instruction, it may not have the calling routine's value.
   169   170   171   172   173   174   175   176   177   178   179