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

4,5 A Simplified Two-Pass Assembler                                 105


          PASS2 :   CLR   LCNTR ; clear location counter, which is object code index
                    LDX   #SOURCE ; begin source scan: x-> first letter in source string
          P21:      LDAB 2, +x ; move past label and space, to get opcode character
                    LEAX 2 , X ; skip mnenmonic and space after it
                    CMPB #' D' ; if mnemonic is a directive D,
                    BEQ   P22 ; go to get the hex value
                    JSR   GETOPCD ; otherwise get the opcode, returns opcode in A
                    LDAB 1, x+ ; get symbolic name which is instruction effective address
                    JSR   FINDLBL ; search labels, OR label value into opcode in A
                    BRA P23
          P22:      BSR   GETHEX ; get hexadecimal value into A
          P23 :     LDAB LCNTR     ; get location counter which is 8-bits, into B
                    EXG b, y       ; expand B by filling with zero bits, to get 16-bit Y
                    STAA OBJECT, y ; store the opcode-address or the hex value
                    INC   LCNTR     ; increment location counter
                    LDAB #$d ; skip to end of the current source code line
          P24:      CMPB l,x+
                    BNE   P24
                    TST 0, x ; get first character of next line; if null, exit
                    BNE   P21 ; otherwise loop again
                    RTS
                               Figure 4.18. Assembler Pass 2
            PAS SI (Figure 4.17) simply reads the characters from the source listing and inserts
        labels and their values into the symbol table. As is typical of many programs, an initial
        program segment initializes the variables needed in the rest of the subroutine, which is a
        loop. This loop processes one line of assembly-language source code. If the line begins
        with a label, it inserts the label and the current location counter into the symbol table. If
        the line begins with a space, it skips the character. It then scans the characters until it
        runs into the end of the line, indicated by a carriage return. Then it repeats the loop.
        When a NULL character is encountered where a line should begin, it exits.
            PASS2 (Figure 4.18) simply reads the characters from the source listing and
        generates machine code, which is put into the object code vector. As in PASS1, an
        initial program segment initializes the variables needed in the rest of the subroutine,
        which is a loop. This loop processes one line of assembly-language source code. The
        program skips the label and space characters. If the mnemonic is a D for define constant,
        it calls a subroutine GETHEX to get the hexadecimal value; otherwise, it passes the
        opcode mnemonic to a subroutine GETOPCD that searches the list of mnemonic codes,
        returning the opcode. In the latter case, the subroutine FINDLBL finds the symbolic
        label, ORing its value into the opcode. The machine code byte is then put into the object
        code OBJECT.
            GETOPCD (Figure 4.19) searches until it finds a match for the mnemonic. As it
        searches for a match in B, it generates the machine code in A. Because there are no errors
        in our source code, this extremely simple search procedure will always succeed in
        returning the value for the matching mnemonic. Because the directive D has been
        previously tested, if the opcode mnemonic is not an "L" or an "A" it must be "S."
   123   124   125   126   127   128   129   130   131   132   133