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

140                                Chapter 6 Assembly Language Subroutines


            For the purpose of this discussion, we assume that the program segment has
        information passed into it by its input parameters (or input arguments) and that the
        results of its computation are passed out through its output parameters (or output
        arguments). Any variables used in the segment for its computation but not used
        elsewhere, and which are not parameters are called local variables. The program segment
        can be thought of as a box with the parameters and variables that relate to it. Some of
        the parameters may be global variables—variables that are, or can be, used by all
        program segments. If you have learned about sequential machines, the input parameters
        are like the inputs to the sequential machine, the local variables are like the internal
        states of the machine, and the output parameters are like the outputs of the machine. As
        a sequential machine can describe a hardware module without the details about how the
        module is built, one can think about the input and output parameters and local variables
        of a program segment without knowing how it is written in assembly language. Indeed,
        one can think of them before the segment is written.
            Consider the following example. Suppose that we have two vectors V and W, each
        having two I-byte elements (or components) V (1), V ( 2 ) and W (1), W {2 ). We want
        to compute the inner product
                              V(1)*W(1) + V(2)*W(2)                          (1)

        which is often used in physics. Input parameters are the components of V and W, and the
        one output is the dot product result. The components of V and W are assumed to be 1-
        byte unsigned numbers; for instance, assume that VI is 1, V2 is 2, Wl is 3, and W2 is
        4. The 2-byte dot product is placed in accumulator D at the end of the segment, but it
        becomes clear that we will have to store one of the products in expression (1) somewhere
        while we are computing the second product in accumulator D. This 2-byte term that we
        save is a local variable for the program segment we are considering. It may also be
        convenient to place copies of the vectors V and W somewhere for easy access during the
        calculation. These copies could also be considered local variables. We will continue this
        example below to show how local variables are stored in a program segment.
            We first consider the lazy practice of saving local variables as if they were global
        variables, stored in memory and accessed with page-zero or direct addressing. One
        technique might use the same global location over and over again. Another technique
        might be to use differently named global variables for each local variable. While both
        techniques are undesirable, we will illustrate them in the examples below.
            A single global variable, or a small number of global variables, might be used to
        hold all local variables. For example, assuming that the directive TEMP DS 2 is in the
        program, one could use the two locations TEMP and TEMP+1 to store one of the 2-byte
        local variables for the dot product segment. Figure 6.4 illustrates this practice. Six bytes
        are needed for various temporary storage. We first allocate six bytes using the declaration
        TEMP DS 6 . Then the values of these variables are initialized by MOVE instructions.
        Next, these local variables are used in the program segment that calculates the inner
        product. The algorithm to compute the inner product is clearly illustrated by comments.
            Using this approach can lead to the propagation of errors between segments
        discussed earlier. This can be seen by looking at the "coat hanger" diagram of Figure 6,3,
        A horizontal line represents a program segment, and a break in it represents a call to a
        subroutine. The diagonal lines represent the subroutine call and its return. Figure 6,3
   158   159   160   161   162   163   164   165   166   167   168