home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / asm / asm48 / asm48.bas next >
BASIC Source File  |  1988-05-25  |  23KB  |  594 lines

  1.    '                    ASM48 VER. 1.3
  2.    '          An 8748 source code assembler
  3.    '                     May 1, 1988
  4.    '                 By Vance Navarrette
  5.    '
  6.    ' This file assembles 8748 opcodes into an object listing
  7.    ' from an source file. The source file must have NO FILE EXTENSION
  8.    ' for the assembler to operate. The assembler produces the following
  9.    ' outputs:
  10.     '                    1. <filespec>.lst - assembled source listing
  11.     '                    2. <filespec>.obj - binary object code
  12.     '                    3. <filespec>.lst printout (optional)
  13.     ' The file to be assembled must:
  14.     '                    1. Use Intel standard 8748 op codes
  15.     '                    2. note comments with ;
  16.     '                    3. contain no special control codes, and must
  17.     '                       be an ascii coded file.
  18.     '
  19.     '
  20.     '
  21.     '         THIS BEGINS THE MAIN LOOP.
  22.     '
  23.     '         INPUT THE FILE TO BE ASSEMBLED, AND INITIALIZE THE SYSTEM
  24.     '
  25.     '
  26.     ON ERROR GOTO  ErrHan ' SETUP ERROR HANDLING
  27.     PRINT CHR$(12): PRINT TAB(26);"ASM48: 8748 Cross Assembler"_
  28.         :PRINT TAB(34);"Version 1.3":PRINT
  29.     INPUT "Name of file to assemble";SOURCE$
  30.     DEFINT A-Z' DEFINE INTEGER VARIABLES TO SPEED EXECUTION
  31.     INPUT "Do you wish to print the source code listing (return=yes)";LST$
  32.     PRINT:PRINT:PRINT "BEGINNING PASS 1":PRINT "Press F1 key to abort assembly."
  33.     KEY (1) ON: ON KEY (1) GOSUB ASMABORT
  34.     OPNUM=222: ' OPNUM=NUMBER OF LEGAL OPCODES
  35.     PRINT:PRINT:PRINT : ADD=0 ' ADD=absolute assembly address offset
  36.     LCNT=1: ECNT=0 :EF=0 : OF=0
  37.     '
  38.     '         ADD= MACHINE ADDRESS FOR ASSEMBLY
  39.     '         LCNT=NUMBER OF LABELS FOUND IN SOURCE TEXT
  40.     '         ECNT=NUMBER OF ERRORS FOUND DURING ASSEMBLY
  41.     '         OF=ASSEMBLY ADDRESS OFFSET, USED BY PSUEDO-OPS
  42.     '         BYTCNT=NUMBER OF BYTES REQUIRED BY A GIVEN OPCODE
  43.     '         OPCD=DECIMAL VALUE OF AN OPCODE
  44.     '         LABEL$=TEXT STRING FROM SOURCE CONTAINING A LABEL
  45.     '         LVALUE=NUMERIC VALUE OF A LABEL
  46.     '         OPCD$=TEXT STRING FROM SOURCE CONTAINING AN OPCODE NMEMONIC
  47.     '
  48.     DIM OPCD$(OPNUM),BYTCNT(OPNUM),OPCD(OPNUM),LABEL$(OPNUM),LVALUE(OPNUM)
  49.     '
  50.     '         READ ALL THE OPCODES IN TO AN ARRAY
  51.     '
  52.     FOR I=1 TO OPNUM: READ OPCD$(I),BYTCNT(I),OPCD(I)
  53.     NEXT I
  54.     '
  55.     '         OPEN SOURCE FILE AND TEMPORARY FILE
  56.     '
  57. Opensource:
  58.     If Source$="" then ASMabort 'assembly cancelled
  59.     OPEN"I",1,SOURCE$
  60.     OPEN "O",2,SOURCE$+".TEM"
  61.     '
  62.     '         BEGIN MAIN ROUTINE FOR 1ST PASS
  63.     '
  64. PassOne:
  65.     IF EOF(1) THEN Donepass1
  66.     GOSUB Inlin  ' GO GET A LINE
  67.     IF TEMP$="" THEN GOSUB Nulline ELSE Initstrings
  68.     GOTO PassOne
  69. Initstrings:
  70.     TLAB$="":TOP$="":TVAR$="":TCOM$="" ' INITIALIZE TEMPORARY_
  71.         ' LABEL, OPCODE, VARIABLE AND COMMENT STRINGS
  72.     GOSUB Subcom: '  SUBTRACT OFF ANY COMMENTS THAT ARE PRESENT
  73.     GOSUB Leadspace: ' SUBTRACT ANY LEADING SPACES
  74.     IF TEM$="" THEN GOSUB Svacmnt
  75.     IF TEM$="" THEN PassOne ' NO OPCODE, SO TRY AGAIN
  76.     GOSUB Opcheck: ' SEE IF NEXT WORD IS OPCODE
  77.     IF CNT>0 THEN Opfound ' IF CNT>0, OPCODE WAS FOUND
  78.     GOSUB Label:: ' IF NO OPCODE, SEE IF LABEL
  79.     IF LFND=1 THEN GOSUB Leadspace ' IFLABLE FOUND, STRIP MORE SPACES
  80.     GOSUB Opcheck: ' SEE IF THERE IS AN OPCODE
  81.     IF CNT=0 AND OP$>""   THEN LFND=0 :TCOM$=";**UNKNOWN OPCODE**"_
  82.         :Gosub lastspace
  83.     If Cnt=0 and op$>"" Then Top$=Tem$ : GOTO UnKnOp  'OPCODE IS UNKNOWN
  84. Opfound:
  85.     IF CNT>0 AND BYTCNT(CNT)>1_
  86.     THEN GOSUB Variable : ' IF OPCODE NEEDS VARIABLE, GO FIND IT
  87. UnKnOp:
  88.     IF LFND=0 AND CNT=0 THEN ECNT=ECNT+1 ' FOUND AN ERROR, SO INC'ENT COUNT
  89.         If Bytcnt(Cnt)=4 then Gosub Psuedo 'See if there is a psuedo op     
  90.     GOSUB Svaln
  91.     IF BYTCNT(CNT)=4 THEN GOSUB Deftxt  ' Process Byte Psuedo op codes
  92.     IF BYTCNT(CNT)<3 THEN ADD=ADD+BYTCNT(CNT)
  93.     IF BYTCNT(CNT)=3 THEN ADD=ADD+2
  94.     IF BYTCNT(CNT)=4 THEN ADD=ADD+OF:OF=0
  95.     IF NOT EOF(1) THEN PassOne: ' PRINTED ASSEMBLED STRING, GO GET ANOTHER
  96. Donepass1:
  97.     CLOSE (1): CLOSE (2): PRINT "BEGINNING PASS 2":GOTO Passtwo
  98.      '
  99.      '    subroutine: "subcom"
  100.      '
  101.      '    sutracts a comment designated by ";" from a line to be decoded
  102.      '
  103. Subcom:
  104.      For I=1 to LEN(TEMP$)
  105.         IF MID$(TEMP$,I,1)=";" THEN TEM$=LEFT$(TEMP$,I-1)_
  106.         :TCOM$=RIGHT$(TEMP$,LEN(TEMP$)-I+1):RETURN
  107.          Next I
  108.          TEM$=TEMP$: RETURN
  109.     '
  110.     '    subroutine: "leadspace"
  111.     '
  112.     '   SUBTRACTS LEADING SPACES, RETURNS WITH REST AS "TEM$"
  113.     '
  114. Leadspace:
  115.     For I=1 to LEN(TEM$)
  116.         IF " "<MID$(TEM$,I,1) THEN TEM$=RIGHT$(TEM$,LEN(TEM$)-I+1)_
  117.         : RETURN
  118.         Next I
  119.         TEM$="" : RETURN
  120.      '
  121.      '   subroutine: "opcheck"
  122.      '
  123.      '  looks for opcode in first 10 characters of tem$
  124.      '  cnt=sequence number of opcode, 0 if no code found
  125.      '
  126. Opcheck:
  127.     OP$=LEFT$(TEM$,10): CNT=0 '   INITIALIZE LOCAL VARIABLES
  128.     IF OP$<>"" THEN TEST=ASC(OP$):IF TEST>64 AND TEST<91_
  129.      THEN J=(TEST-65)*7+1 ELSE RETURN 'Use first letter to speed search
  130.     For I=J to OPNUM 'Look for Opcode in Opcode Table
  131.         IF LEFT$(OP$,LEN(OPCD$(I)))=OPCD$(I) THEN_
  132.         CNT=I:TOP$=OPCD$(I):TEM$=RIGHT$(TEM$,LEN(TEM$)-LEN(TOP$))_
  133.         :RETURN
  134.     Next I
  135.     RETURN
  136.      '
  137.      '   subroutine: "label"
  138.      '
  139.      '   Insert string into label table, and return
  140.      '
  141.      '  return w/label in table, label subtracted from string
  142.      '
  143. Label:
  144.     LFND=0   'lfnd=1 means a label was succesfully found
  145.     For I=1 to LEN(TEM$)
  146.             IF RIGHT$(LEFT$(OP$,I),1)<=" " THEN Cont
  147.     NEXT I
  148. Cont:
  149.     LABEL$(LCNT)=LEFT$(OP$,(I-1))
  150.     TEM$=RIGHT$(TEM$,LEN(TEM$)-I+1)
  151.         If I>10 then Tcom$=";**LABEL TOO LONG**":_
  152.         Lvalue(Lcnt)=Add:TLAB$=Left$(Label$(lcnt),10):Return
  153.     LVALUE(LCNT)=ADD:LFND=1:TLAB$=LABEL$(LCNT):LCNT=LCNT+1
  154.     FOR I=1 TO LCNT-2 ' LOOK FOR DUPLICATE LABELS
  155.         IF LABEL$(LCNT-1)=LABEL$(I) THEN TCOM$=";**DUPLICATE DEFINITION**":ECNT=ECNT+1:RETURN
  156.     NEXT I
  157.     RETURN
  158.     '
  159.     '
  160.     '    Last space routine
  161.     '
  162.     '    subtracts trailing spaces and tab charaters
  163.     '
  164.     '
  165. Lastspace:
  166.     For I=Len(tem$) to 1 step -1
  167.         if Mid$(tem$,i,1)>" " then tem$=left$(tem$,I):Return
  168.     Next I
  169.     Tem$="":Return
  170.      '
  171.      '        INPUT ROUTINE: INPUTS A SINGLE LINE FROM OPEN FILE #1
  172.      '        TO BE PROCESSED. RETURNS WITH TEMP$=LINE FROM FILE
  173.      '
  174. Inlin:
  175.     LINE INPUT #1,TEMP$ '    GET THE STRING
  176.     RETURN : ' GOT A STRING OR END OF FILE
  177.      '
  178.      ' SUBROUTINE "VARIABLE"   STRIPS TRAILING SPACES OF VARIABLE
  179.      '
  180.      ' EXPECTS CNT>0 IF OPCODE FOUND, TEM$ CONTAINS VARIABLE
  181.      ' RETURNS CNT, LFND =0 IF VARIABLE NOT FOUND
  182.      '
  183. Variable:
  184.     GOSUB Leadspace ' STRIP LEADING SPACES
  185.     For I=1 to Len(tem$)' INITIALIZE LOCAL LOOP COUNTER
  186.          IF LEFT$(RIGHT$(TEM$,I),1)>" " THEN_
  187.          TVAR$=LEFT$(TEM$,LEN(TEM$)-I+1):RETURN
  188.     Next I
  189.     TCOM$=";**MISSING VARIABLE**":LFND=0:CNT=0:RETURN
  190.      '
  191.      '
  192.      '            THIS SUBROUTINE HANDLES PSUEDO OPCODES
  193.      '
  194.      '                 ORG  0A        ; SETS ADDRESS COUNTER=0A HEX
  195.      '
  196.      '       LABEL1    EQU  05        ; SETS "LABEL1" EQUAL TO 05H
  197.      '                 DS   A0        ; DEFINES SPACE OF A0 BYTES
  198.      '                 DT   "BYE"     ; DEFINES ASCII TEXT: BYE
  199.      '                 DB   01,AF     ; DEFINES BYTES OF STORAGE, FILLED
  200.      '                                  WITH HEX NUMBERS 01H, AFH
  201. Psuedo:
  202.     If Tvar$="" then return 'No variable to process, so done.
  203.     IF TOP$<>"ORG" THEN Defspc
  204.     FOR I=1 TO LCNT-2' CHECK FOR VARIABLE
  205.         IF TVAR$=LABEL$(I) THEN ADD=LVALUE(I) :RETURN
  206.     NEXT I
  207.     T$=TVAR$: GOSUB Hexc ' GOT THIS FAR, SO IT MUST BE A HEX VARIABLE
  208.     ADD=CHEX : RETURN
  209.      '
  210.      '             HANDLES DS (DEFINE SPACE) PSUEDO OP
  211.      '
  212. Defspc:
  213.     IF TOP$<>"DS" THEN Equ
  214.             FOR I=1 TO LCNT-2 ' SEE IF VARIABLE IS A LABEL
  215.                     IF TVAR$=LABEL$(I) THEN OF=LVALUE(I):RETURN
  216.             NEXT I
  217.         T$=TVAR$: GOSUB Hexc: ' IT MUST BE HEX, SO GO CONVERT IT
  218.         OF=CHEX: RETURN
  219.      '
  220.      '                PSUEDO-OP "EQU"
  221.      '
  222.      '
  223. Equ:
  224.     If Top$<>"EQU" then return
  225.     FOR I=1 TO LCNT-2
  226.         IF TVAR$=LABEL$(I) THEN LVALUE(LCNT-1)=LVALUE(I):RETURN
  227.     NEXT I
  228.     T$=TVAR$: GOSUB Hexc ' GOT THIS FAR, SO IT MUST BE HEXADECIMAL
  229.     LVALUE(LCNT-1)=CHEX : RETURN
  230.      '
  231.      '              HANDLES DT (DEFINE TEXT) PSUEDO OP
  232.      '
  233. Deftxt:
  234.     If Tvar$="" Then Return ' No variable, so all done
  235.     IF TOP$<>"DT" THEN Defbyt
  236.     OF=LEN(TVAR$)
  237.     FOR I=1 TO OF
  238.         Byte=ASC(RIGHT$(LEFT$(TVAR$,I),1))
  239.         GOSUB Svabyt
  240.     NEXT I
  241.     RETURN
  242.      '
  243.      '            HANDLES THE DB PSUEDO OP (DEFINE BYTE(S))
  244.      '
  245. Defbyt:
  246.     If Top$<>"DB" then return ' not DB or DT, so return
  247.     TVAR$=TVAR$+" ":N=LEN(TVAR$)
  248.     For I=1 to N ' Fetch each byte, and calculate Hex number
  249.              IF Mid$(TVAR$,I,1)<="/"_
  250.          THEN T$=MID$(TVAR$,I-2,2):GOSUB Hexc : B(I\3)=Chex
  251.         If Tcom$=";**ILLEGAL VARIABLE**" Then Gosub Svacmnt : Exit For
  252.     Next I
  253.     If I<3 then return
  254.     For J=1 to I\3  ' Go print the Hex data
  255.         Byte=B(J) : Gosub Svabyt
  256.     NEXT J
  257.     OF=I\3 : RETURN ' Calculate OF (offset) for address computation
  258.      '
  259.      '        SUBROUTINE HEXC "CONVERT FROM ASCII HEX TO DECIMAL NUMBER"
  260.      '
  261.      '        EXPECTS VARIABLE TO BE CONVERTED AS "T$"
  262.      '        RETURNS WITH CHEX; DECIMAL VALUE OF HEX STRING "T$"
  263.      '
  264. Hexc:
  265.     CHEX=0' INITIALIZE VARIABLES
  266.     FOR J=0 TO LEN(T$)-1
  267.         H=ASC(LEFT$(RIGHT$(T$,J+1),1))-48
  268.         IF 0<=H AND H<=9 THEN CHEX=CHEX+H*16^J
  269.         IF J>2 OR H>22 OR H<0 OR (H>9 AND H<17) THEN_
  270.          TCOM$=";**ILLEGAL VARIABLE**":ECNT=ECNT+1:RETURN
  271.         IF 17<=H AND H<=22 THEN CHEX=CHEX+(H-7)*16^J
  272.     NEXT J
  273.     RETURN
  274.      '
  275.      '        PRINT# SUBROUTINES FOLLOW
  276.      '        THESE ROUTINES OUTPUT STRINGS TO THE TEMPORARY
  277.      '        WORK FILE .
  278.      '
  279.      '
  280.      '                SUBROUTINE NULLINE
  281. Nulline:
  282.     PRINT#2,"": RETURN
  283.      '
  284.      '                SUBROUTINE SAVE-A-LINE (Svaln)
  285.      '
  286. Svaln:
  287.     IF BYTCNT(CNT)=0 THEN PRINT#2,"|";"|";"|";TLAB$;"|";TOP$;_
  288.         "|";TVAR$;"|";TCOM$ :RETURN
  289.     PRINT#2,ADD;"|";BYTCNT(CNT);"|";OPCD(CNT);"|";TLAB$;"|";
  290.     PRINT#2,TOP$;"|";TVAR$;"|";TCOM$
  291.     RETURN
  292.      '
  293.      '                SUBROUTINE SAVE-A-COMMENT (Svacmnt)
  294.      '
  295. Svacmnt:
  296.     PRINT#2,"|";"|";"|";"|";"|";"|";TCOM$
  297.     RETURN
  298.      '
  299.      '                SUBROUTINE SAVE-A-BYTE (svabyt)
  300.      '
  301. Svabyt:
  302.     PRINT#2,"|";"|";BYTE;"|";"|";"|";"|"
  303.     RETURN
  304.  
  305.  
  306.      '                BEGINNING OF PASS TWO
  307.      '
  308.      '        PASS TWO DOES THE FOLLOWING:
  309.      '                A. CREATES LISTING FILE AND PRINTS IT
  310.      '                B. CREATES INTEL FORMAT OBJECT FILE (HEX)
  311.      '                C. INSERTS OPCODES FOR MULTIBYTE INSTRUCTIONS
  312.      '
  313.      '        OPEN FILES, INPUT A LINE
  314.      '
  315. Passtwo:
  316.     OPEN "I",#1,SOURCE$+".TEM":OPEN "O",#2,SOURCE$+".OBJ":LIS=0
  317.     IF LST$="" OR LST$="Y" OR LST$="y" THEN LIS=1
  318.     OPEN "O",#3,SOURCE$+".LST"
  319.          PRINT#3, TAB(35);SOURCE$: PRINT#3, "ADD";TAB(8);"OPCODE";TAB(20);"LABEL";TAB(30);"MNEMONIC";TAB(40);"VARIABLE";TAB(50);"COMMENT"
  320.     ADDTEMP=0 :CKSUM=0:STADD=0' INITIALIZE TEMP ADDRESS, CHECKSUM, START ADD
  321.     LPCNTR=0 ' LPCNTR IS USED AS FLAG TO INDICATE START OF NEW DATA RECORD
  322.      '
  323.      '        START OF MAIN LOOP FOR PASS TWO
  324.      '
  325. Looptwo:
  326.     IF EOF(1) THEN Doneloop2
  327.     TEMP$=""' CLEAR THE VARIABLES PRIOR TO INPUT
  328.     GOSUB Inlin: ' GET A LINE FROM THE FILE
  329.     IF TEMP$="" THEN PRINT#3,"":GOTO Looptwo ' OUTPUT A NULL TO LISTING
  330.     GOSUB Parse  ' GO PARSE THE STRING
  331.     GOSUB Objfile : ' WRITE HEX OBJECT CODE TO FILE
  332.     IF BYTCNT=3 THEN BYTCNT=2: ' SET BYTCNT TO ACTUAL # OF BYTES
  333.     GOSUB listfile : ' OUTPUT A LINE TO THE LIST FILE
  334.     GOTO Looptwo ' END OF LOOP FOR PASS 2
  335.  
  336. Doneloop2:
  337.     GOSUB Inhex ' OUTPUT LAST LINE FOR INTEL HEX FILE
  338.     PRINT#2, ":0000000000"+CHR$(13)+CHR$(10);' OUTPUT END OF RECORD
  339.     PRINT#3,:PRINT#3,:PRINT#3,
  340.  
  341.         ' PRINT LABEL TABLE TO LIST FILE    
  342.     FOR I=1 TO LCNT-1 STEP 4:
  343.         FOR J=0 TO 3
  344.             PRINT#3, LABEL$(I+J);SPC(3);HEX$(LVALUE(I+J));TAB((J+1)*20)
  345.             IF I+J=LCNT-1 THEN Cont2
  346.         NEXT J
  347.     PRINT#3,
  348.      NEXT I
  349. Cont2:
  350.     PRINT#3,:PRINT#3,:PRINT#3, "TOTAL ERRORS THIS ASSEMBLY: ";ECNT
  351.     CLOSE #1,#2,#3: 'DONE, SO CLOSE PRIOR TO LISTING
  352.     Kill Source$+".TEM" ' Delete temporary file
  353.     IF ECNT>0 THEN KILL SOURCE$+".OBJ": ' IF ERROR, DELETE OBJECT CODE
  354.     IF LIS<>1 THEN Closefiles: ' NO LISTING REQUESTED, SO GO QUIT
  355.      '
  356.      '        DONE WITH PASS 2, SO GO DO LISTING IF NEEDEED
  357.      '
  358.     OPEN "I",1,SOURCE$+".LST"
  359.         '
  360.         '     LINE PRINTER LIST ROUTINE (LPTLST)
  361.         '
  362. Lptlst:
  363.     IF EOF(1) THEN Closefiles
  364.     LINE INPUT#1,T$:LPRINT T$
  365.     GOTO Lptlst' SEE IF THERE IS ANOTHER LINE TO LIST
  366. Closefiles:
  367.     CLOSE #1 ' IF LIS=1 THEN CLOSE 1
  368.     PRINT:PRINT:PRINT:PRINT"TOTAL ERRORS THIS ASSEMBLY: ";ECNT
  369. Done:
  370.     END
  371.      '        SUBROUTINE PARSE
  372.      '  PARSES A STRING FROM THE TEMP FILE
  373. Parse:
  374.     GOSUB Stringcut
  375.     TADD=VAL(T$):TADD$=T$
  376.     GOSUB Stringcut
  377.     BYTCNT=VAL(T$):BYT$=T$
  378.     GOSUB Stringcut
  379.     TOP=VAL(T$):TOP$=T$
  380.     GOSUB Stringcut
  381.     TLAB$=T$
  382.     GOSUB Stringcut
  383.     TMNEM$=T$
  384.     GOSUB Stringcut
  385.     TVAR$=T$
  386.     TCOM$=TEMP$
  387.     RETURN
  388.      '
  389.      '                SUBROUTINE STRINGCUT
  390.      '  DIVIDE STRING AT "|" CHARACTER
  391.      '
  392. Stringcut:
  393.      J=Len(Temp$)
  394.      For I=1 to J
  395.     IF MID$(TEMP$,I,1)="|" THEN T$=LEFT$(TEMP$,I-1):TEMP$=RIGHT$(TEMP$,J-I):RETURN
  396.      Next I
  397.      Return
  398.      '
  399.      '                SUBROUTINE PROCVAR
  400.      '
  401.      '        PROCESSES VARIABLES AND RETURNS WITH THE NUMERIC VALUE
  402.      '
  403. Procvar:
  404.     FOR I=1 TO LCNT-1
  405.             IF LABEL$(I)=TVAR$ THEN TVAR=LVALUE(I) :RETURN
  406.         NEXT I
  407.      '        GOT THIS FAR, SO IT MUST BE A HEX NUMBER
  408.     T$=TVAR$: GOSUB Hexc
  409.     TVAR=CHEX
  410.     RETURN
  411.      '
  412.      '                SUBROUTINE PROCJMP
  413.      '
  414.      '        PROCESSES JUMP AND CALL INSTRUCTIONS
  415.      '
  416. Procjmp:
  417.     GOSUB Procvar ' FIND OUT VALUE OF VARIABLE TO JUMP TO
  418.         UPADD=TVAR AND 1792: UPADD=UPADD/8 ' GET UPPER 3 BITS
  419.         TOP=TOP OR UPADD: TVAR=TVAR AND 255
  420.         RETURN
  421.      '
  422.      '        SUBROUTINE TESTRANGE
  423.      ' TESTS FOR RANGE VIOLATIONS ON JUMP INSTRUCTIONS
  424.      '
  425. Testrange:
  426.     IF BYTCNT=3 AND TVAR>&H7FF THEN TCOM$=";**ADDRESS OVERFLOW**"_
  427.         :ECNT=ECNT+1: RETURN
  428.     IF BYTCNT=2 AND (ASC(TMNEM$)=68 OR ASC(TMNEM$)=74) THEN Cont3_
  429.         ELSE RETURN
  430. Cont3:
  431.     IF (TADD AND &H700)>TVAR OR (TADD OR &HFF)<TVAR THEN_
  432.         ECNT=ECNT+1:TCOM$=";**PAGE VIOLATION**":RETURN
  433.     RETURN
  434.      '
  435.      '                SUBROUTINE OBJFILE
  436.      '        OUTPUT HEX ASCII CODE TO OBJECT FILE
  437.      '
  438. Objfile:
  439.     IF BYTCNT=3 THEN GOSUB Procjmp: ' IT'S A BRANCH, SO BIT TWIDDLE.
  440.      IF TOP$="" THEN RETURN: ' NO CODE TO PRINT, SO RETURN
  441.      IF BYT$<>"" AND BYTCNT=0 AND TOP=0 THEN RETURN
  442.      IF BYTCNT=2 THEN GOSUB Procvar: ' IT NEEDS A VARIABLE, GO GET IT.
  443.      IF BYTCNT=2 OR BYTCNT=3 THEN GOSUB Testrange: ' CHECK RANGE ON JMP INSTR
  444.         IF TADD=ADDTEMP AND LPCNTR=1 THEN Cont4
  445.         IF TADD$>"" AND TADD<>ADDTEMP THEN ADDTEMP=TADD: GOSUB Inhex:
  446.         IF TADD$="" AND LPCNTR=1 THEN Cont4
  447.      IF TADD$="" AND LPCNTR=0 THEN LPCNTR=1: STADD=ADDTEMP: GOTO Cont4
  448.         IF BYTCNT<4 THEN ADDTEMP=TADD:STADD=ADDTEMP:LPCNTR=1' SAVE STARTING ADDRESS FOR THIS RECORD
  449. Cont4:
  450.     IF BYTCNT=4 THEN RETURN ELSE ADDTEMP=ADDTEMP+1:INHEX$=INHEX$+RIGHT$("0"+HEX$(TOP),2)_
  451.         :CKSUM=CKSUM+TOP ' IF ITS A PSEUDO OP RETURN, ELSE GET OPCODE
  452.         IF (ADDTEMP AND &H3F)=0 THEN GOSUB Inhex:' OUTPUT IF ADDRESS ROLLS OVER
  453.      IF BYTCNT>1 AND LPCNTR=0 THEN STADD=ADDTEMP:LPCNTR=1 ' OUTPUT SECOND BYTE IF NEEDED
  454.         IF BYTCNT<=1 THEN RETURN ELSE ADDTEMP=ADDTEMP+1:INHEX$=INHEX$+RIGHT$("0"+HEX$(TVAR),2):CKSUM=CKSUM+TVAR
  455.         IF (ADDTEMP AND &H3F)=0 THEN GOSUB Inhex: ' SECOND BYTE DONE, SO RET
  456.      RETURN
  457.      '
  458.      '                SUBROUTINE INHEX
  459.      '        OUTPUTS A DATA RECORD TO INTEL HEX FILE
  460.      '
  461. Inhex:
  462.      CKSUM=-(CKSUM+STADD+(LEN(INHEX$)/2))+1 AND 255' COMPUTE CHECKSUM
  463.      PRINT#2, ":";RIGHT$("0"+HEX$(LEN(INHEX$)/2),2);RIGHT$_
  464.     ("000"+HEX$(STADD),4);"00";INHEX$;RIGHT$("0"+HEX$(256-CKSUM),2);_
  465.     CHR$(13);CHR$(10);
  466.      LPCNTR=0: CKSUM=0:INHEX$="":RETURN
  467.      '
  468.      '                SUBROUTINE LISTFILE
  469.      '        PRINTS OUTPUT TO LISTING FILE FOR PRINTING
  470. listfile:
  471.     TTOP$=RIGHT$("0"+HEX$(TOP),2)
  472.     TTVAR$=RIGHT$("0"+HEX$(TVAR),2)
  473.     TADD$=RIGHT$("00"+HEX$(TADD),3): ' CONVERT TO 3 PLACE HEX
  474.       '
  475.       '       CHANGED OPCODE AND VARIABLES TO TWO BYTE FORMAT
  476.       '       SO GO OUTPUT TO LISTING FILE.
  477.       '
  478.      IF BYTCNT=1 THEN PRINT#3,TADD$;TAB(8);TTOP$ ;TAB(20);TLAB$;TAB(30);_
  479.     TMNEM$;TAB(42);TVAR$;TAB(50);TCOM$:RETURN
  480.      IF BYTCNT=2 THEN PRINT#3,TADD$;TAB(8);TTOP$;TAB(13);TTVAR$;TAB(20);_
  481.     TLAB$;TAB(30);TMNEM$;TAB(42);TVAR$;TAB(50);TCOM$: RETURN
  482.      IF TOP$="" THEN PRINT#3, TAB(20);TLAB$;TAB(30);TMNEM$;TAB(42);_
  483.     TVAR$;TAB(50);TCOM$:RETURN
  484.      IF BYT$="" THEN PRINT#3, TAB(8);TTOP$;TAB(20);TLAB$;TAB(30);TMNEM$;_
  485.     TAB(42);TVAR$;TAB(50);TCOM$:RETURN
  486.      IF BYTCNT=0 THEN PRINT#3, TAB(20);TLAB$;TAB(30);TMNEM$;TAB(42);TVAR$;_
  487.     TAB(50);TCOM$:RETURN
  488.      IF BYTCNT=4 THEN PRINT#3,TADD$;TAB(20);TLAB$;TAB(30);TMNEM$;TAB(42);_
  489.     TVAR$;TAB(50);TCOM$
  490.      RETURN
  491.      '                ERROR HANDLING
  492.      '
  493.      '        THIS GIVES ERROR MESSAGE AND TERMINATES EXECUTION
  494.      '
  495. ErrHan:
  496.     IF ERR=57 OR ERR=27 THEN PRINT:PRINT_
  497.       "Printer is off line or out of paper."_
  498.       :PRINT "List file was created but not printed.":GOTO Closefiles
  499.      IF ERR=53 THEN PRINT:PRINT "The file you specified cannot be found."_
  500.        :INPUT "Re-enter file name to try again or <ENTER> to cancel.",_
  501.        SOURCE$: GOTO Opensource
  502.     IF ERR=61 THEN PRINT: PRINT _
  503.       "The disk in use is full. Assembly was aborted.":END
  504.     IF ERR=71 Or Err=70 THEN PRINT: PRINT_
  505.       "The specified disk drive is not ready."_
  506.       :PRINT "Assembly was aborted.":END
  507.     ON ERROR GOTO 0:END
  508.      '
  509.      '
  510.      '        Subroutine ASMABORT
  511.      '
  512.      '    Aborts assembly at user request
  513.      '
  514.      '
  515. Asmabort:
  516.     Print:Print:Print "Aborting assembly at user request."
  517.     Close 'Close all open files
  518.     End    ' End of program
  519.      '
  520.      '         DATA TABLES FOR 8748 OPCODES, BYTECOUNTS AND BINARY CODE
  521.      '
  522.      DATA"ADD A,R0",1,&H68,"ADD A,R1",1,&H69,"ADD A,R2",1,&H6A,"ADD A,R3",1,&H6B
  523.      DATA"ADD A,R4",1,&H6C,"ADD A,R5",1,&H6D,"ADD A,R6",1,&H6E,"ADD A,R7",1,&H6F
  524.      DATA"ADD A,@R0",1,&H60,"ADD A,@R1",1,&H61
  525.      DATA "ADD A,#",2,&H03,"ADDC A,R0",1,&H78,"ADDC A,R1",1,&H79
  526.      DATA "ADDC A,R2",1,&H7A,"ADDC A,R3",1,&H7B,"ADDC A,R4",1,&H7C
  527.      DATA "ADDC A,R5",1,&H7D,"ADDC A,R6",1,&H7E,"ADDC A,R7",1,&H7F
  528.      DATA "ADDC A,@R0",1,&H70,"ADD A,@R1",1,&H71
  529.      DATA "ADDC A,#",2,&H13
  530.      DATA "ANL A,R0",1,&H58,"ANL A,R1",1,&H59,"ANL A,R2",1,&H5A
  531.      DATA "ANL A,R3",1,&H5B,"ANL A,R4",1,&H5C,"ANL A,R5",1,&H5D
  532.      DATA "ANL A,R6",1,&H5E,"ANL A,R7",1,&H5F
  533.      DATA "ANL A,@R0",1,&H50,"ANL A,@R1",1,&H51
  534.      DATA "ANL A,#",2,&H53,"ANL BUS,#",2,&H98
  535.      DATA "ANL P1,#",2,&H99,"ANL P2,#",2,&H9A
  536.      DATA "ANLD P4,#",1,&H9C,"ANLD P5,#",1,&H9D
  537.      DATA "ANLD P6,#",1,&H9E,"ANLD P7,#",1,&H9F
  538.      DATA "CLR A",1,&H27,"CLR C",1,&H97,"CLR F1",1,&HA5,"CLR F0",1,&H85
  539.      DATA "CPL A",1,&H37,"CPL C",1,&HA7,"CPL F0",1,&H95,"CPL F1",1,&HB5
  540.      DATA "CALL",3,&H14
  541.      DATA "DA A",1,&H57,"DEC A",1,&H07,"DEC R0",1,&HC8,"DEC R1",1,&HC9
  542.      DATA "DEC R2",1,&HCA,"DEC R3",1,&HCB,"DEC R4",1,&HCC,"DEC R5",1,&HCD
  543.      DATA "DEC R6",1,&HCE,"DEC R7",1,&HCF,"DIS I",1,&H15,"DIS TCNTI",1,&H35
  544.      DATA "DT",4,&H00,"DS",4,&H00,"DB",4,&H00,"EQU",4,&H00
  545.      DATA "DJNZ R0",2,&HE8,"DJNZ R1",2,&HE9,"DJNZ R2",2,&HEA,"DJNZ R3",2,&HEB
  546.      DATA "DJNZ R4",2,&HEC,"DJNZ R5",2,&HED,"DJNZ R6",2,&HEE,"DJNZ R7",2,&HEF
  547.      DATA "EN I",1,&H05,"EN TCNTI",1,&H25,"ENT0 CLK",1,&H75
  548.      DATA "IN A,P1",1,&H09,"IN A,P2",1,&H0A
  549.      DATA "INC A",1,&H17,"INC R0",1,&H18,"INC R1",1,&H19,"INC R2",1,&H1A
  550.      DATA "INC R3",1,&H1B
  551.      DATA "INC R4",1,&H1C,"INC R5",1,&H1D,"INC R6",1,&H1E,"INC R7",1,&H1F
  552.      DATA "INC @R0",1,&H10,"INC @R1",1,&H11,"INS A,BUS",1,&H08
  553.      DATA "JC",2,&HF6,"JF0",2,&HB6,"JF1",2,&H76,"JMPP @A",1,&HB3
  554.      DATA "JNC",2,&HE6,"JNI",2,&H86,"JNT0",2,&H26,"JNT1",2,&H46
  555.      DATA "JNZ",2,&H96,"JTF",2,&H16,"JT0",2,&H36,"JT1",2,&H56,"JZ",2,&HC6
  556.      DATA "JB0",2,&H12,"JB1",2,&H32,"JB2",2,&H52,"JB3",2,&H72
  557.      DATA "JB4",2,&H92,"JB5",2,&HB2,"JB6",2,&HD2,"JB7",2,&HF2
  558.      DATA "JMP",3,&H04,"EQU",4,&H00
  559.      DATA "MOV A,#",2,&H23,"MOV A,PSW",1,&HC7,"MOV A,R0",1,&HF8
  560.      DATA "MOV A,R1",1,&HF9,"MOV A,R2",1,&HFA,"MOV A,R3",1,&HFB
  561.      DATA "MOV A,R4",1,&HFC,"MOV A,R5",1,&HFD,"MOV A,R6",1,&HFE
  562.      DATA "MOV A,R7",1,&HFF,"MOV A,@R0",1,&HF0,"MOV A,@R1",1,&HF1
  563.      DATA "MOV A,T",1,&H42,"MOV PSW,A",1,&HD7,"MOV R0,A",1,&HA8
  564.      DATA "MOV R1,A",1,&HA9,"MOV R2,A",1,&HAA,"MOV R3,A",1,&HAB
  565.      DATA "MOV R4,A",1,&HAC,"MOV R5,A",1,&HAD,"MOV R6,A",1,&HAE
  566.      DATA "MOV R7,A",1,&HAF,"MOV R0,#",2,&HB8,"MOV R1,#",2,&HB9
  567.      DATA "MOV R2,#",2,&HBA,"MOV R3,#",2,&HBB,"MOV R4,#",2,&HBC
  568.      DATA "MOV R5,#",2,&HBD,"MOV R6,#",2,&HBE,"MOV R7,#",2,&HBF
  569.      DATA "MOV @R0,A",1,&HA0,"MOV @R1,A",1,&HA1,"MOV @R0,#",2,&HB0
  570.      DATA "MOV @R1,#",2,&HB1,"MOV T,A",1,&H62,"MOV A,P4",1,&H0C
  571.      DATA "MOV A,P5",1,&H0D,"MOV A,P6",1,&H0E,"MOV A,P7",1,&H0F
  572.      DATA "MOV P4,A",1,&H3C,"MOV P5,A",1,&H3D,"MOV P6,A",1,&H3E
  573.      DATA "MOV P7,A",1,&H3F,"MOVP A,@A",1,&HA3,"MOVP3 A,@A",1,&HE3
  574.      DATA "MOVX A,@R0",1,&H80,"MOVX A,@R1",1,&H81,"MOVX @R0,A",1,&H90
  575.      DATA "MOVX @R1,A",1,&H91,"NOP",1,&H00,"ORG",4,&H00,"ORL A,R0",1,&H48
  576.      DATA "ORL A,R1",1,&H49,"ORL A,R2",1,&H4A,"ORL A,R3",1,&H4B
  577.      DATA "ORL A,R4",1,&H4C,"ORL A,R5",1,&H4D,"ORL A,R6",1,&H4E
  578.      DATA "ORL A,R7",1,&H4F,"ORL A,@R0",1,&H40,"ORL A,@R1",1,&H41
  579.      DATA "ORL A,#",2,&H43,"ORL BUS,#",2,&H88,"ORL P1,#",2,&H89
  580.      DATA "ORL P2,#",2,&H8A,"ORLD P4,A",1,&H8C,"ORLD P5,A",1,&H8D
  581.      DATA "ORLD P6,A",1,&H8E,"ORLD P7,A",1,&H8F
  582.      DATA "OUTL BUS,A",1,&H02,"OUTL P1,A",1,&H39,"OUTL P2,A",1,&H3A
  583.      DATA "RETR",1,&H93,"RET",1,&H83,"RL A",1,&HE7,"RLC A",1,&HF7
  584.      DATA "RR A",1,&H77,"RRC A",1,&H67,"SEL MB0",1,&HE5,"SEL MB1",1,&HF5
  585.      DATA "SEL RB0",1,&HC5,"SEL RB1",1,&HD5,"STOP TCNT",1,&H65
  586.      DATA "STRT CNT",1,&H45,"STRT T",1,&H55,"SWAP A",1,&H47,"XCH A,R0",1,&H28
  587.      DATA "XCH A,R1",1,&H29,"XCH A,R2",1,&H2A,"XCH A,R3",1,&H2B,"XCH A,R4",1
  588.      DATA &H2C,"XCH A,R5",1,&H2D,"XCH A,R6",1,&H2E,"XCH A,R7",1,&H2F
  589.      DATA "XCH A,@R0",1,&H20,"XCH A,@R1",1,&H21,"XCHD A,@R0",1,&H30
  590.      DATA "XCHD A,@R1",1,&H31,"XRL A,R0",1,&HD8,"XRL A,R1",1,&HD9
  591.      DATA "XRL A,R2",1,&HDA,"XRL A,R3",1,&HDB,"XRL A,R4",1,&HDC,"XRL A,R5",1
  592.      DATA &HDD,"XRL A,R6",1,&HDE,"XRL A,R7",1,&HDF,"XRL A,@R0",1,&HD0
  593.      DATA "XRL A,@R1",1,&HD1,"XRL A,#",2,&HD3
  594.