BASBUILD: DO; /* ORIGINALLY ORG'ED AT 2D00H ABOVE INTERP */ /* ******************************************************** * * * BASIC-E BUILD PROGRAM * * * * U. S. NAVY POSTGRADUATE SCHOOL * * MONTEREY, CALIFORNIA * * * * WRITTEN BY GORDON EUBANKS, JR. * * * * CPM VERSION 1.3 * * * * DECEMBER 1976 * * * ******************************************************** */ /* ******************************************************** * * * THE BUILD PROGRAM GAINS CONTROL WHEN THE * * RUN TIME MONITOR IS EXECUTED. THE INT FILE * * FOR THE PROGRAM TO BE EXECUTED IS OPENED * * AND THE BASIC-E MACHINE IS BUILT. * * * * BUILD PERFORMS THE FOLLOWING FUNCTIONS: * * * * (1) THE NUMERIC CONSTANTS ARE READ FROM * * THE INT FILE, CONVERTED TO INTERNAL REP- * * RESENTATION, AND STORED IN THE FSA. * * * * (2) THE SIZE OF THE CODE AREA, DATA AREA * * AND NUMBER OF PRT ENTRIES ARE READ FROM * * THE INT FILE. BUILD THEN DETERMINES THE * * ABSOLUTE ADDRESS OF EACH SECTION OF THE * * BASIC-E MACHINE. THESE ADDRESSES ARE * * PASSED TO THE INTERP PROGRAM VIA FIXED * * ADDRESSES IN THE FLOATING POINT SCRATCH * * PAD. * * * * (3) FINALLY INSTRUCTIONS ARE READ FROM * * THE FILE AND PLACED IN EITHER THE DATA * * AREA OR THE CODE AREA. IN THE CASE OF BRS * * BRC, PRO, CON, AND DEF OPERATORS THE * * ADDRESS FOLLOWING THE INSTRUCTION IS RE- * * LOCATED TO REFLECT ACTUAL MACHINE ADDRESSES * * (MINUS 1 BECAUSE PROGRAM COUNTER GETS * * INCREMENTED PRIOR TO USE (EXCEPT FOR CON)!!) * * AFTER (REPEAT AFTER) THE MACHINE HAS BEEN * * REPOSITIONED BY INTERP. THE END OF THE INT * * FILE IS INDICATED BY A MACHINE INSTRUCTION * * 7FH. * * REPOSITIONED BY INTERP. * * * ******************************************************** */ /* ******************************************************** * * * GLOBAL LITERALS * * * ******************************************************** */ DECLARE LIT LITERALLY 'LITERALLY', TRUE LIT '1', FALSE LIT '0', CR LIT '0DH', LF LIT '0AH'; /* ******************************************************** * * * SYSTEM PARAMETERS WHICH MAY * * REQUIRE MODIFICATION BY USERS * * * ******************************************************** */ DECLARE /* OP CODES FOR BASIC-E MACHINE INSTRUCTIONS */ DAT LIT '51', ILS LIT '28', DEF LIT '94', BRS LIT '54', BRC LIT '55', PRO LIT '30', CON LIT '46'; /* ******************************************************** * * * EXTERNAL ENTRY POINTS * * THESE ENTRY POINTS ALLOW INTERFACEING WITH CP/M * * * ******************************************************** */ DECLARE BDOSBEGIN ADDRESS INITIAL(06H), /* PTR TO BOTTOM CP/M */ MAX BASED BDOSBEGIN ADDRESS, /* OFFSET IS THE SIZE OF THIS MODULE */ OFFSET ADDRESS EXTERNAL, /* INITIALIZED BELOW */ /* START IS THE ADDRESS TO START INTERPRETATION */ START LABEL EXTERNAL, /* BEGIN HOLDS THE VALUE OF .MEMORY FOR INTERP */ BEGIN ADDRESS EXTERNAL, /* PARAMETER PASSING LOCATIONS */ PARAM1 ADDRESS EXTERNAL , PARAM2 ADDRESS EXTERNAL , PARAM3 ADDRESS EXTERNAL , PARAM4 ADDRESS EXTERNAL ; /* ******************************************************** * * * GLOBAL VARIABLES * * * ******************************************************** */ DECLARE MCD LIT 'PARAM1', MDA LIT 'PARAM2', MPR LIT 'PARAM3', SB LIT 'PARAM4', MBASE ADDRESS, /* PTR TO NEXT POSTION IN DATA AREA */ MF BASED MBASE BYTE, BASE ADDRESS, /* PTR TO NEXT POSITION IN CODE AREA */ CURCHAR BYTE, /* HOLDS CHAR BEING ANALYZED */ B BASED BASE BYTE, BV BASED BASE(1) BYTE, /* VECTOR VERSION OF B */ A BASED BASE ADDRESS, AP BYTE, /* ACCUMULATOR INDEX */ ACCUM(16) BYTE, /* HOLDS CONSTANTS PRIOR TO CONV */ TEMP ADDRESS, T BASED TEMP BYTE; /* ******************************************************** * * * FLOATING POINT INTERFACE ROUTINES * * * ******************************************************** */ FLTOP: PROCEDURE(FUNCTION,LOCATION) EXTERNAL; DECLARE FUNCTION BYTE, LOCATION ADDRESS; END FLTOP; DECLARE FPN LITERALLY 'FLTOP'; FLTRET: PROCEDURE(FUNCTION,LOCATION) EXTERNAL; DECLARE FUNCTION BYTE, LOCATION ADDRESS; END FLTRET; DECLARE FP LITERALLY 'FLTRET'; FLTINP: PROCEDURE(COUNT,LOCATION) EXTERNAL; DECLARE COUNT BYTE, LOCATION ADDRESS; END FLTINP; DECLARE FPINP LITERALLY 'FLTINP'; /* ******************************************************** * * * CP/M INTERFACE ROUTINES * * * ******************************************************** */ DECLARE DISKBUFFLOC LIT '80H', FCBLOC LIT '5CH', DISKBUFFEND LIT '100H', /* IF OPERATING SYSTEM READS VARIABLE LENGTH RECORDS THIS MUST BE ADDRESS OF ACTUAL END OF RECORD */ BUFF ADDRESS INITIAL(DISKBUFFEND), /* INPUT BUFFER */ CHAR BASED BUFF BYTE, /* INPUTBUFF POINTER */ FILENAME ADDRESS INITIAL (FCBLOC), FNP BASED FILENAME(33) BYTE; /* FILE CONTROL BLK */ MON1:PROCEDURE(FUNCTION,PARAMETER) EXTERNAL; DECLARE FUNCTION BYTE, PARAMETER ADDRESS; END MON1; MON2: PROCEDURE(FUNCTION,PARAMETER) BYTE EXTERNAL; DECLARE FUNCTION BYTE, PARAMETER ADDRESS; END MON2; MON3: PROCEDURE EXTERNAL; END MON3; PRINTCHAR: PROCEDURE(CHAR) EXTERNAL; DECLARE CHAR BYTE; END PRINTCHAR; PRINT: PROCEDURE(BUFFER) EXTERNAL; /* PRINT A LINE ON CONSOLE FOLLOWED BY A CARRIAGE RETURN AND LINEFEED */ DECLARE BUFFER ADDRESS; END PRINT; PRINTF: PROCEDURE(BUFFER); DECLARE BUFFER ADDRESS; CALL PRINT(BUFFER); CALL PRINTCHAR(CR); CALL PRINTCHAR(LF); END PRINTF; OPEN$INT$FILE: PROCEDURE; FNP(9) = 'I'; FNP(10) = 'N'; FNP(11) = 'T'; IF MON2(15,FILENAME) = 255 THEN DO; CALL PRINTF(.('NI $')); CALL MON3; END; END OPEN$INT$FILE; READ$INT$FILE: PROCEDURE BYTE; /* NEXT RECORD IS READ FROM INT FILE DISKBUFFEND MUST REFLECT THE ADDRESS OF THE END OF THE RECORD PLUS ONE FOR FIXED SIZE RECORDS THIS IS A CONSTANT RETURNS ZERO IF READ IS SAT, AND 1 IF EOF */ RETURN MON2(20,FILENAME); END READ$INT$FILE; /* ******************************************************** * * * GLOBAL PROCEDURES * * * ******************************************************** */ INCBUF: PROCEDURE; IF(BUFF := BUFF + 1) >= DISKBUFFEND THEN DO; BUFF = DISKBUFFLOC; IF READ$INT$FILE <> 0 THEN CHAR = 7FH; END; END INCBUF; STO$CHAR$INC: PROCEDURE; /* GET NEXT CHAR FROM INT FILE AND PLACE IN CODE AREA. THEN INCREMENT PTR INTO CODE AREA. */ B=CHAR; BASE=BASE+1; END STO$CHAR$INC; NEXT$CHAR: PROCEDURE BYTE; CALL INCBUF; RETURN CURCHAR := CHAR; END NEXT$CHAR; GET$TWO$BYTES: PROCEDURE; /* GET NEXT TWO BYTES FROM THE INT FILE AND PLACE THEM IN THE CODE AREA IN REVERSE ORDER. */ BV(1) = NEXT$CHAR; B = NEXT$CHAR; RETURN; END GET$TWO$BYTES; INC$BASE$TWO: PROCEDURE; BASE = BASE + 1 + 1; RETURN; END INC$BASE$TWO; GETPARM: PROCEDURE ADDRESS; /* READ A 16 BIT PARAMETER FROM INT FILE AND CONVERT IT TO AN 8080 ADDRESS QUANTITY */ RETURN SHL(DOUBLE(NEXT$CHAR),8) + NEXT$CHAR; END GETPARM; /* ******************************************************** * * * EXECUTION BEGINS HERE * * * ******************************************************** */ BUILD: CALL PRINTF(.('BASIC-E INTERPRETER - VER 2.2$')); CALL OPEN$INT$FILE; BASE = (.MEMORY + 100H) AND 0FF00H; /* BEGINNING OF MACHINE AND FDA */ OFFSET = BASE - BEGIN; /* SIZE OF THE BUILD MODULE */ CALL FPN(0,0); /* INITIALIZE FLOATING POINT PACKAGE */ /* PROCESS CONSTANTS EACH CONSTANT IS SEPARATED BY A $ LAST CONSTANT FOLLOWED BY A * */ DO WHILE(ACCUM(0) := NEXT$CHAR) <> '*'; /* * INDICATES END OF CONST */ AP = 0; /* COUNTER FOR LENGTH OF THIS CONSTANT */ DO WHILE(ACCUM(AP:=AP+1) := NEXT$CHAR) <> '$'; /* GET CONSTANT INTO THE ACCUM */ END; CALL FPINP(AP,.ACCUM); /* CONVERT IT TO INTERNAL FORM */ CALL FP(9,BASE); /* LOAD INTO FDA FROM F/P ACCUM */ BASE = BASE + 4; /* NEXT LOCATION */ END; /* OF LOOKING FOR * */ /* SETUP MACHINE ADDRESS BASE WILL NOW BE NEXT POSITION IN CODE AREA MBASE WILL BE NEXT POSTION IN DATA AREA ACTUAL ADDRESSES OF CODE AREA, DATA AREA PRT, AND STACK ARE PASSED TO INTERPRETER USING FIXED LOCATIONS */ MBASE = GETPARM + BASE; MDA = MBASE - OFFSET; /* ACTUAL DATA AREA ADDR */ MCD = BASE - OFFSET; /* ACTUAL CODE AREA ADDR */ MPR = GETPARM + MDA; /* ACTUAL BEGINNING OF PRT */ IF MPR >= MAX THEN /* INSURE THERE IS ENOUGH MEMORY */ DO; CALL PRINTF(.('NM $')); CALL MON3; END; SB = SHL(GETPARM,2) + MPR; /* NUMBER OF ENTRIES IN PRT * 4=SIZE PRT */ /* BUILD MACHINE - ATLAST AS OPCODES ARE READ THEY MAY BE: (1) DAT - WHICH MEANS ALL CHARACTERS FOLLOWING DAT GO INTO DATA AREA UNTIL A BINARY ZERO IS INCOUNTERED (2) GREATER THAN 127 - WHICH IS A LIT OR A LIT. TREAT THIS AS 16 BIT OPCODE AND PUT IN CODE AREA IN ORDER THEY ARE ON INT FILE (3) ILS - WHICH MEANS ALL CHARACTERS FOLLOWING GO INTO CODE AREA UNTIL A BINARY ZERO IS INCOUNTERED - BUT FIRST PUT A ILS IN CODE AREA AND THE NEXT BYTE IS SET TO ZERO AND INCREMENTED FOR EACH CHARACTER IN THE STRING. IE A STRING CONSTANT IS A ILS OPCODE, A LENGTH AND THE STRING. (4) A NORMAL OP CODE - PUT IN CODE AREA - BUT IF IT IS A BRS OR BRC OR DEF OR PRO THEN THE NEXT TWO BYTES ARE AN ADDRESS WHICH MUST BE RELOCATED TO THE ACTUAL CODE AREA MINUS 1; OR IT COULD BE A CON WHICH IS RELOCATED TO THE FDA. */ DO WHILE NEXT$CHAR <> 7FH; /* BUILD MACHINE */ IF CURCHAR = DAT THEN /* PROCESS DATA STATEMENT */ DO WHILE(MF := NEXT$CHAR) <> 0; /* LOOK FOR END */ MBASE = MBASE + 1; END; ELSE IF CURCHAR >= 128 THEN /* PROCESS LIT OR LID */ DO; CALL STO$CHAR$INC; CALL INCBUF; CALL STO$CHAR$INC; END; ELSE IF CURCHAR = ILS THEN /* PROCESS INLINE STRING */ DO; CALL STO$CHAR$INC; TEMP = BASE; CHAR = 0; /* TO SET LENGTH TO 0 INITIAL */ CALL STO$CHAR$INC; DO WHILE NEXT$CHAR <> 0; CALL STO$CHAR$INC; T = T + 1; END; END; ELSE DO; CALL STO$CHAR$INC; IF (CURCHAR = BRS) OR (CURCHAR = BRC) OR (CURCHAR = DEF) OR (CURCHAR = PRO) THEN DO; CALL GET$TWO$BYTES; A = A + MCD - 1; CALL INC$BASE$TWO; END; ELSE IF CURCHAR = CON THEN DO; CALL GET$TWO$BYTES; A = SHL(A,2) + BEGIN; CALL INC$BASE$TWO; END; END; END; /* LOOKING FOR 7FH */ GO TO START; /* RETURNS TO BASE MODULE FOR FURTHER PROCESSING */ END;