URL
https://opencores.org/ocsvn/t51/t51/trunk
Subversion Repositories t51
[/] [t51/] [trunk/] [sw/] [BASIC-52.asm] - Rev 7
Go to most recent revision | Compare with Previous | Blame | View Log
;*****************************************************************************
;* *
;* MCS BASIC-52 (tm) Source Listing *
;* December 18, 1986 *
;* The original source code of V1.1 (BASIC.SRC and FP52.SRC) by *
;* Intel Corporation, Embedded Controller Operations *
;* is public donain *
;* *
;*---------------------------------------------------------------------------*
;* Alterations made by D. Wulf , December 18, 1999 *
;* Alterations made by D. Wallner , May 4, 2002 *
;* *
;*****************************************************************************
;
; The BASIC.a51 source listing, when compiled without modification,
; create the same object code that is found on the MCS BASIC-52
; Version 1.1 microcontrollers but with a timing independent baud rate
; recognition routine and a shorter ego message.
;
; The following alterations are made to the original source code:
;
; The original source code had 2 files BASIC.SRC and FP52.SRC those have
; been incorporated into this file for ease of assembly.
;
; All absolute and relativ jumps and calls without labels were providet
; with labels.
;
; All machine code in the original source, codet in databytes is replaced
; by the menomics.
;
; One routine in the source was different to the ROM code and is replaced
; by the ROM code.
;
; Daniel Wallner , May 4, 2002:
; Part of ego message replaced with a different baud recognition routine.
;
;*****************************************************************************
;
T2CON EQU 0C8H ; This three lines are necessary for MS-DOS freeware
TL2 EQU 0CCH ; MCS-51 Family Cross Assembler ASEM-51 V1.2
TH2 EQU 0CDH ; from W.W. Heinz (e-mail: ww@andiunx.m.isar.de)
;
;*****************************************************************************
;
$EJECT
;**************************************************************
;
; TRAP VECTORS TO MONITOR
;
; RESET TAG (0AAH) ---------2001H
;
; TAG LOCATION (5AH) ------ 2002H
;
; EXTERNAL INTERRUPT 0 ---- 2040H
;
; COMMAND MODE ENTRY ------ 2048H
;
; SERIAL PORT ------------- 2050H
;
; MONITOR (BUBBLE) OUTPUT - 2058H
;
; MONITOR (BUBBLE) INPUT -- 2060H
;
; MONITOR (BUBBLE) CSTS --- 2068H
;
; GET USER JUMP VECTOR ---- 2070H
;
; GET USER LOOKUP VECTOR -- 2078H
;
; PRINT AT VECTOR --------- 2080H
;
; INTERRUPT PWM ----------- 2088H
;
; EXTERNAL RESET ---------- 2090H
;
; USER OUTPUT-------------- 4030H
;
; USER INPUT -------------- 4033H
;
; USER CSTS --------------- 4036H
;
; USER RESET -------------- 4039H
;
; USER DEFINED PRINT @ --- 403CH
;
;***************************************************************
;
$EJECT
;***************************************************************
;
; MCS - 51 - 8K BASIC VERSION 1.1
;
;***************************************************************
;
AJMP CRST ;START THE PROGRAM
ADDC A,@R1
;
ORG 3H
;
;***************************************************************
;
;EXTERNAL INTERRUPT 0
;
;***************************************************************
;
JB DRQ,STQ ;SEE IF DMA IS SET
PUSH PSW ;SAVE THE STATUS
LJMP 4003H ;JUMP TO USER IF NOT SET
;
ORG 0BH
;
;***************************************************************
;
;TIMER 0 OVERFLOW INTERRUPT
;
;***************************************************************
;
PUSH PSW ;SAVE THE STATUS
JB C_BIT,STJ ;SEE IF USER WANTS INTERRUPT
LJMP 400BH ;EXIT IF USER WANTS INTERRUPTS
;
ORG 13H
;
;***************************************************************
;
;EXTERNAL INTERRUPT 1
;
;***************************************************************
;
JB INTBIT,STK
PUSH PSW
LJMP 4013H
;
$EJECT
;
ORG 1BH
;
;***************************************************************
;
;TIMER 1 OVERFLOW INTERRUPT
;
;***************************************************************
;
PUSH PSW
LJMP CKS_I
;
STJ: LJMP I_DR ;DO THE INTERRUPT
;
;***************************************************************
;
;SERIAL PORT INTERRUPT
;
;***************************************************************
;
ORG 23H
;
PUSH PSW
JB SPINT,STU ;SEE IF MONITOR EANTS INTERRUPT
LJMP 4023H
;
ORG 2BH
;
;**************************************************************
;
;TIMER 2 OVERFLOW INTERRUPT
;
;**************************************************************
;
PUSH PSW
LJMP 402BH
;
$EJECT
;**************************************************************
;
;USER ENTRY
;
;**************************************************************
;
ORG 30H
;
LJMP IBLK ;LINK TO USER BLOCK
;
STQ: JB I_T0,STS ;SEE IF MONITOR WANTS IT
CLR DACK
JNB P3.2,$ ;WAIT FOR DMA TO END
SETB DACK
RETI
;
STS: LJMP 2040H ;GO TO THE MONITOR
;
STK: SETB INTPEN ;TELL BASIC AN INTERRUPT WAS RECEIVED
RETI
;
STU: LJMP 2050H ;SERIAL PORT INTERRUPT
;
$EJECT
;$INCLUDE(:F2:LOOK52.SRC)
; INCLUDED BELOW
;
;**************************************************************
;
; This is the equate table for 8052 basic.
;
;**************************************************************
;
; The register to direct equates for CJNE instructions.
;
R0B0 EQU 0
R1B0 EQU 1
R2B0 EQU 2
R3B0 EQU 3
R4B0 EQU 4
R5B0 EQU 5
R6B0 EQU 6
R7B0 EQU 7
;
; Register bank 1 contains the text pointer
; and the arg stack pointer.
;
TXAL EQU 8 ;R0 BANK 1 = TEXT POINTER LOW
ASTKA EQU 9 ;R1 BANK 1 = ARG STACK
TXAH EQU 10 ;R2 BANK 1 = TEXT POINTER HIGH
;
; Now five temporary locations that are used by basic.
;
TEMP1 EQU 11
TEMP2 EQU 12
TEMP3 EQU 13
TEMP4 EQU 14
TEMP5 EQU 15
;
$EJECT
; Register bank 2 contains the read text pointer
; and the control stack pointer.
;
RTXAL EQU 16 ;R0 BANK 2 = READ TEXT POINTER LOW
CSTKA EQU 17 ;R1 BANK 2 = CONTROL STACK POINTER
RTXAH EQU 18 ;R2 BANK 2 = READ TEXT POINTER HIGH
;
; Now some internal system equates.
;
BOFAH EQU 19 ;START OF THE BASIC PROGRAM, HIGH BYTE
BOFAL EQU 20 ;START OF THE BASIC PROGRAM, LOW BYTE
NULLCT EQU 21 ;NULL COUNT
PHEAD EQU 22 ;PRINT HEAD POSITION
FORMAT EQU 23
;
; Register bank 3 is for the user and can be loaded
; by basic
;
;
;
; Now everything else is used by basic.
; First the bit locations, these use bytes 34, 35, 36, 37 and 38
;
$EJECT
OTS BIT 16 ;34.0-ON TIME INSTRUCTION EXECUTED
INPROG BIT 17 ;34.1-INTERRUPT IN PROCESS
INTBIT BIT 18 ;34.2-INTERRUPT SET BIT
ON_ERR BIT 19 ;34.3-ON ERROR EXECUTED
OTI BIT 20 ;34.4-ON TIME INTERRUPT IN PROGRESS
LINEB BIT 21 ;34.5-LINE CHANGE OCCURED
INTPEN BIT 22 ;34.6-INTERRUPT PENDING BIT
CONB BIT 23 ;34.7-CAN CONTINUE IF SET
GTRD BIT 24 ;35.0-READ GET LOCATION
LPB BIT 25 ;35.1-PRINT TO LINE PRINTER PORT
CKS_B BIT 26 ;35.2-FOR PWM INTERRUPT
COB BIT 27 ;35.3-CONSOLE OUT BIT
; 0 = SERIAL PORT
; 1 = LINE PRINTER
COUB BIT 28 ;35.4-USER CONSOLE OUT BIT
; 0 = SERIAL PORT
; 1 = USER DRIVER
INBIT BIT 29 ;35.5-INITIALIZATION BIT
CIUB BIT 30 ;35.6-USER CONSOLE IN BIT
; 0 = SERIAL PORT
; 1 = USER ROUTINE
SPINT BIT 31 ;35.7-SERIAL PORT INTERRUPT
STOPBIT BIT 32 ;36.0-PROGRAM STOP ENCOUNTERED
U_IDL BIT 33 ;36.1-USER IDLE BREAK
INP_B BIT 34 ;36.2-SET DURING INPUT INSTRUCTION
;DCMPXZ BIT 35 ;36.3-DCMPX ZERO FLAG
ARGF BIT 36 ;36.4-ARG STACK HAS A VALUE
RETBIT BIT 37 ;36.5-RET FROM INTERRUPT EXECUTED
I_T0 BIT 38 ;36.6-TRAP INTERRUPT ZERO TO MON
UPB BIT 39 ;36.7-SET WHEN @ IS VALID
JKBIT BIT 40 ;37.0-WB TRIGGER
ENDBIT BIT 41 ;37.1-GET END OF PROGRAM
UBIT BIT 42 ;37.2-FOR DIM STATEMENT
ISAV BIT 43 ;37.3-SAVE INTERRUPT STATUS
BO BIT 44 ;37.4-BUBBLE OUTPUT
XBIT BIT 45 ;37.5-EXTERNAL PROGRAM PRESENT
C_BIT BIT 46 ;37.6-SET WHEN CLOCK RUNNING
DIRF BIT 47 ;37.7-DIRECT INPUT MODE
NO_C BIT 48 ;38.0-NO CONTROL C
DRQ BIT 49 ;38.1-DMA ENABLED
BI BIT 50 ;38.2-BUBBLE INPUT
INTELB BIT 51 ;38.3-INTELLIGENT PROM PROGRAMMING
C0ORX1 BIT 52 ;38.4-PRINT FROM ROM OR RAM
CNT_S BIT 53 ;38.5-CONTROL S ENCOUNTERED
ZSURP BIT 54 ;38.6-ZERO SUPRESS
HMODE BIT 55 ;38.7-HEX MODE PRINT
LP BIT P1.7 ;SOFTWARE LINE PRINTER
DACK BIT P1.6 ;DMA ACK
PROMV BIT P1.5 ;TURN ON PROM VOLTAGE
PROMP BIT P1.4 ;PROM PULSE
ALED BIT P1.3 ;ALE DISABLE
T_BIT BIT P1.2 ;I/O TOGGLE BIT
;
$EJECT
;
; The next location is a bit addressable byte counter
;
BABC EQU 39
;
; Now floating point and the other temps
;
; FP Uses to locations 03CH
;
; Now the stack designators.
;
SPSAV EQU 3EH
S_LEN EQU 3FH
T_HH EQU 40H
T_LL EQU 41H
INTXAH EQU 42H
INTXAL EQU 43H
MT1 EQU 45H
MT2 EQU 46H
MILLIV EQU 47H ;TIMER LOCATIONS
TVH EQU 48H
TVL EQU 49H
SAVE_T EQU 4AH
SP_H EQU 4BH ;SERIAL PORT TIME OUT
SP_L EQU 4CH
CMNDSP EQU 4DH ;SYSTEM STACK POINTER
RCAPH2 EQU 0CBH
RCAPL2 EQU 0CAH
IRAMTOP EQU 0FFH ;TOP OF RAM
STACKTP EQU 0FEH ;ARG AND CONTROL STACK TOPS
;
; The character equates
;
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
BELL EQU 07H ;BELL CHARACTER
BS EQU 08H ;BACK SPACE
CNTRLC EQU 03H ;CONTROL C
CNTRLD EQU 04H ;CONTROL D
NULL EQU 00H ;NULL
;
$EJECT
;
; The internal system equates
;
LINLEN EQU 73 ;THE LENGTH OF AN INPUT LINE
EOF EQU 01 ;END OF FILE CHARACTER
ASTKAH EQU 01 ;ASTKA IS IN PAGE 1 OF RAM
CSTKAH EQU 00 ;CSTKA IS IN PAGE 0 OF RAM
FTYPE EQU 01 ;CONTROL STACK "FOR"
GTYPE EQU 02 ;CONTROL STACK "GOSUB"
DTYPE EQU 03 ;DO-WHILE/UNTIL TYPE
ROMADR EQU 8000H ;LOCATION OF ROM
;
; The floating point equates
;
FPSIZ EQU 6 ;NO. OF BYTES IN A FLOATING NUM
DIGIT EQU FPSIZ-2 ;THE MANTISSA OF A FLOATING NUM
STESIZ EQU FPSIZ+3 ;SIZE OF SYMBOL ADJUSTED TABLE ELEMENT
;FP_BASE EQU 1993H ;BASE OF FLOATING POINT ROUTINES
PSTART EQU 512 ;START OF A PROGRAM IN RAM
FSIZE EQU FPSIZ+FPSIZ+2+2+1
;
$EJECT
;**************************************************************
;
USENT: ; User entry jump table
;
;**************************************************************
;
DW CMND1 ;(00, 00H)COMMAND MODE JUMP
DW IFIX ;(01, 01H)CONVERT FP TO INT
DW PUSHAS ;(02, 02H)PUSH VALUE ONTO ARG STACK
DW POPAS ;(03, 03H)POP VALUE OFF ARG STACK
DW PG1 ;(04, 04H)PROGRAM A PROM
DW INLINE ;(05, 05H)INPUT A LINE
DW UPRNT ;(06, 06H)PRINT A LINR
DW CRLF ;(07, 07H)OUTPUT A CRLF
;
;**************************************************************
;
; This is the operation jump table for arithmetics
;
;**************************************************************
;
OPTAB: DW ALPAR ;(08, 08H)LEFT PAREN
DW AEXP ;(09, 09H)EXPONENTAION
DW AMUL ;(10, 0AH)FP MUL
DW AADD ;(11, 0BH)FLOATING POINT ADD
DW ADIV ;(12, 0CH)FLOATING POINT DIVIDE
DW ASUB ;(13, 0DH)FLOATING POINT SUBTRACTION
DW AXRL ;(14, 0EH)XOR
DW AANL ;(15, 0FH)AND
DW AORL ;(16, 10H)OR
DW ANEG ;(17, 11H)NEGATE
DW AEQ ;(18, 12H)EQUAL
DW AGE ;(19, 13H)GREATER THAN OR EQUAL
DW ALE ;(20, 14H)LESS THAN OR EQUAL
DW ANE ;(21, 15H)NOT EQUAL
DW ALT ;(22, 16H)LESS THAN
DW AGT ;(23, 17H)GREATER THAN
;
$EJECT
;***************************************************************
;
; This is the jump table for unary operators
;
;***************************************************************
;
DW AABS ;(24, 18H)ABSOLUTE VALUE
DW AINT ;(25, 19H)INTEGER OPERATOR
DW ASGN ;(26, 1AH)SIGN OPERATOR
DW ANOT ;(27, 1BH)ONE'S COMPLEMENT
DW ACOS ;(28, 1CH)COSINE
DW ATAN ;(29, 1DH)TANGENT
DW ASIN ;(30, 1EH)SINE
DW ASQR ;(31, 1FH)SQUARE ROOT
DW ACBYTE ;(32, 20H)READ CODE
DW AETOX ;(33, 21H)E TO THE X
DW AATAN ;(34, 22H)ARC TANGENT
DW ALN ;(35, 23H)NATURAL LOG
DW ADBYTE ;(36, 24H)READ DATA MEMORY
DW AXBYTE ;(37, 25H)READ EXTERNAL MEMORY
DW PIPI ;(38, 26H)PI
DW ARND ;(39, 27H)RANDOM NUMBER
DW AGET ;(40, 28H)GET INPUT CHARACTER
DW AFREE ;(41, 29H)COMPUTE #BYTES FREE
DW ALEN ;(42, 2AH) COMPUTE LEN OF PORGRAM
DW AXTAL ;(43, 2BH) CRYSTAL
DW PMTOP ;(44, 2CH)TOP OF MEMORY
DW ATIME ;(45, 2DH) TIME
DW A_IE ;(46, 2EH) IE
DW A_IP ;(47, 2FH) IP
DW ATIM0 ;(48, 30H) TIMER 0
DW ATIM1 ;(49, 31H) TIMER 1
DW ATIM2 ;(50, 32H) TIMER 2
DW AT2CON ;(51, 33H) T2CON
DW ATCON ;(52, 34H) TCON
DW ATMOD ;(53, 35H) ATMOD
DW ARCAP2 ;(54, 36H) RCAP2
DW AP1 ;(55, 37H) P1
DW APCON ;(56, 38H) PCON
DW EXPRB ;(57, 39H) EVALUATE AN EXPRESSION
DW AXTAL1 ;(58, 3AH) CALCULATE CRYSTAL
DW LINE ;(59, 3BH) EDIT A LINE
DW PP ;(60, 3CH) PROCESS A LINE
DW UPPL0 ;(61, 3DH) UNPROCESS A LINE
DW VAR ;(62, 3EH) FIND A VARIABLE
DW GC ;(63, 3FH) GET A CHARACTER
DW GCI ;(64, 40H) GET CHARACTER AND INCREMENT
DW INCHAR ;(65, 41H) INPUT A CHARACTER
DW CRUN ;(66, 42H) RUN A PROGRAM
$EJECT
OPBOL: DB 1 ;
;
DB 15 ;LEFT PAREN
DB 14 ;EXPONENTIAN **
DB 10 ;MUL
DB 8 ;ADD
DB 10 ;DIVIDE
DB 8 ;SUB
DB 3 ;XOR
DB 5 ;AND
DB 4 ;OR
DB 12 ;NEGATE
DB 6 ;EQ
DB 6 ;GT
DB 6 ;LT
DB 6 ;NE
DB 6 ;LE
DB 6 ;GE
;
UOPBOL: DB 15 ;AABS
DB 15 ;AAINT
DB 15 ;ASGN
DB 15 ;ANOT
DB 15 ;ACOS
DB 15 ;ATAN
DB 15 ;ASIN
DB 15 ;ASQR
DB 15 ;ACBYTE
DB 15 ;E TO THE X
DB 15 ;AATAN
DB 15 ;NATURAL LOG
DB 15 ;DBYTE
DB 15 ;XBYTE
;
$EJECT
;***************************************************************
;
; The ASCII printed messages.
;
;***************************************************************
;
STP: DB 'STOP"'
;
IAN: DB 'TRY AGAIN"'
;
RDYS: DB 'READY"'
;
INS: DB ' - IN LINE "'
;
;**************************************************************
;
; This is the command jump table
;
;**************************************************************
;
CMNDD: DW CRUN ;RUN
DW CLIST ;LIST
DW CNULL ;NULL
DW CNEW ;NEW
DW CCONT ;CONTINUE
DW CPROG ;PROGRAM A PROM
DW CXFER ;TRANSFER FROM ROM TO RAM
DW CRAM ;RAM MODE
DW CROM ;ROM MODE
DW CIPROG ;INTELLIGENT PROM PROGRAMMING
;
$EJECT
;***************************************************************
;
; This is the statement jump table.
;
;**************************************************************
;
STATD: ;
DW SLET ;LET 80H
DW SCLR ;CLEAR 81H
DW SPUSH ;PUSH VAR 82H
DW SGOTO ;GO TO 83H
DW STONE ;TONE 84H
DW SPH0 ;PRINT MODE 0 85H
DW SUI ;USER INPUT 86H
DW SUO ;USER OUTPUT 87H
DW SPOP ;POP VAR 88H
DW SPRINT ;PRINT 89H
DW SCALL ;CALL 8AH
DW SDIMX ;DIMENSION 8BH
DW STRING ;STRING ALLO 8CH
DW SBAUD ;SET BAUD 8DH
DW SCLOCK ;CLOCK 8EH
DW SPH1 ;PRINT MODE 1 8FH
;
; No direct mode from here on
;
DW SSTOP ;STOP 90H
DW SOT ;ON TIME 91H
DW SONEXT ;ON EXT INT 92H
DW SRETI ;RET FROM INT 93H
DW S_DO ;DO 94H
DW SRESTR ;RESTOR 95H
DW WCR ;REM 96H
DW SNEXT ;NEXT 97H
DW SONERR ;ON ERROR 98H
DW S_ON ;ON 99H
DW SINPUT ;INPUT 9AH
DW SREAD ;READ 9BH
DW FINDCR ;DATA 9CH
DW SRETRN ;RETURN 9DH
DW SIF ;IF 9EH
DW SGOSUB ;GOSUB 9FH
DW SFOR ;FOR A0H
DW SWHILE ;WHILE A1H
DW SUNTIL ;UNTIL A2H
DW CMND1 ;END A3H
DW I_DL ;IDLE A4H
DW ST_A ;STORE AT A5H
DW LD_A ;LOAD AT A6H
DW PGU ;PGM A7H
DW RROM ;RUN A ROM A9H
;
$EJECT
;**************************************************************
;
TOKTAB: ; This is the basic token table
;
;**************************************************************
;
; First the tokens for statements
;
DB 80H ;LET TOKEN
DB 'LET'
;
DB 81H ;CLEAR TOKEN
DB 'CLEAR'
;
DB 82H ;PUSH TOKEN
DB 'PUSH'
;
T_GOTO EQU 83H
;
DB 83H ;GO TO TOKEN
DB 'GOTO'
;
DB 84H ;TOGGLE TOKEN
DB 'PWM'
;
DB 85H ;PRINT HEX MODE 0
DB 'PH0.'
;
DB 86H ;USER IN TOKEN
DB 'UI'
;
DB 87H ;USER OUT TOKEN
DB 'UO'
;
DB 88H ;POP TOKEN
DB 'POP'
;
$EJECT
DB 89H ;PRINT TOKEN
DB 'PRINT'
DB 89H
DB 'P.' ;P. ALSO MEANS PRINT
DB 89H ;? ALSO
DB '?'
;
DB 8AH ;CALL TOKEN
DB 'CALL'
;
DB 8BH ;DIMENSION TOKEN
DB 'DIM'
;
DB 8CH ;STRING TOKEN
DB 'STRING'
;
DB 8DH ;SET BAUD RATE
DB 'BAUD'
;
DB 8EH ;CLOCK
DB 'CLOCK'
;
DB 8FH ;PRINT HEX MODE 1
DB 'PH1.'
;
T_STOP EQU 90H ;STOP TOKEN
DB T_STOP
DB 'STOP'
;
T_DIR EQU T_STOP ;NO DIRECT FROM HERE ON
;
DB T_STOP+1 ;ON TIMER INTERRUPT
DB 'ONTIME'
;
DB T_STOP+2 ;ON EXTERNAL INTERRUPT
DB 'ONEX1'
;
DB T_STOP+3 ;RETURN FROM INTERRUPT
DB 'RETI'
;
DB T_STOP+4 ;DO TOKEN
DB 'DO'
;
DB T_STOP+5 ;RESTORE TOKEN
DB 'RESTORE'
;
$EJECT
T_REM EQU T_STOP+6 ;REMARK TOKEN
DB T_REM
DB 'REM'
;
DB T_REM+1 ;NEXT TOKEN
DB 'NEXT'
;
DB T_REM+2 ;ON ERROR TOKEN
DB 'ONERR'
;
DB T_REM+3 ;ON TOKEN
DB 'ON'
;
DB T_REM+4 ;INPUT
DB 'INPUT'
;
DB T_REM+5 ;READ
DB 'READ'
;
T_DATA EQU T_REM+6 ;DATA
DB T_DATA
DB 'DATA'
;
DB T_DATA+1 ;RETURN
DB 'RETURN'
;
DB T_DATA+2 ;IF
DB 'IF'
;
T_GOSB EQU T_DATA+3 ;GOSUB
DB T_GOSB
DB 'GOSUB'
;
DB T_GOSB+1 ;FOR
DB 'FOR'
;
DB T_GOSB+2 ;WHILE
DB 'WHILE'
;
DB T_GOSB+3 ;UNTIL
DB 'UNTIL'
;
DB T_GOSB+4 ;END
DB 'END'
;
$EJECT
T_LAST EQU T_GOSB+5 ;LAST INITIAL TOKEN
;
T_TAB EQU T_LAST ;TAB TOKEN
DB T_TAB
DB 'TAB'
;
T_THEN EQU T_LAST+1 ;THEN TOKEN
DB T_THEN
DB 'THEN'
;
T_TO EQU T_LAST+2 ;TO TOKEN
DB T_TO
DB 'TO'
;
T_STEP EQU T_LAST+3 ;STEP TOKEN
DB T_STEP
DB 'STEP'
;
T_ELSE EQU T_LAST+4 ;ELSE TOKEN
DB T_ELSE
DB 'ELSE'
;
T_SPC EQU T_LAST+5 ;SPACE TOKEN
DB T_SPC
DB 'SPC'
;
T_CR EQU T_LAST+6
DB T_CR
DB 'CR'
;
DB T_CR+1
DB 'IDLE'
;
DB T_CR+2
DB 'ST@'
;
DB T_CR+3
DB 'LD@'
;
DB T_CR+4
DB 'PGM'
;
DB T_CR+5
DB 'RROM'
;
$EJECT
; Operator tokens
;
T_LPAR EQU 0E0H ;LEFT PAREN
DB T_LPAR
DB '('
;
DB T_LPAR+1 ;EXPONENTIAN
DB '**'
;
DB T_LPAR+2 ;FP MULTIPLY
DB '*'
;
T_ADD EQU T_LPAR+3
DB T_LPAR+3 ;ADD TOKEN
DB '+'
;
DB T_LPAR+4 ;DIVIDE TOKEN
DB '/'
;
T_SUB EQU T_LPAR+5 ;SUBTRACT TOKEN
DB T_SUB
DB '-'
;
DB T_LPAR+6 ;LOGICAL EXCLUSIVE OR
DB '.XOR.'
;
DB T_LPAR+7 ;LOGICAL AND
DB '.AND.'
;
DB T_LPAR+8 ;LOGICAL OR
DB '.OR.'
;
T_NEG EQU T_LPAR+9
;
T_EQU EQU T_LPAR+10 ;EQUAL
DB T_EQU
DB '='
;
DB T_LPAR+11 ;GREATER THAN OR EQUAL
DB '>='
;
DB T_LPAR+12 ;LESS THAN OR EQUAL
DB '<='
;
DB T_LPAR+13 ;NOT EQUAL
DB '<>'
;
DB T_LPAR+14 ;LESS THAN
DB '<'
;
DB T_LPAR+15 ;GREATER THAN
DB '>'
;
;
T_UOP EQU 0B0H ;UNARY OP BASE TOKEN
;
DB T_UOP ;ABS TOKEN
DB 'ABS'
;
DB T_UOP+1 ;INTEGER TOKEN
DB 'INT'
;
DB T_UOP+2 ;SIGN TOKEN
DB 'SGN'
;
DB T_UOP+3 ;GET TOKEN
DB 'NOT'
;
DB T_UOP+4 ;COSINE TOKEN
DB 'COS'
;
DB T_UOP+5 ;TANGENT TOKEN
DB 'TAN'
;
DB T_UOP+6 ;SINE TOKEN
DB 'SIN'
;
DB T_UOP+7 ;SQUARE ROOT TOKEN
DB 'SQR'
;
DB T_UOP+8 ;CBYTE TOKEN
DB 'CBY'
;
DB T_UOP+9 ;EXP (E TO THE X) TOKEN
DB 'EXP'
;
DB T_UOP+10
DB 'ATN'
;
DB T_UOP+11
DB 'LOG'
;
DB T_UOP+12 ;DBYTE TOKEN
DB 'DBY'
;
DB T_UOP+13 ;XBYTE TOKEN
DB 'XBY'
;
T_ULAST EQU T_UOP+14 ;LAST OPERATOR NEEDING PARENS
;
DB T_ULAST
DB 'PI'
;
DB T_ULAST+1 ;RND TOKEN
DB 'RND'
;
DB T_ULAST+2 ;GET TOKEN
DB 'GET'
;
DB T_ULAST+3 ;FREE TOKEN
DB 'FREE'
;
DB T_ULAST+4 ;LEN TOKEN
DB 'LEN'
;
T_XTAL EQU T_ULAST+5 ;CRYSTAL TOKEN
DB T_XTAL
DB 'XTAL'
;
T_MTOP EQU T_ULAST+6 ;MTOP
DB T_MTOP
DB 'MTOP'
;
T_IE EQU T_ULAST+8 ;IE REGISTER
DB T_IE
DB 'IE'
;
T_IP EQU T_ULAST+9 ;IP REGISTER
DB T_IP
DB 'IP'
;
TMR0 EQU T_ULAST+10 ;TIMER 0
DB TMR0
DB 'TIMER0'
;
TMR1 EQU T_ULAST+11 ;TIMER 1
DB TMR1
DB 'TIMER1'
;
TMR2 EQU T_ULAST+12 ;TIMER 2
DB TMR2
DB 'TIMER2'
;
T_TIME EQU T_ULAST+7 ;TIME
DB T_TIME
DB 'TIME'
;
TT2C EQU T_ULAST+13 ;T2CON
DB TT2C
DB 'T2CON'
;
TTC EQU T_ULAST+14 ;TCON
DB TTC
DB 'TCON'
;
TTM EQU T_ULAST+15 ;TMOD
DB TTM
DB 'TMOD'
;
TRC2 EQU T_ULAST+16 ;RCAP2
DB TRC2
DB 'RCAP2'
;
T_P1 EQU T_ULAST+17 ;P1
DB T_P1
DB 'PORT1'
;
T_PC EQU T_ULAST+18 ;PCON
DB T_PC
DB 'PCON'
;
T_ASC EQU T_ULAST+19 ;ASC TOKEN
DB T_ASC
DB 'ASC('
;
T_USE EQU T_ULAST+20 ;USING TOKEN
DB T_USE
DB 'USING('
DB T_USE
DB 'U.('
;
T_CHR EQU T_ULAST+21 ;CHR TOKEN
DB T_CHR
DB 'CHR('
;
$EJECT
T_CMND EQU 0F0H ;COMMAND BASE
;
DB 0F0H ;RUN TOKEN
DB 'RUN'
;
DB 0F1H ;LIST TOKEN
DB 'LIST'
;
DB 0F2H ;NULL TOKEN
DB 'NULL'
;
DB 0F3H ;NEW TOKEN
DB 'NEW'
;
DB 0F4H ;CONTINUE TOKEN
DB 'CONT'
;
DB 0F5H ;PROGRAM TOKEN
DB 'PROG'
;
DB 0F6H ;TRANSFER TOKEN
DB 'XFER'
;
DB 0F7H ;RAM MODE
DB 'RAM'
;
DB 0F8H ;ROM MODE
DB 'ROM'
;
DB 0F9H ;INTELLIGENT PROM PROGRAMMING
DB 'FPROG'
;
DB 0FFH ;END OF TABLE
;
; END OF INCLUDE LOOK52
;$INCLUDE(:F2:LOOK52.SRC)
;
EIG: DB 'EXTRA IGNORED"'
;
EXA: DB 'A-STACK"'
;
EXC: DB 'C-STACK"'
;
$EJECT
;$INCLUDE(:F2:BAS52.RST)
; BEGINNING
;**************************************************************
;
CRST: ; This performs system initialzation, it was moved here so the
; new power on reset functions could be tested in an 8751.
;
;**************************************************************
;
; First, initialize SFR's
;
MOV SCON,#5AH ;INITIALIZE SFR'S
MOV TMOD,#10H
MOV TCON,#54H
MOV T2CON,#34H
; DB 75H ;MOV DIRECT, # OP CODE
; DB 0C8H ;T2CON LOCATION
; DB 34H ;CONFIGURATION BYTE
;
MOV DPTR,#2001H ;READ CODE AT 2001H
CLR A
MOVC A,@A+DPTR
CJNE A,#0AAH,CRST1 ;IF IT IS AN AAH, DO USER RESET
LCALL 2090H
;
CRST1: MOV R0,#IRAMTOP ;PUT THE TOP OF RAM IN R0
CLR A ;ZERO THE ACC
;
CRST2: MOV @R0,A ;CLEAR INTERNAL MEMORY
DJNZ R0,CRST2 ;LOOP TIL DONE
;
; Now, test the external memory
;
MOV SPSAV,#CMNDSP ;SET UP THE STACK
MOV SP,SPSAV
;
MOV BOFAH,#HIGH ROMADR
MOV BOFAL,#LOW ROMADR+17
MOV DPTR,#ROMADR ;GET THE BYTE AT 8000H
MOVX A,@DPTR
CLR C
SUBB A,#31H ;FOR BIAS
MOV MT1,A ;SAVE IN DIRECT MATH LOC
CLR ACC.2 ;SAVE FOR RESET
MOV R7,A ;SAVE IT IN R7
INC DPTR
ACALL L31DPI ;SAVE BAUD RATE
LCALL RCL
INC DPTR ;GET MEMTOP
ACALL L31DPI
MOV DPTR,#5FH ;READ THE EXTERNAL BYTE
MOVX A,@DPTR
MOV DPTR,#0 ;ESTABLISH BASE FOR CLEAR
CJNE A,#0A5H,CRS
MOV A,MT1
CLR ACC.0 ;CLEAR BIT ONE
XRL A,#4H
JZ CR2
;
CRS: CJNE R7,#2,CRS1
SJMP CRS2
CRS1: CJNE R7,#3,CR0
CRS2: ACALL CL_1
SJMP CR1
;
CR0: MOV R3,DPH ;SAVE THE DPTR
MOV R1,DPL
INC DPTR
MOV A,#5AH
MOVX @DPTR,A
MOVX A,@DPTR
CJNE A,#5AH,CR1
CLR A
MOVX @DPTR,A
CJNE R3,#0E0H,CR0
;
CR1: CJNE R3,#03H,CR11 ;NEED THIS MUCH RAM
CR11: JC CRST
MOV DPTR,#MEMTOP ;SAVE MEMTOP
ACALL S31DP2 ;SAVE MEMTOP AND SEED RCELL
ACALL CNEW ;CLEAR THE MEMORY AND SET UP POINTERS
;
CR2: ACALL RC1 ;SET UP STACKS IF NOT DONE
;
LCALL AXTAL0 ;DO THE CRYSTAL
MOV A,MT1 ;GET THE RESET BYTE
CJNE A,#5,CR20
LCALL 4039H
CR20: JNC BG1 ;CHECK FOR 0,1,2,3, OR 4
JNB ACC.0,BG3 ;NO RUN IF WRONG TYPE
MOV DPTR,#ROMADR+16
MOVX A,@DPTR ;READ THE BYTE
CJNE A,#55H,BG3
LJMP CRUN
; START OF BAUD RATE MODIFICATIONS BY DANIEL WALLNER
BG1: CLR A ;DO BAUD RATE
MOV R3,A
MOV R1,A
MOV TL2,A
CLR T2CON.2
JB RXD,$ ;LOOP UNTIL A CHARACTER IS RECEIVED
MOV T2CON,#5
CALL TIB2
JNB RXD,$
MOV T2CON,#34H
CALL RCL ;LOAD THE TIMER
NOP
NOP
; END OF BAUD RATE MODIFICATIONS BY DANIEL WALLNER
BG3: MOV DPTR,#S_N ;GET THE MESSAGE
ACALL CRP ;PRINT IT
LJMP CRAM
; END
;$INCLUDE(:F2:BAS52.RST)
;
$EJECT
;***************************************************************
;
; CIPROG AND CPROG - Program a prom
;
;***************************************************************
;
;$INCLUDE(:F2:BAS52.PGM)
;BEGINNING
PG8: MOV R7,#00H ;PROGRAM ONE BYTE AT A TIME
MOV R6,#01H
MOV R2,#HIGH ROMADR-1
MOV R0,#LOW ROMADR-1;LOAD PROM ADDRESS
ACALL PG101
INC R6
MOV A,RCAPH2
; DB 0E5H ;MOV A DIRECT OP CODE
; DB 0CBH ;ADDRESS OF R2CAP HIGH
ACALL PG101
MOV A,RCAPL2
; DB 0E5H ;MOV A, DIRECT OP CODE
; DB 0CAH ;R2CAP LOW
MOV R6,#3
MOV R1,#LOW MEMTOP-1
MOV R3,#HIGH MEMTOP
ACALL PG101 ;SAVE MEMTOP
SJMP PGR
;
CIPROG: MOV DPTR,#IPROGS ;LOAD IPROG LOCATION
SETB INTELB
SJMP CPROG1 ;GO DO PROG
;
CPROG: MOV DPTR,#PROGS ;LOAD PROG LOCATION
CLR INTELB
;
CPROG1: ACALL LD_T ;LOAD THE TIMER
CLR PROMV ;TURN ON THE PROM VOLTAGE
CALL DELTST ;SEE IF A CR
JNZ PG8 ;SAVE TIMER IF SO
MOV R4,#0FEH
SETB INBIT
ACALL ROMFD ;GET THE ROM ADDRESS OF THE LAST LOCATION
CALL TEMPD ;SAVE THE ADDRESS
MOV A,R4 ;GET COUNT
CPL A
CALL TWO_R2 ;PUT IT ON THE STACK
CALL FP_BASE7 ;OUTPUT IT
ACALL CCAL ;GET THE PROGRAM
ACALL CRLF ;DO CRLF
MOV R0,TEMP4 ;GET ADDRESS
MOV R2,TEMP5
MOV A,#55H ;LOAD SIGNIFIER
INC R6 ;LOAD LEN + 1
CJNE R6,#00,CPROG2
INC R7
CPROG2: ACALL PG102
;
$EJECT
PGR: SETB PROMV
AJMP C_K
;
PG1: MOV P2,R3 ;GET THE BYTE TO PROGRAM
MOVX A,@R1
PG101: LCALL INC3210 ;BUMP POINTERS
PG102: MOV R5,#1 ;SET UP INTELLIGENT COUMTER
;
PG2: MOV R4,A ;SAVE THE BYTE IN R4
ACALL PG7 ;PROGRAM THE BYTE
ACALL PG9
JB INTELB,PG4 ;SEE IF INTELLIGENT PROGRAMMING
;
PG3: XRL A,R4
JNZ PG6 ;ERROR IF NOT THE SAME
CALL DEC76 ;BUMP THE COUNTERS
JNZ PG1 ;LOOP IF NOT DONE
ANL PSW,#11100111B ;INSURE RB0
PG31: RET
;
PG4: XRL A,R4 ;SEE IF PROGRAMMED
JNZ PG5 ;JUMP IF NOT
MOV A,R4 ;GET THE DATA BACK
ACALL PG7 ;PROGRAM THE LOCATION
PG41: ACALL ZRO ;AGAIN
ACALL ZRO ;AND AGAIN
ACALL ZRO ;AND AGAIN
DJNZ R5,PG41 ;KEEP DOING IT
ACALL PG9 ;RESET PROG
SJMP PG3 ;FINISH THE LOOP
;
PG5: INC R5 ;BUMP THE COUNTER
MOV A,R4 ;GET THE BYTE
CJNE R5,#25,PG2 ;SEE IF TRIED 25 TIMES
;
PG6: SETB PROMV ;TURN OFF PROM VOLTAGE
MOV PSW,#0 ;INSURE RB0
JNB DIRF,PG31 ;EXIT IF IN RUN MODE
MOV DPTR,#E16X ;PROGRAMMING ERROR
;
ERRLK: LJMP ERROR ;PROCESS THE ERROR
;
$EJECT
PG7: MOV P0,R0 ;SET UP THE PORTS
MOV P2,R2 ;LATCH LOW ORDER ADDRESS
ACALL PG11 ;DELAY FOR 8748/9
CLR ALED
MOV P0,A ;PUT DATA ON THE PORT
;
ZRO: NOP ;SETTLEING TIME + FP ZERO
NOP
NOP
NOP
NOP
NOP
ACALL PG11 ;DELAY A WHILE
CLR PROMP ;START PROGRAMMING
ACALL TIMER_LOAD ;START THE TIMER
JNB TF1,$ ;WAIT FOR PART TO PROGRAM
RET ;EXIT
;
PG9: SETB PROMP
ACALL PG11 ;DELAY FOR A WHILE
JNB P3.2,$ ;LOOP FOR EEPROMS
MOV P0,#0FFH
CLR P3.7 ;LOWER READ
ACALL PG11
MOV A,P0 ;READ THE PORT
SETB P3.7
SETB ALED
RET
;
PG11: MOV TEMP5,#12 ;DELAY 30uS AT 12 MHZ
DJNZ TEMP5,$
RET
;
;END
;$INCLUDE(:F2:BAS52.PGM)
$EJECT
;**************************************************************
;
PGU: ;PROGRAM A PROM FOR THE USER
;
;**************************************************************
;
CLR PROMV ;TURN ON THE VOLTAGE
MOV PSW,#00011000B ;SELECT RB3
ACALL PG1 ;DO IT
SETB PROMV ;TURN IT OFF
RET
;
;
;*************************************************************
;
CCAL: ; Set up for prom moves
; R3:R1 gets source
; R7:R6 gets # of bytes
;
;*************************************************************
;
ACALL GETEND ;GET THE LAST LOCATION
INC DPTR ;BUMP TO LOAD EOF
MOV R3,BOFAH
MOV R1,BOFAL ;RESTORE START
CLR C ;PREPARE FOR SUBB
MOV A,DPL ;SUB DPTR - BOFA > R7:R6
SUBB A,R1
MOV R6,A
MOV A,DPH
SUBB A,R3
MOV R7,A
CCAL1: RET
;
;
;$INCLUDE(:F2:BAS52.TL)
;BEGINNING
;**************************************************************
;
TIMER_LOAD:; Load the timer
;
;*************************************************************
;
ACALL CCAL1 ;DELAY FOUR CLOCKS
TIMER_LOAD1:
CLR TR1 ;STOP IT WHILE IT'S LOADED
MOV TH1,T_HH
MOV TL1,T_LL
CLR TF1 ;CLEAR THE OVERFLOW FLAG
SETB TR1 ;START IT NOW
RET
;
;END
;$INCLUDE(:F2:BAS52.TL)
$EJECT
;***************************************************************
;
CROM: ; The command action routine - ROM - Run out of rom
;
;***************************************************************
;
CLR CONB ;CAN'T CONTINUE IF MODE CHANGE
ACALL RO1 ;DO IT
;
C_K: LJMP CL3 ;EXIT
;
;RO1: CALL INTGER ;SEE IF INTGER PRESENT
; MOV R4,R0B0 ;SAVE THE NUMBER
; JNC $+4
; MOV R4,#01H ;ONE IF NO INTEGER PRESENT
; CALL ROMFD ;FIND THE PROGRAM
; ACALL ROMFD ;FIND THE PROGRAM
RO1: CALL DELTST
MOV R4,#1
JNC RO11
CALL ONE
MOV R4,A
RO11: ACALL ROMFD
CJNE R4,#0,RFX ;EXIT IF R4 <> 0
INC DPTR ;BUMP PAST TAG
MOV BOFAH,DPH ;SAVE THE ADDRESS
MOV BOFAL,DPL
RET
;
ROMFD: MOV DPTR,#ROMADR+16 ;START OF USER PROGRAM
;
RF1: MOVX A,@DPTR ;GET THE BYTE
CJNE A,#55H,RF3 ;SEE IF PROPER TAG
DJNZ R4,RF2 ;BUMP COUNTER
;
RFX: RET ;DPTR HAS THE START ADDRESS
;
RF2: INC DPTR ;BUMP PAST TAG
ACALL G5
INC DPTR ;BUMP TO NEXT PROGRAM
SJMP RF1 ;DO IT AGAIN
;
RF3: JBC INBIT,RFX ;EXIT IF SET
;
NOGO: MOV DPTR,#NOROM
AJMP ERRLK
;
$EJECT
;***************************************************************
;
L20DPI: ; load R2:R0 with the location the DPTR is pointing to
;
;***************************************************************
;
MOVX A,@DPTR
MOV R2,A
INC DPTR
MOVX A,@DPTR
MOV R0,A
RET ;DON'T BUMP DPTR
;
;***************************************************************
;
X31DP: ; swap R3:R1 with DPTR
;
;***************************************************************
;
XCH A,R3
XCH A,DPH
XCH A,R3
XCH A,R1
XCH A,DPL
XCH A,R1
RET
;
;***************************************************************
;
LD_T: ; Load the timer save location with the value the DPTR is
; pointing to.
;
;****************************************************************
;
MOVX A,@DPTR
MOV T_HH,A
INC DPTR
MOVX A,@DPTR
MOV T_LL,A
RET
;
$EJECT
;
;***************************************************************
;
;GETLIN - FIND THE LOCATION OF THE LINE NUMBER IN R3:R1
; IF ACC = 0 THE LINE WAS NOT FOUND I.E. R3:R1
; WAS TOO BIG, ELSE ACC <> 0 AND THE DPTR POINTS
; AT THE LINE THAT IS GREATER THAN OR EQUAL TO THE
; VALUE IN R3:R1.
;
;***************************************************************
;
GETEND: SETB ENDBIT ;GET THE END OF THE PROGRAM
;
GETLIN: CALL DP_B ;GET BEGINNING ADDRESS
;
G1: CALL B_C
JZ G3 ;EXIT WITH A ZERO IN A IF AT END
INC DPTR ;POINT AT THE LINE NUMBER
JB ENDBIT,G2 ;SEE IF WE WANT TO FIND THE END
ACALL DCMPX ;SEE IF (DPTR) = R3:R1
ACALL DECDP ;POINT AT LINE COUNT
MOVX A,@DPTR ;PUT LINE LENGTH INTO ACC
JB UBIT,G3 ;EXIT IF EQUAL
JC G3 ;SEE IF LESS THAN OR ZERO
;
G2: ACALL ADDPTR ;ADD IT TO DPTR
SJMP G1 ;LOOP
;
G3: CLR ENDBIT ;RESET ENDBIT
RET ;EXIT
;
G4: MOV DPTR,#PSTART ;DO RAM
;
G5: SETB ENDBIT
SJMP G1 ;NOW DO TEST
;
$EJECT
;***************************************************************
;
; LDPTRI - Load the DATA POINTER with the value it is pointing
; to - DPH = (DPTR) , DPL = (DPTR+1)
;
; acc gets wasted
;
;***************************************************************
;
LDPTRI: MOVX A,@DPTR ;GET THE HIGH BYTE
PUSH ACC ;SAVE IT
INC DPTR ;BUMP THE POINTER
MOVX A,@DPTR ;GET THE LOW BYTE
MOV DPL,A ;PUT IT IN DPL
POP DPH ;GET THE HIGH BYTE
RET ;GO BACK
;
;***************************************************************
;
;L31DPI - LOAD R3 WITH (DPTR) AND R1 WITH (DPTR+1)
;
;ACC GETS CLOBBERED
;
;***************************************************************
;
L31DPI: MOVX A,@DPTR ;GET THE HIGH BYTE
MOV R3,A ;PUT IT IN THE REG
INC DPTR ;BUMP THE POINTER
MOVX A,@DPTR ;GET THE NEXT BYTE
MOV R1,A ;SAVE IT
RET
;
;***************************************************************
;
;DECDP - DECREMENT THE DATA POINTER - USED TO SAVE SPACE
;
;***************************************************************
;
DECDP2: ACALL DECDP
;
DECDP: XCH A,DPL ;GET DPL
JNZ DECDP1 ;BUMP IF ZERO
DEC DPH
DECDP1: DEC A ;DECREMENT IT
XCH A,DPL ;GET A BACK
RET ;EXIT
;
$EJECT
;***************************************************************
;
;DCMPX - DOUBLE COMPARE - COMPARE (DPTR) TO R3:R1
;R3:R1 - (DPTR) = SET CARRY FLAG
;
;IF R3:R1 > (DPTR) THEN C = 0
;IF R3:R1 < (DPTR) THEN C = 1
;IF R3:R1 = (DPTR) THEN C = 0
;
;***************************************************************
;
DCMPX: CLR UBIT ;ASSUME NOT EQUAL
MOVX A,@DPTR ;GET THE BYTE
CJNE A,R3B0,D1 ;IF A IS GREATER THAN R3 THEN NO CARRY
;WHICH IS R3<@DPTR = NO CARRY AND
;R3>@DPTR CARRY IS SET
INC DPTR ;BUMP THE DATA POINTER
MOVX A,@DPTR ;GET THE BYTE
ACALL DECDP ;PUT DPTR BACK
CJNE A,R1B0,D1 ;DO THE COMPARE
CPL C ;FLIP CARRY
;
CPL UBIT ;SET IT
D1: CPL C ;GET THE CARRY RIGHT
RET ;EXIT
;
;***************************************************************
;
; ADDPTR - Add acc to the dptr
;
; acc gets wasted
;
;***************************************************************
;
ADDPTR: ADD A,DPL ;ADD THE ACC TO DPL
MOV DPL,A ;PUT IT IN DPL
JNC ADDPTR1 ;JUMP IF NO CARRY
INC DPH ;BUMP DPH
ADDPTR1:RET ;EXIT
;
$EJECT
;*************************************************************
;
LCLR: ; Set up the storage allocation
;
;*************************************************************
;
ACALL ICLR ;CLEAR THE INTERRUPTS
ACALL G4 ;PUT END ADDRESS INTO DPTR
MOV A,#6 ;ADJUST MATRIX SPACE
ACALL ADDPTR ;ADD FOR PROPER BOUNDS
ACALL X31DP ;PUT MATRIX BOUNDS IN R3:R1
MOV DPTR,#MT_ALL ;SAVE R3:R1 IN MATRIX FREE SPACE
ACALL S31DP ;DPTR POINTS TO MEMTOP
ACALL L31DPI ;LOAD MEMTOP INTO R3:R1
MOV DPTR,#STR_AL ;GET MEMORY ALLOCATED FOR STRINGS
ACALL LDPTRI
CALL DUBSUB ;R3:R1 = MEMTOP - STRING ALLOCATION
MOV DPTR,#VARTOP ;SAVE R3:R1 IN VARTOP
;
; FALL THRU TO S31DP2
;
;***************************************************************
;
;S31DP - STORE R3 INTO (DPTR) AND R1 INTO (DPTR+1)
;
;ACC GETS CLOBBERED
;
;***************************************************************
;
S31DP2: ACALL S31DP ;DO IT TWICE
;
S31DP: MOV A,R3 ;GET R3 INTO ACC
MOVX @DPTR,A ;STORE IT
INC DPTR ;BUMP DPTR
MOV A,R1 ;GET R1
MOVX @DPTR,A ;STORE IT
INC DPTR ;BUMP IT AGAIN TO SAVE PROGRAM SPACE
RET ;GO BACK
;
;
;***************************************************************
;
STRING: ; Allocate memory for strings
;
;***************************************************************
;
LCALL TWO ;R3:R1 = NUMBER, R2:R0 = LEN
MOV DPTR,#STR_AL ;SAVE STRING ALLOCATION
ACALL S31DP
INC R6 ;BUMP
MOV S_LEN,R6 ;SAVE STRING LENGTH
AJMP RCLEAR ;CLEAR AND SET IT UP
;
$EJECT
;***************************************************************
;
; F_VAR - Find the variable in symbol table
; R7:R6 contain the variable name
; If not found create a zero entry and set the carry
; R2:R0 has the address of variable on return
;
;***************************************************************
;
F_VAR: MOV DPTR,#VARTOP ;PUT VARTOP IN DPTR
ACALL LDPTRI
ACALL DECDP2 ;ADJUST DPTR FOR LOOKUP
;
F_VAR0: MOVX A,@DPTR ;LOAD THE VARIABLE
JZ F_VAR2 ;TEST IF AT THE END OF THE TABLE
INC DPTR ;BUMP FOR NEXT BYTE
CJNE A,R7B0,F_VAR1 ;SEE IF MATCH
MOVX A,@DPTR ;LOAD THE NAME
CJNE A,R6B0,F_VAR1
;
; Found the variable now adjust and put in R2:R0
;
DLD: MOV A,DPL ;R2:R0 = DPTR-2
SUBB A,#2
MOV R0,A
MOV A,DPH
SUBB A,#0 ;CARRY IS CLEARED
MOV R2,A
RET
;
F_VAR1: MOV A,DPL ;SUBTRACT THE STACK SIZE+ADJUST
CLR C
SUBB A,#STESIZ
MOV DPL,A ;RESTORE DPL
JNC F_VAR0
DEC DPH
SJMP F_VAR0 ;CONTINUE COMPARE
;
$EJECT
;
; Add the entry to the symbol table
;
F_VAR2: LCALL R76S ;SAVE R7 AND R6
CLR C
ACALL DLD ;BUMP THE POINTER TO GET ENTRY ADDRESS
;
; Adjust pointer and save storage allocation
; and make sure we aren't wiping anything out
; First calculate new storage allocation
;
MOV A,R0
SUBB A,#STESIZ-3 ;NEED THIS MUCH RAM
MOV R1,A
MOV A,R2
SUBB A,#0
MOV R3,A
;
; Now save the new storage allocation
;
MOV DPTR,#ST_ALL
CALL S31DP ;SAVE STORAGE ALLOCATION
;
; Now make sure we didn't blow it, by wiping out MT_ALL
;
ACALL DCMPX ;COMPARE STORAGE ALLOCATION
JC CCLR3 ;ERROR IF CARRY
SETB C ;DID NOT FIND ENTRY
RET ;EXIT IF TEST IS OK
;
$EJECT
;***************************************************************
;
; Command action routine - NEW
;
;***************************************************************
;
CNEW: MOV DPTR,#PSTART ;SAVE THE START OF PROGRAM
MOV A,#EOF ;END OF FILE
MOVX @DPTR,A ;PUT IT IN MEMORY
;
; falls thru
;
;*****************************************************************
;
; The statement action routine - CLEAR
;
;*****************************************************************
;
CNEW1: CLR LINEB ;SET UP FOR RUN AND GOTO
;
RCLEAR: ACALL LCLR ;CLEAR THE INTERRUPTS, SET UP MATRICES
MOV DPTR,#MEMTOP ;PUT MEMTOP IN R3:R1
ACALL L31DPI
ACALL G4 ;DPTR GETS END ADDRESS
ACALL CL_1 ;CLEAR THE MEMORY
;
RC1: MOV DPTR,#STACKTP ;POINT AT CONTROL STACK TOP
CLR A ;CONTROL UNDERFLOW
;
RC2: MOVX @DPTR,A ;SAVE IN MEMORY
MOV CSTKA,#STACKTP
MOV ASTKA,#STACKTP
CLR CONB ;CAN'T CONTINUE
RET
;
$EJECT
;***************************************************************
;
; Loop until the memory is cleared
;
;***************************************************************
;
CL_1: INC DPTR ;BUMP MEMORY POINTER
CLR A ;CLEAR THE MEMORY
MOVX @DPTR,A ;CLEAR THE RAM
MOVX A,@DPTR ;READ IT
JNZ CCLR3 ;MAKE SURE IT IS CLEARED
MOV A,R3 ;GET POINTER FOR COMPARE
CJNE A,DPH,CL_1 ;SEE TO LOOP
MOV A,R1 ;NOW TEST LOW BYTE
CJNE A,DPL,CL_1
;
CL_2: RET
;
CCLR3: JMP TB ;ALLOCATED MEMORY DOESN'T EXSIST
;
;**************************************************************
;
SCLR: ;Entry point for clear return
;
;**************************************************************
;
CALL DELTST ;TEST FOR A CR
JNC RCLEAR
CALL GCI1 ;BUMP THE TEST POINTER
CJNE A,#'I',RC1 ;SEE IF I, ELSE RESET THE STACK
;
;**************************************************************
;
ICLR: ; Clear interrupts and system garbage
;
;**************************************************************
;
JNB INTBIT,ICLR1 ;SEE IF BASIC HAS INTERRUPTS
CLR EX1 ;IF SO, CLEAR INTERRUPTS
ICLR1: ANL 34,#00100000B ;SET INTERRUPTS + CONTINUE
RETI
;
$EJECT
;***************************************************************
;
;OUTPUT ROUTINES
;
;***************************************************************
;
CRLF2: ACALL CRLF ;DO TWO CRLF'S
;
CRLF: MOV R5,#CR ;LOAD THE CR
ACALL TEROT ;CALL TERMINAL OUT
MOV R5,#LF ;LOAD THE LF
AJMP TEROT ;OUTPUT IT AND RETURN
;
;PRINT THE MESSAGE ADDRESSED IN ROM OR RAM BY THE DPTR
;ENDS WITH THE CHARACTER IN R4
;DPTR HAS THE ADDRESS OF THE TERMINATOR
;
CRP: ACALL CRLF ;DO A CR THEN PRINT ROM
;
ROM_P: CLR A ;CLEAR A FOR LOOKUP
MOVC A,@A+DPTR ;GET THE CHARACTER
CLR ACC.7 ;CLEAR MS BIT
CJNE A,#'"',ROM_P1 ;EXIT IF TERMINATOR
RET
ROM_P1: SETB C0ORX1
;
PN1: MOV R5,A ;OUTPUT THE CHARACTER
ACALL TEROT
INC DPTR ;BUMP THE POINTER
SJMP PN0
;
UPRNT: ACALL X31DP
;
PRNTCR: MOV R4,#CR ;OUTPUT UNTIL A CR
;
PN0: JBC C0ORX1,ROM_P
MOVX A,@DPTR ;GET THE RAM BYTE
JZ PN01
CJNE A,R4B0,PN02 ;SEE IF THE SAME AS TERMINATOR
PN01: RET ;EXIT IF THE SAME
PN02: CJNE A,#CR,PN1 ;NEVER PRINT A CR IN THIS ROUTINE
LJMP E1XX ;BAD SYNTAX
;
$EJECT
;***************************************************************
;
; INLINE - Input a line to IBUF, exit when a CR is received
;
;***************************************************************
;
INL2: CJNE A,#CNTRLD,INL2B ;SEE IF A CONTROL D
;
INL0: ACALL CRLF ;DO A CR
;
INLINE: MOV P2,#HIGH IBUF ;IBUF IS IN THE ZERO PAGE
MOV R0,#LOW IBUF ;POINT AT THE INPUT BUFFER
;
INL1: ACALL INCHAR ;GET A CHARACTER
MOV R5,A ;SAVE IN R5 FOR OUTPUT
CJNE A,#7FH,INL2 ;SEE IF A DELETE CHARACTER
CJNE R0,#LOW IBUF,INL6
INL11: MOV R5,#BELL ;OUTPUT A BELL
;
INLX: ACALL TEROT ;OUTPUT CHARACTER
SJMP INL1 ;DO IT AGAIN
;
INL2B: MOVX @R0,A ;SAVE THE CHARACTER
CJNE A,#CR,INL2B1 ;IS IT A CR
AJMP CRLF ;OUTPUT A CRLF AND EXIT
INL2B1: CJNE A,#20H,INL2B2
INL2B2: JC INLX ;ONLY ECHO CONTROL CHARACTERS
INC R0 ;BUMP THE POINTER
CJNE R0,#IBUF+79,INLX
DEC R0 ;FORCE 79
SJMP INL11 ;OUTPUT A BELL
;
INL6: DEC R0 ;DEC THE RAM POINTER
MOV R5,#BS ;OUTPUT A BACK SPACE
ACALL TEROT
ACALL STEROT ;OUTPUT A SPACE
MOV R5,#BS ;ANOTHER BACK SPACE
SJMP INLX ;OUTPUT IT
;
PTIME: DB 128-2 ; PROM PROGRAMMER TIMER
DB 00H
DB 00H
DB 50H
DB 67H
DB 41H
;
$EJECT
;$INCLUDE(:F2:BAS52.OUT)
;BEGINNING
;***************************************************************
;
; TEROT - Output a character to the system console
; update PHEAD position.
;
;***************************************************************
;
STEROT: MOV R5,#' ' ;OUTPUT A SPACE
;
TEROT: PUSH ACC ;SAVE THE ACCUMULATOR
PUSH DPH ;SAVE THE DPTR
PUSH DPL
TEROT01:JNB CNT_S,TEROT02 ;WAIT FOR A CONTROL Q
ACALL BCK ;GET SERIAL STATUS
SJMP TEROT01
TEROT02:MOV A,R5 ;PUT OUTPUT BYTE IN A
JNB BO,TEROT03 ;CHECK FOR MONITOR
LCALL 2040H ;DO THE MONITOR
AJMP TEROT1 ;CLEAN UP
TEROT03:JNB COUB,TEROT04 ;SEE IF USER WANTS OUTPUT
LCALL 4030H
AJMP TEROT1
TEROT04:JNB UPB,T_1 ;NO AT IF NO XBIT
JNB LPB,T_1 ;AT PRINT
LCALL 403CH ;CALL AT LOCATION
AJMP TEROT1 ;FINISH OFF OUTPUT
;
T_1: JNB COB,TXX ;SEE IF LIST SET
MOV DPTR,#SPV ;LOAD BAUD RATE
ACALL LD_T
CLR LP ;OUTPUT START BIT
ACALL TIMER_LOAD ;LOAD AND START THE TIMER
MOV A,R5 ;GET THE OUTPUT BYTE
SETB C ;SET CARRY FOR LAST OUTPUT
MOV R5,#9 ;LOAD TIMER COUNTDOWN
;
LTOUT1: RRC A ;ROTATE A
JNB TF1,$ ;WAIT TILL TIMER READY
MOV LP,C ;OUTPUT THE BIT
ACALL TIMER_LOAD ;DO THE NEXT BIT
DJNZ R5,LTOUT1 ;LOOP UNTIL DONE
JNB TF1,$ ;FIRST STOP BIT
ACALL TIMER_LOAD
JNB TF1,$ ;SECOND STOP BIT
MOV R5,A ;RESTORE R5
SJMP TEROT1 ;BACK TO TEROT
;
$EJECT
TXX: JNB TI,$ ;WAIT FOR TRANSMIT READY
CLR TI
MOV SBUF,R5 ;SEND OUT THE CHARACTER
;
TEROT1: CJNE R5,#CR,TEROT11 ;SEE IF A CR
MOV PHEAD,#00H ;IF A CR, RESET PHEAD AND
;
TEROT11:CJNE R5,#LF,NLC ;SEE IF A LF
MOV A,NULLCT ;GET THE NULL COUNT
JZ NLC ;NO NULLS IF ZERO
;
TEROT2: MOV R5,#NULL ;PUT THE NULL IN THE OUTPUT REGISTER
ACALL TEROT ;OUTPUT THE NULL
DEC A ;DECREMENT NULL COUNT
JNZ TEROT2 ;LOOP UNTIL DONE
;
NLC: CJNE R5,#BS,NLC1 ;DEC PHEAD IF A BACKSPACE
DEC PHEAD
NLC1: CJNE R5,#20H,NLC2 ;IS IT A PRINTABLE CHARACTER?
NLC2: JC NLC3 ;DON'T INCREMENT PHEAD IF NOT PRINTABLE
INC PHEAD ;BUMP PRINT HEAD
NLC3: POP DPL ;RESTORE DPTR
POP DPH
POP ACC ;RESTORE ACC
RET ;EXIT
;
;END
;$INCLUDE(:F2:BAS52.OUT)
;
BCK: ACALL CSTS ;CHECK STATUS
JNC CI_RET1 ;EXIT IF NO CHARACTER
;
$EJECT
;***************************************************************
;
;INPUTS A CHARACTER FROM THE SYSTEM CONSOLE.
;
;***************************************************************
;
INCHAR: JNB BI,INCHAR1 ;CHECK FOR MONITOR (BUBBLE)
LCALL 2060H
SJMP INCH1
INCHAR1:JNB CIUB,INCHAR2 ;CHECK FOR USER
LCALL 4033H
SJMP INCH1
INCHAR2:JNB RI,$ ;WAIT FOR RECEIVER READY.
MOV A,SBUF
CLR RI ;RESET READY
CLR ACC.7 ;NO BIT 7
;
INCH1: CJNE A,#13H,INCH11
SETB CNT_S
INCH11: CJNE A,#11H,INCH12
CLR CNT_S
INCH12: CJNE A,#CNTRLC,INCH13
JNB NO_C,C_EX ;TRAP NO CONTROL C
RET
;
INCH13: CLR JKBIT
CJNE A,#17H,CI_RET ;CONTROL W
SETB JKBIT
;
CI_RET: SETB C ;CARRY SET IF A CHARACTER
CI_RET1:RET ;EXIT
;
;*************************************************************
;
;RROM - The Statement Action Routine RROM
;
;*************************************************************
;
RROM: SETB INBIT ;SO NO ERRORS
ACALL RO1 ;FIND THE LINE NUMBER
JBC INBIT,CRUN
RET ;EXIT
;
$EJECT
;***************************************************************
;
CSTS: ; RETURNS CARRY = 1 IF THERE IS A CHARACTER WAITING FROM
; THE SYSTEM CONSOLE. IF NO CHARACTER THE READY CHARACTER
; WILL BE CLEARED
;
;***************************************************************
;
JNB BI,CSTS1 ;BUBBLE STATUS
LJMP 2068H
CSTS1: JNB CIUB,CSTS2 ;SEE IF EXTERNAL CONSOLE
LJMP 4036H
CSTS2: MOV C,RI
RET
;
C_EX0: MOV DPTR,#WB ;EGO MESSAGE
ACALL ROM_P
;
C_EX: CLR CNT_S ;NO OUTPUT STOP
LCALL SPRINT1 ;ASSURE CONSOLE
ACALL CRLF
JBC JKBIT,C_EX0
;
JNB DIRF,SSTOP0
AJMP C_K ;CLEAR COB AND EXIT
;
T_CMP: MOV A,TVH ;COMPARE TIMER TO SP_H AND SP_L
MOV R1,TVL
CJNE A,TVH,T_CMP
XCH A,R1
SUBB A,SP_L
MOV A,R1
SUBB A,SP_H
RET
;
;*************************************************************
;
BR0: ; Trap the timer interrupt
;
;*************************************************************
;
CALL T_CMP ;COMPARE TIMER
JC BCHR1 ;EXIT IF TEST FAILS
SETB OTI ;DOING THE TIMER INTERRUPT
CLR OTS ;CLEAR TIMER BIT
MOV C,INPROG ;SAVE IN PROGRESS
MOV ISAV,C
MOV DPTR,#TIV
SJMP BR2
;
$EJECT
;***************************************************************
;
; The command action routine - RUN
;
;***************************************************************
;
CRUN: LCALL CNEW1 ;CLEAR THE STORAGE ARRAYS
ACALL SRESTR1 ;GET THE STARTING ADDRESS
ACALL B_C
JZ CMNDLK ;IF NULL GO TO COMMAND MODE
;
ACALL T_DP
ACALL B_TXA ;BUMP TO STARTING LINE
;
CILOOP: ACALL SP0 ;DO A CR AND A LF
CILOOP1:CLR DIRF ;NOT IN DIRECT MODE
;
;INTERPERTER DRIVER
;
ILOOP: MOV SP,SPSAV ;RESTORE THE STACK EACH TIME
JB DIRF,ILOOP1 ;NO INTERRUPTS IF IN DIRECT MODE
MOV INTXAH,TXAH ;SAVE THE TEXT POINTER
MOV INTXAL,TXAL
ILOOP1: LCALL BCK ;GET CONSOLE STATUS
JB DIRF,I_L ;DIRECT MODE
ANL C,/GTRD ;SEE IF CHARACTER READY
JNC BCHR ;NO CHARACTER = NO CARRY
;
; DO TRAP OPERATION
;
MOV DPTR,#GTB ;SAVE TRAP CHARACTER
MOVX @DPTR,A
SETB GTRD ;SAYS READ A BYTE
;
BCHR: JB OTI,I_L ;EXIT IF TIMER INTERRUPT IN PROGRESS
JB OTS,BR0 ;TEST TIMER VALUE IF SET
BCHR1: JNB INTPEN,I_L ;SEE IF INTERRUPT PENDING
JB INPROG,I_L ;DON'T DO IT AGAIN IF IN PROGRESS
MOV DPTR,#INTLOC ;POINT AT INTERRUPT LOCATION
;
BR2: MOV R4,#GTYPE ;SETUP FOR A FORCED GOSUB
ACALL SGS1 ;PUT TXA ON STACK
SETB INPROG ;INTERRUPT IN PROGRESS
;
ERL4: CALL L20DPI
AJMP D_L1 ;GET THE LINE NUMBER
;
I_L: ACALL ISTAT ;LOOP
ACALL CLN_UP ;FINISH IT OFF
JNC ILOOP ;LOOP ON THE DRIVER
JNB DIRF,CMNDLK ;CMND1 IF IN RUN MODE
LJMP CMNDR ;DON'T PRINT READY
;
CMNDLK: JMP CMND1 ;DONE
$EJECT
;**************************************************************
;
; The Statement Action Routine - STOP
;
;**************************************************************
;
SSTOP: ACALL CLN_UP ;FINISH OFF THIS LINE
MOV INTXAH,TXAH ;SAVE TEXT POINTER FOR CONT
MOV INTXAL,TXAL
;
SSTOP0: SETB CONB ;CONTINUE WILL WORK
MOV DPTR,#STP ;PRINT THE STOP MESSAGE
SETB STOPBIT ;SET FOR ERROR ROUTINE
JMP ERRS ;JUMP TO ERROR ROUTINE
;
$EJECT
;**************************************************************
;
; ITRAP - Trap special function register operators
;
;**************************************************************
;
ITRAP: CJNE A,#TMR0,ITRAP1 ;TIMER 0
MOV TH0,R3
MOV TL0,R1
RET
;
ITRAP1: CJNE A,#TMR1,ITRAP2 ;TIMER 1
MOV TH1,R3
MOV TL1,R1
RET
;
ITRAP2: CJNE A,#TMR2,ITRAP3 ;TIMER 2
MOV TH2,R3
MOV TL2,R1
; DB 8BH ;MOV R3 DIRECT OP CODE
; DB 0CDH ;T2H LOCATION
; DB 89H ;MOV R1 DIRECT OP CODE
; DB 0CCH ;T2L LOCATION
RET
;
ITRAP3: CJNE A,#TRC2,RCL1 ;RCAP2 TOKEN
RCL: MOV RCAPH2,R3
MOV RCAPL2,R1
; DB 8BH ;MOV R3 DIRECT OP CODE
; DB 0CBH ;RCAP2H LOCATION
; DB 89H ;MOV R1 DIRECT OP CODE
; DB 0CAH ;RCAP2L LOCATION
RET
;
RCL1: ACALL R3CK ;MAKE SURE THAT R3 IS ZERO
CJNE A,#TT2C,RCL2
MOV T2CON,R1
; DB 89H ;MOV R1 DIRECT OP CODE
; DB 0C8H ;T2CON LOCATION
RET
;
RCL2: CJNE A,#T_IE,RCL3 ;IE TOKEN
MOV IE,R1
RET
;
RCL3: CJNE A,#T_IP,RCL4 ;IP TOKEN
MOV IP,R1
RET
;
RCL4: CJNE A,#TTC,RCL5 ;TCON TOKEN
MOV TCON,R1
RET
;
RCL5: CJNE A,#TTM,RCL6 ;TMOD TOKEN
MOV TMOD,R1
RET
;
RCL6: CJNE A,#T_P1,T_T2 ;P1 TOKEN
MOV P1,R1
RET
;
;***************************************************************
;
; T_TRAP - Trap special operators
;
;***************************************************************
;
T_T: MOV TEMP5,A ;SAVE THE TOKEN
ACALL GCI1 ;BUMP POINTER
ACALL SLET2 ;EVALUATE AFTER =
MOV A,TEMP5 ;GET THE TOKEN BACK
CJNE A,#T_XTAL,T_T01
LJMP AXTAL1 ;SET UP CRYSTAL
;
T_T01: ACALL IFIXL ;R3:R1 HAS THE TOS
MOV A,TEMP5 ;GET THE TOKEN AGAIN
CJNE A,#T_MTOP,T_T1 ;SEE IF MTOP TOKEN
MOV DPTR,#MEMTOP
CALL S31DP
JMP RCLEAR ;CLEAR THE MEMORY
;
T_T1: CJNE A,#T_TIME,ITRAP ;SEE IF A TIME TOKEN
MOV C,EA ;SAVE INTERRUPTS
CLR EA ;NO TIMER 0 INTERRUPTS DURING LOAD
MOV TVH,R3 ;SAVE THE TIME
MOV TVL,R1
MOV EA,C ;RESTORE INTERRUPTS
RET ;EXIT
;
T_T2: CJNE A,#T_PC,INTERX ;PCON TOKEN
MOV PCON,R1
; DB 89H ;MOV DIRECT, R1 OP CODE
; DB 87H ;ADDRESS OF PCON
RET ;EXIT
;
T_TRAP: CJNE A,#T_ASC,T_T ;SEE IF ASC TOKEN
ACALL IGC ;EAT IT AND GET THE NEXT CHARACTER
CJNE A,#'$',INTERX ;ERROR IF NOT A STRING
ACALL CSY ;CALCULATE ADDRESS
ACALL X3120
CALL TWO_EY
ACALL SPEOP1 ;EVALUATE AFTER EQUALS
AJMP ISTAX1 ;SAVE THE CHARACTER
;
$EJECT
;**************************************************************
;
;INTERPERT THE STATEMENT POINTED TO BY TXAL AND TXAH
;
;**************************************************************
;
ISTAT: ACALL GC ;GET THR FIRST CHARACTER
JNB XBIT,IAT ;TRAP TO EXTERNAL RUN PACKAGE
CJNE A,#20H,ISTAT1
ISTAT1: JNC IAT
LCALL 2070H ;LET THE USER SET UP THE DPTR
ACALL GCI1
ANL A,#0FH ;STRIP OFF BIAS
SJMP ISTA1
;
IAT: CJNE A,#T_XTAL,IAT1
IAT1: JNC T_TRAP
JNB ACC.7,SLET ;IMPLIED LET IF BIT 7 NOT SET
CJNE A,#T_UOP+12,ISTAX ;DBYTE TOKEN
ACALL SPEOP ;EVALUATE SPECIAL OPERATOR
ACALL R3CK ;CHECK LOCATION
MOV @R1,A ;SAVE IT
RET
;
ISTAX: CJNE A,#T_UOP+13,ISTAY ;XBYTE TOKEN
ACALL SPEOP
;
ISTAX1: MOV P2,R3
MOVX @R1,A
RET
;
ISTAY: CJNE A,#T_CR+1,ISTAY1;TRAP NEW OPERATORS
ISTAY1: JC I_S
CJNE A,#0B0H,ISTAY2 ;SEE IF TOO BIG
ISTAY2: JNC INTERX
ADD A,#0F9H ;BIAS FOR LOOKUP TABLE
SJMP ISTA0 ;DO THE OPERATION
;
I_S: CJNE A,#T_LAST,I_S1 ;MAKE SURE AN INITIAL RESERVED WORD
I_S1: JC INTERX1 ;ERROR IF NOT
;
INTERX: LJMP E1XX ;SYNTAX ERROR
;
INTERX1:JNB DIRF,ISTA0 ;EXECUTE ALL STATEMENTS IF IN RUN MODE
CJNE A,#T_DIR,INTERX2;SEE IF ON TOKEN
INTERX2:JC ISTA0 ;OK IF DIRECT
CJNE A,#T_GOSB+1,INTERX3;SEE IF FOR
SJMP ISTA0 ;FOR IS OK
INTERX3:CJNE A,#T_REM+1,INTERX4 ;NEXT IS OK
SJMP ISTA0
INTERX4:CJNE A,#T_STOP+6,INTERX ;SO IS REM
;
$EJECT
ISTA0: ACALL GCI1 ;ADVANCE THE TEXT POINTER
MOV DPTR,#STATD ;POINT DPTR TO LOOKUP TABLE
CJNE A,#T_GOTO-3,ISTA01;SEE IF LET TOKEN
SJMP ISTAT ;WASTE LET TOKEN
ISTA01: ANL A,#3FH ;STRIP OFF THE GARBAGE
;
ISTA1: RL A ;ROTATE FOR OFFSET
ADD A,DPL ;BUMP
MOV DPL,A ;SAVE IT
CLR A
MOVC A,@A+DPTR ;GET HIGH BYTE
PUSH ACC ;SAVE IT
INC DPTR
CLR A
MOVC A,@A+DPTR ;GET LOW BYTE
POP DPH
MOV DPL,A
;
AC1: CLR A
JMP @A+DPTR ;GO DO IT
;
$EJECT
;***************************************************************
;
; The statement action routine - LET
;
;***************************************************************
;
SLET: ACALL S_C ;CHECK FOR POSSIBLE STRING
JC SLET0 ;NO STRING
CLR LINEB ;USED STRINGS
;
CALL X31DP ;PUT ADDRESS IN DPTR
MOV R7,#T_EQU ;WASTE =
ACALL EATC
ACALL GC ;GET THE NEXT CHARACTER
CJNE A,#'"',S_3 ;CHECK FOR A "
MOV R7,S_LEN ;GET THE STRING LENGTH
;
S_0: ACALL GCI1 ;BUMP PAST "
ACALL DELTST ;CHECK FOR DELIMITER
JZ INTERX ;EXIT IF CARRIAGE RETURN
MOVX @DPTR,A ;SAVE THE CHARACTER
CJNE A,#'"',S_1 ;SEE IF DONE
;
S_E: MOV A,#CR ;PUT A CR IN A
MOVX @DPTR,A ;SAVE CR
AJMP GCI1
;
S_3: PUSH DPH
PUSH DPL ;SAVE DESTINATION
ACALL S_C ;CALCULATE SOURCE
JC INTERX ;ERROR IF CARRY
POP R0B0 ;GET DESTINATION BACK
POP R2B0
;
SSOOP: MOV R7,S_LEN ;SET UP COUNTER
;
S_4: CALL TBYTE ;TRANSFER THE BYTE
CJNE A,#CR,S_41 ;EXIT IF A CR
RET
S_41: DJNZ R7,S_5 ;BUMP COUNTER
MOV A,#CR ;SAVE A CR
MOVX @R0,A
AJMP EIGP ;PRINT EXTRA IGNORED
;
$EJECT
;
S_5: CALL INC3210 ;BUMP POINTERS
SJMP S_4 ;LOOP
;
S_1: DJNZ R7,S_11 ;SEE IF DONE
ACALL S_E
ACALL EIGP ;PRINT EXTRA IGNORED
AJMP FINDCR ;GO FIND THE END
S_11: INC DPTR ;BUMP THE STORE POINTER
SJMP S_0 ;CONTINUE TO LOOP
;
E3XX: MOV DPTR,#E3X ;BAD ARG ERROR
AJMP EK
;
SLET0: ACALL SLET1
AJMP POPAS ;COPY EXPRESSION TO VARIABLE
;
SLET1: ACALL VAR_ER ;CHECK FOR A"VARIABLE"
;
SLET2: PUSH R2B0 ;SAVE THE VARIABLE ADDRESS
PUSH R0B0
MOV R7,#T_EQU ;GET EQUAL TOKEN
ACALL WE
POP R1B0 ;POP VARIABLE TO R3:R1
POP R3B0
RET ;EXIT
;
R3CK: CJNE R3,#00H,E3XX ;CHECK TO SEE IF R3 IS ZERO
RET
;
SPEOP: ACALL GCI1 ;BUMP TXA
ACALL P_E ;EVALUATE PAREN
SPEOP1: ACALL SLET2 ;EVALUATE AFTER =
CALL TWOL ;R7:R6 GETS VALUE, R3:R1 GETS LOCATION
MOV A,R6 ;SAVE THE VALUE
;
CJNE R7,#00H,E3XX ;R2 MUST BE = 0
RET
;
$EJECT
;**************************************************************
;
; ST_CAL - Calculate string Address
;
;**************************************************************
;
IST_CAL:;
;
ACALL I_PI ;BUMP TEXT, THEN EVALUATE
ACALL R3CK ;ERROR IF R3 <> 0
INC R1 ;BUMP FOR OFFSET
MOV A,R1 ;ERROR IF R1 = 255
JZ E3XX
MOV DPTR,#VARTOP ;GET TOP OF VARIABLE STORAGE
MOV B,S_LEN ;MULTIPLY FOR LOCATION
ACALL VARD ;CALCULATE THE LOCATION
MOV DPTR,#MEMTOP ;SEE IF BLEW IT
CALL FUL1
MOV DPL,S_LEN ;GET STRING LENGTH, DPH = 00H
DEC DPH ;DPH = 0
;
DUBSUB: CLR C
MOV A,R1
SUBB A,DPL
MOV R1,A
MOV A,R3
SUBB A,DPH
MOV R3,A
ORL A,R1
RET
;
;***************************************************************
;
;VARD - Calculate the offset base
;
;***************************************************************
;
VARB: MOV B,#FPSIZ ;SET UP FOR OPERATION
;
VARD: CALL LDPTRI ;LOAD DPTR
MOV A,R1 ;MULTIPLY BASE
MUL AB
ADD A,DPL
MOV R1,A
MOV A,B
ADDC A,DPH
MOV R3,A
RET
;
$EJECT
;*************************************************************
;
CSY: ; Calculate a biased string address and put in R3:R1
;
;*************************************************************
;
ACALL IST_CAL ;CALCULATE IT
PUSH R3B0 ;SAVE IT
PUSH R1B0
MOV R7,#',' ;WASTE THE COMMA
ACALL EATC
ACALL ONE ;GET THE NEXT EXPRESSION
MOV A,R1 ;CHECK FOR BOUNDS
CJNE A,S_LEN,CSY1
CSY1: JNC E3XX ;MUST HAVE A CARRY
DEC R1 ;BIAS THE POINTER
POP ACC ;GET VALUE LOW
ADD A,R1 ;ADD IT TO BASE
MOV R1,A ;SAVE IT
POP R3B0 ;GET HIGH ADDRESS
JNC CSY2 ;PROPAGATE THE CARRY
INC R3
CSY2: AJMP ERPAR ;WASTE THE RIGHT PAREN
;
$EJECT
;***************************************************************
;
; The statement action routine FOR
;
;***************************************************************
;
SFOR: ACALL SLET1 ;SET UP CONTROL VARIABLE
PUSH R3B0 ;SAVE THE CONTROL VARIABLE LOCATION
PUSH R1B0
ACALL POPAS ;POP ARG STACK AND COPY CONTROL VAR
MOV R7,#T_TO ;GET TO TOKEN
ACALL WE
ACALL GC ;GET NEXT CHARACTER
CJNE A,#T_STEP,SF2
ACALL GCI1 ;EAT THE TOKEN
ACALL EXPRB ;EVALUATE EXPRESSION
SJMP SF21 ;JUMP OVER
;
SF2: LCALL PUSH_ONE ;PUT ONE ON THE STACK
;
SF21: MOV A,#-FSIZE ;ALLOCATE FSIZE BYTES ON THE CONTROL STACK
ACALL PUSHCS ;GET CS IN R0
ACALL CSC ;CHECK CONTROL STACK
MOV R3,#CSTKAH ;IN CONTROL STACK
MOV R1,R0B0 ;STACK ADDRESS
ACALL POPAS ;PUT STEP ON STACK
ACALL POPAS ;PUT LIMIT ON STACK
ACALL DP_T ;DPTR GETS TEXT
MOV R0,R1B0 ;GET THE POINTER
ACALL T_X_S ;SAVE THE TEXT
POP TXAL ;GET CONTROL VARIABLE
POP TXAH
MOV R4,#FTYPE ;AND THE TYPE
ACALL T_X_S ;SAVE IT
;
SF3: ACALL T_DP ;GET THE TEXT POINTER
AJMP ILOOP ;CONTINUE TO PROCESS
;
$EJECT
;**************************************************************
;
; The statement action routines - PUSH and POP
;
;**************************************************************
;
SPUSH: ACALL EXPRB ;PUT EXPRESSION ON STACK
ACALL C_TST ;SEE IF MORE TO DO
JNC SPUSH ;IF A COMMA PUSH ANOTHER
RET
;
;
SPOP: ACALL VAR_ER ;GET VARIABLE
ACALL XPOP ;FLIP THE REGISTERS FOR POPAS
ACALL C_TST ;SEE IF MORE TO DO
JNC SPOP
;
SPOP1: RET
;
;***************************************************************
;
; The statement action routine - IF
;
;***************************************************************
;
SIF: ACALL RTST ;EVALUATE THE EXPRESSION
MOV R1,A ;SAVE THE RESULT
ACALL GC ;GET THE CHARACTER AFTER EXPR
CJNE A,#T_THEN,SIF1 ;SEE IF THEN TOKEN
ACALL GCI1 ;WASTE THEN TOKEN
SIF1: CJNE R1,#0,T_F1 ;CHECK R_OP RESULT
;
E_FIND: MOV R7,#T_ELSE ;FIND ELSE TOKEN
ACALL FINDC
JZ SPOP1 ;EXIT IF A CR
ACALL GCI1 ;BUMP PAST TOKEN
CJNE A,#T_ELSE,E_FIND;WASTE IF NO ELSE
;
T_F1: ACALL INTGER ;SEE IF NUMBER
JNC D_L1 ;EXECUTE LINE NUMBER
AJMP ISTAT ;EXECUTE STATEMENT IN NOT
;
B_C: MOVX A,@DPTR
DEC A
JB ACC.7,FL11
RET
;
$EJECT
;***************************************************************
;
; The statement action routine - GOTO
;
;***************************************************************
;
SGOTO: ACALL RLINE ;R2:R0 AND DPTR GET INTGER
;
SGT1: ACALL T_DP ;TEXT POINTER GETS DPTR
;
JBC RETBIT,SGT2 ;SEE IF RETI EXECUTED
;
JNB LINEB,SGT11 ;SEE IF A LINE WAS EDITED
LCALL CNEW1 ;CLEAR THE MEMORY IF SET
SGT11: AJMP CILOOP1 ;CLEAR DIRF AND LOOP
;
SGT2: JBC OTI,SGT21 ;SEE IF TIMER INTERRUPT
ANL 34,#10111101B ;CLEAR INTERRUPTS
AJMP ILOOP ;EXECUTE
SGT21: MOV C,ISAV
MOV INPROG,C
AJMP ILOOP ;RESTORE INTERRUPTS AND RET
;
;
;*************************************************************
;
RTST: ; Test for ZERO
;
;*************************************************************
;
ACALL EXPRB ;EVALUATE EXPRESSION
CALL INC_ASTKA ;BUMP ARG STACK
JZ RTST1 ;EXIT WITH ZERO OR 0FFH
MOV A,#0FFH
RTST1: RET
;
$EJECT
;
;**************************************************************
;
; GLN - get the line number in R2:R0, return in DPTR
;
;**************************************************************
;
GLN: ACALL DP_B ;GET THE BEGINNING ADDRESS
;
FL1: MOVX A,@DPTR ;GET THE LENGTH
MOV R7,A ;SAVE THE LENGTH
DJNZ R7,FL3 ;SEE IF END OF FILE
;
FL11: MOV DPTR,#E10X ;NO LINE NUMBER
AJMP EK ;HANDLE THE ERROR
;
FL3: JB ACC.7,FL11 ;CHECK FOR BIT 7
INC DPTR ;POINT AT HIGH BYTE
MOVX A,@DPTR ;GET HIGH BYTE
CJNE A,R2B0,FL2 ;SEE IF MATCH
INC DPTR ;BUMP TO LOW BYTE
DEC R7 ;ADJUST AGAIN
MOVX A,@DPTR ;GET THE LOW BYTE
CJNE A,R0B0,FL2 ;SEE IF LOW BYTE MATCH
INC DPTR ;POINT AT FIRST CHARACTER
RET ;FOUND IT
;
FL2: MOV A,R7 ;GET THE LENGTH COUNTER
CALL ADDPTR ;ADD A TO DATA POINTER
SJMP FL1 ;LOOP
;
;
;*************************************************************
;
;RLINE - Read in ASCII string, get line, and clean it up
;
;*************************************************************
;
RLINE: ACALL INTERR ;GET THE INTEGER
;
RL1: ACALL GLN
AJMP CLN_UP
;
;
D_L1: ACALL GLN ;GET THE LINE
AJMP SGT1 ;EXECUTE THE LINE
;
$EJECT
;***************************************************************
;
; The statement action routines WHILE and UNTIL
;
;***************************************************************
;
SWHILE: ACALL RTST ;EVALUATE RELATIONAL EXPRESSION
CPL A
SJMP S_WU
;
SUNTIL: ACALL RTST ;EVALUATE RELATIONAL EXPRESSION
;
S_WU: MOV R4,#DTYPE ;DO EXPECTED
MOV R5,A ;SAVE R_OP RESULT
SJMP SR0 ;GO PROCESS
;
;
;***************************************************************
;
CNULL: ; The Command Action Routine - NULL
;
;***************************************************************
;
ACALL INTERR ;GET AN INTEGER FOLLOWING NULL
MOV NULLCT,R0 ;SAVE THE NULLCOUNT
AJMP CMNDLK ;JUMP TO COMMAND MODE
;
$EJECT
;***************************************************************
;
; The statement action routine - RETI
;
;***************************************************************
;
SRETI: SETB RETBIT ;SAYS THAT RETI HAS BEEN EXECUTED
;
;***************************************************************
;
; The statement action routine - RETURN
;
;***************************************************************
;
SRETRN: MOV R4,#GTYPE ;MAKE SURE OF GOSUB
MOV R5,#55H ;TYPE RETURN TYPE
;
SR0: ACALL CSETUP ;SET UP CONTROL STACK
MOVX A,@R0 ;GET RETURN TEXT ADDRESS
MOV DPH,A
INC R0
MOVX A,@R0
MOV DPL,A
INC R0 ;POP CONTROL STACK
MOVX A,@DPTR ;SEE IF GOSUB WAS THE LAST STATEMENT
CJNE A,#EOF,SR01
AJMP CMNDLK
SR01: MOV A,R5 ;GET TYPE
JZ SGT1 ;EXIT IF ZERO
MOV CSTKA,R0 ;POP THE STACK
CPL A ;OPTION TEST, 00H, 55H, 0FFH, NOW 55H
JNZ SGT1 ;MUST BE GOSUB
RET ;NORMAL FALL THRU EXIT FOR NO MATCH
;
$EJECT
;***************************************************************
;
; The statement action routine - GOSUB
;
;***************************************************************
;
SGOSUB: ACALL RLINE ;NEW TXA IN DPTR
;
SGS0: MOV R4,#GTYPE
ACALL SGS1 ;SET EVERYTHING UP
AJMP SF3 ;EXIT
;
SGS1: MOV A,#-3 ;ALLOCATE 3 BYTES ON CONTROL STACK
ACALL PUSHCS
;
T_X_S: MOV P2,#CSTKAH ;SET UP PORT FOR CONTROL STACK
MOV A,TXAL ;GET RETURN ADDRESS AND SAVE IT
MOVX @R0,A
DEC R0
MOV A,TXAH
MOVX @R0,A
DEC R0
MOV A,R4 ;GET TYPE
MOVX @R0,A ;SAVE TYPE
RET ;EXIT
;
;
CS1: MOV A,#3 ;POP 3 BYTES
ACALL PUSHCS
;
CSETUP: MOV R0,CSTKA ;GET CONTROL STACK
MOV P2,#CSTKAH
MOVX A,@R0 ;GET BYTE
CJNE A,R4B0,CSETUP1 ;SEE IF TYPE MATCH
INC R0
RET
CSETUP1:JZ E4XX ;EXIT IF STACK UNDERFLOW
CJNE A,#FTYPE,CS1 ;SEE IF FOR TYPE
ACALL XXI3 ;WASTE THE FOR TYPE
SJMP CSETUP ;LOOP
;
$EJECT
;***************************************************************
;
; The statement action routine - NEXT
;
;***************************************************************
;
SNEXT: MOV R4,#FTYPE ;FOR TYPE
ACALL CSETUP ;SETUP CONTROL STACK
MOV TEMP5,R0 ;SAVE CONTROL VARIABLE ADDRESS
MOV R1,#TEMP1 ;SAVE VAR + RETURN IN TEMP1-4
;
XXI: MOVX A,@R0 ;LOOP UNTIL DONE
MOV @R1,A
INC R1
INC R0
CJNE R1,#TEMP5,XXI
;
ACALL VAR ;SEE IF THE USER HAS A VARIABLE
JNC XXI1
MOV R2,TEMP1
MOV R0,TEMP2
XXI1: MOV A,R2 ;SEE IF VAR'S AGREE
CJNE A,TEMP1,E4XX
MOV A,R0
CJNE A,TEMP2,E4XX
ACALL PUSHAS ;PUT CONTROL VARIABLE ON STACK
MOV A,#FPSIZ+FPSIZ+2;COMPUTE ADDRESS TO STEP VALUE SIGN
ADD A,TEMP5 ;ADD IT TO BASE OF STACK
MOV R0,A ;SAVE IN R0
MOV R2,#CSTKAH ;SET UP TO PUSH STEP VALUE
MOV P2,R2 ;SET UP PORT
MOVX A,@R0 ;GET SIGN
INC R0 ;BACK TO EXPONENT
PUSH ACC ;SAVE SIGN OF STEP
ACALL PUSHAS ;PUT STEP VALUE ON STACK
PUSH R0B0 ;SAVE LIMIT VALUE LOCATION
CALL AADD ;ADD STEP VALUE TO VARIABLE
CALL CSTAKA ;COPY STACK
MOV R3,TEMP1 ;GET CONTROL VARIABLE
MOV R1,TEMP2
ACALL POPAS ;SAVE THE RESULT
MOV R2,#CSTKAH ;RESTORE LIMIT LOCATION
POP R0B0
ACALL PUSHAS ;PUT LIMIT ON STACK
CALL FP_BASE2 ;DO THE COMPARE
POP ACC ;GET LIMIT SIGN BACK
JZ XXI2 ;IF SIGN NEGATIVE, TEST "BACKWARDS"
CPL C
XXI2: ORL C,F0 ;SEE IF EQUAL
JC N4 ;STILL SMALLER THAN LIMIT?
XXI3: MOV A,#FSIZE ;REMOVE CONTROL STACK ENTRY
;
; Fall thru to PUSHCS
;
$EJECT
;***************************************************************
;
; PUSHCS - push frame onto control stack
; acc has - number of bytes, also test for overflow
;
;***************************************************************
;
PUSHCS: ADD A,CSTKA ;BUMP CONTROL STACK
CJNE A,#CONVT+17,PUSHCS1 ;SEE IF OVERFLOWED
PUSHCS1:JC E4XX ;EXIT IF STACK OVERFLOW
XCH A,CSTKA ;STORE NEW CONTROL STACK VALUE, GET OLD
DEC A ;BUMP OLD VALUE
MOV R0,A ;PUT OLD-1 IN R0
;
PUSHCS2:RET ;EXIT
;
CSC: ACALL CLN_UP ;FINISH OFF THE LINE
JNC PUSHCS2 ;EXIT IF NO TERMINATOR
;
E4XX: MOV DPTR,#EXC ;CONTROL STACK ERROR
AJMP EK ;STACK ERROR
;
N4: MOV TXAH,TEMP3 ;GET TEXT POINTER
MOV TXAL,TEMP4
AJMP ILOOP ;EXIT
;
;***************************************************************
;
; The statement action routine - RESTORE
;
;***************************************************************
;
SRESTR: ACALL X_TR ;SWAP POINTERS
SRESTR1:ACALL DP_B ;GET THE STARTING ADDRESS
ACALL T_DP ;PUT STARTING ADDRESS IN TEXT POINTER
ACALL B_TXA ;BUMP TXA
;
; Fall thru
;
X_TR: ;swap txa and rtxa
;
XCH A,TXAH
XCH A,RTXAH
XCH A,TXAH
XCH A,TXAL
XCH A,RTXAL
XCH A,TXAL
RET ;EXIT
;
$EJECT
;***************************************************************
;
; The statement action routine - READ
;
;***************************************************************
;
SREAD: ACALL X_TR ;SWAP POINTERS
;
SRD0: ACALL C_TST ;CHECK FOR COMMA
JC SRD4 ;SEE WHAT IT IS
;
SRD: ACALL EXPRB ;EVALUATE THE EXPRESSION
ACALL GC ;GET THE CHARACTER AFTER EXPRESSION
CJNE A,#',',SRD1 ;SEE IF MORE DATA
SJMP SRD2 ;BYBASS CLEAN UP IF A COMMA
;
SRD1: ACALL CLN_UP ;FINISH OFF THE LINE, IF AT END
;
SRD2: ACALL X_TR ;RESTORE POINTERS
ACALL VAR_ER ;GET VARIABLE ADDRESS
ACALL XPOP ;FLIP THE REGISTERS FOR POPAS
ACALL C_TST ;SEE IF A COMMA
JNC SREAD ;READ AGAIN IF A COMMA
SRD21: RET ;EXIT IF NOT
;
SRD4: CJNE A,#T_DATA,SRD5 ;SEE IF DATA
ACALL GCI1 ;BUMP POINTER
SJMP SRD
;
SRD5: CJNE A,#EOF,SRD6 ;SEE IF YOU BLEW IT
SRD51: ACALL X_TR ;GET THE TEXT POINTER BACK
MOV DPTR,#E14X ;READ ERROR
;
EK: LJMP ERROR
;
SRD6: ACALL FINDCR ;WASTE THIS LINE
ACALL CLN_UP ;CLEAN IT UP
JC SRD51 ;ERROR IF AT END
SJMP SRD0
;
NUMC: ACALL GC ;GET A CHARACTER
CJNE A,#'#',NUMC1 ;SEE IF A #
SETB COB ;VALID LINE PRINT
AJMP IGC ;BUMP THE TEXT POINTER
;
NUMC1: CJNE A,#'@',SRD21 ;EXIT IF NO GOOD
SETB LPB
AJMP IGC
;
$EJECT
;***************************************************************
;
; The statement action routine - PRINT
;
;***************************************************************
;
SPH0: SETB ZSURP ;NO ZEROS
;
SPH1: SETB HMODE ;HEX MODE
;
SPRINT: ACALL NUMC ;TEST FOR A LINE PRINT
ACALL SPRINT2 ;PROCEED
SPRINT1:ANL 35,#11110101B ;CLEAR COB AND LPB
ANL 38,#00111111B ;NO HEX MODE
;
RET
;
SPRINT2:ACALL DELTST ;CHECK FOR A DELIMITER
JC SP1
;
SP0: JMP CRLF ;EXIT WITH A CR IF SO
;
SP2: ACALL C_TST ;CHECK FOR A COMMA
JC SP0 ;EXIT IF NO COMMA
;
SP1: ACALL CPS ;SEE IF A STRING TO PRINT
JNC SP2 ;IF A STRING, CHECK FOR A COMMA
;
SP4: CJNE A,#T_TAB,SP6
ACALL I_PI ;ALWAYS CLEARS CARRY
SUBB A,PHEAD ;TAKE DELTA BETWEEN TAB AND PHEAD
JC SP2 ;EXIT IF PHEAD > TAB
SJMP SP7 ;OUTPUT SPACES
;
SP6: CJNE A,#T_SPC,SM
ACALL I_PI ;SET UP PAREN VALUE
;
SP7: JZ SP2
LCALL STEROT ;OUTPUT A SPACE
DEC A ;DECREMENT COUNTER
SJMP SP7 ;LOOP
;
$EJECT
SM: CJNE A,#T_CHR,SP8
ACALL IGC
CJNE A,#'$',SM01
ACALL CNX ;PUT THE CHARACTER ON THE STACK
ACALL IFIXL ;PUT THE CHARACTER IN R1
SJMP SM02
SM01: ACALL ONE ;EVALUATE THE EXPRESSION, PUT IN R3:R1
ACALL ERPAR
SM02: MOV R5,R1B0 ;BYTE TO OUTPUT
SJMP SQ
;
SP8: CJNE A,#T_CR,SX
ACALL GCI1 ;EAT THE TOKEN
MOV R5,#CR
;
SQ: CALL TEROT
SJMP SP2 ;OUTPUT A CR AND DO IT AGAIN
;
SX: CJNE A,#T_USE,SP9 ;USING TOKEN
ACALL IGC ;GE THE CHARACTER AFTER THE USING TOKEN
CJNE A,#'F',U4 ;SEE IF FLOATING
MOV FORMAT,#0F0H ;SET FLOATING
ACALL IGC ;BUMP THE POINTER AND GET THE CHARACTER
ACALL GCI1 ;BUMP IT AGAIN
ANL A,#0FH ;STRIP OFF ASCII BIAS
JZ U3 ;EXIT IF ZERO
CJNE A,#3,SX1 ;SEE IF AT LEAST A THREE
SX1: JNC U3 ;FORCE A THREE IF NOT A THREE
MOV A,#3
;
U3: ORL FORMAT,A ;PUT DIGIT IN FORMAT
SJMP U8 ;CLEAN UP END
;
U4: CJNE A,#'0',U5
MOV FORMAT,#0 ;FREE FORMAT
ACALL GCI1 ;BUMP THE POINTER
SJMP U8
;
U5: CJNE A,#'#',U8 ;SEE IF INTGER FORMAT
ACALL U6
MOV FORMAT,R7 ;SAVE THE FORMAT
CJNE A,#'.',U8A ;SEE IF TERMINATOR WAS RADIX
ACALL IGC ;BUMP PAST .
ACALL U6 ;LOOP AGAIN
MOV A,R7 ;GET COUNT
ADD A,FORMAT ;SEE IF TOO BIG
ADD A,#0F7H
JNC U5A
;
$EJECT
SE0: AJMP INTERX ;ERROR, BAD SYNTAX
;
U5A: MOV A,R7 ;GET THE COUNT BACK
SWAP A ;ADJUST
ORL FORMAT,A ;GET THE COUNT
;
U8A: MOV A,FORMAT
;
U8B: SWAP A ;GET THE FORMAT RIGHT
MOV FORMAT,A
;
U8: ACALL ERPAR
AJMP SP2 ;DONE
;
U6: MOV R7,#0 ;SET COUNTER
;
U7: CJNE A,#'#',SP9A ;EXIT IF NOT A #
INC R7 ;BUMP COUNTER
ACALL IGC ;GET THE NEXT CHARACTER
SJMP U7 ;LOOP
;
SP9: ACALL DELTST1 ;CHECK FOR DELIMITER
JNC SP9A ;EXIT IF A DELIMITER
;
CJNE A,#T_ELSE,SS
;
SP9A: RET ;EXIT IF ELSE TOKEN
;
;**************************************************************
;
; P_E - Evaluate an expression in parens ( )
;
;**************************************************************
;
P_E: MOV R7,#T_LPAR
ACALL WE
;
ERPAR: MOV R7,#')' ;EAT A RIGHT PAREN
;
EATC: ACALL GCI ;GET THE CHARACTER
CJNE A,R7B0,SE0 ;ERROR IF NOT THE SAME
RET
;
$EJECT
;***************************************************************
;
S_ON: ; ON Statement
;
;***************************************************************
;
ACALL ONE ;GET THE EXPRESSION
ACALL GCI ;GET THE NEXT CHARACTER
CJNE A,#T_GOTO,C0
ACALL C1 ;EAT THE COMMAS
AJMP SF3 ;DO GOTO
;
C0: CJNE A,#T_GOSB,SE0
ACALL C1
AJMP SGS0 ;DO GOSUB
;
C1: CJNE R1,#0,C2
ACALL INTERR ;GET THE LINE NUMBER
ACALL FINDCR
AJMP RL1 ;FINISH UP THIS LINE
;
C2: MOV R7,#','
ACALL FINDC
CJNE A,#',',SE0 ;ERROR IF NOT A COMMA
DEC R1
ACALL GCI1 ;BUMP PAST COMMA
SJMP C1
;
$EJECT
;
SS: ACALL S_C ;SEE IF A STRING
JC SA ;NO STRING IF CARRY IS SET
LCALL UPRNT ;PUT POINTER IN DPTR
AJMP SP2 ;SEE IF MORE
;
SA: ACALL EXPRB ;MUST BE AN EXPRESSION
MOV A,#72
CJNE A,PHEAD,SA1 ;CHECK PHEAD POSITION
SA1: JNC SA2
ACALL SP0 ;FORCE A CRLF
SA2: JNB HMODE,S13 ;HEX MODE?
CALL FCMP ;SEE IF TOS IS < 0FFFH
JC S13 ;EXIT IF GREATER
CALL AABS ;GET THE SIGN
JNZ OOPS ;WASTE IF NEGATIVE
ACALL IFIXL
CALL FP_BASE11 ;PRINT HEXMODE
AJMP SP2
OOPS: CALL ANEG ;MAKE IT NEGATIVE
;
S13: CALL FP_BASE7 ;DO FP OUTPUT
MOV A,#1 ;OUTPUT A SPACE
AJMP SP7
;
$EJECT
;***************************************************************
;
; ANU - Get variable name from text - set carry if not found
; if succeeds returns variable in R7:R6
; R6 = 0 if no digit in name
;
;***************************************************************
;
ANU: ACALL IGC ;INCREMENT AND GET CHARACTER
LCALL DIGIT_CHECK ;CHECK FOR DIGIT
JC AL2 ;EXIT IF VALID DIGIT
CJNE A,#'_',AL ;SEE IF A _
RET
;
AL: CJNE A,#'A',AL1 ;IS IT AN ASCII A?
AL1: JC AL3 ;EXIT IF CARRY IS SET
CJNE A,#'Z'+1,AL2 ;IS IT LESS THAN AN ASCII Z
AL2: CPL C ;FLIP CARRY
AL3: RET
;
SD01: JNB F0,VAR2
;
SD0: MOV DPTR,#E6X
AJMP EK
;
SDIMX: SETB F0 ;SAYS DOING A DIMENSION
SJMP VAR1
;
VAR: CLR F0 ;SAYS DOING A VARIABLE
;
VAR1: ACALL GC ;GET THE CHARACTER
ACALL AL ;CHECK FOR ALPHA
JNC VAR11 ;ERROR IF IN DIM
JB F0,SD0
RET
VAR11: MOV R7,A ;SAVE ALPHA CHARACTER
CLR A ;ZERO IN CASE OF FAILURE
MOV R5,A ;SAVE IT
;
VY: MOV R6,A
ACALL ANU ;CHECK FOR ALPHA OR NUMBER
JC VX ;EXIT IF NO ALPHA OR NUM
;
XCH A,R7
ADD A,R5 ;NUMBER OF CHARACTERS IN ALPHABET
XCH A,R7 ;PUT IT BACK
MOV R5,#26 ;FOR THE SECOND TIME AROUND
SJMP VY
;
VX: CLR LINEB ;TELL EDITOR A VARIABLE IS DECLARED
CJNE A,#T_LPAR,V4 ;SEE IF A LEFT PAREN
;
ORL R6B0,#80H ;SET BIT 7 TO SIGINIFY MATRIX
CALL F_VAR ;FIND THE VARIABLE
PUSH R2B0 ;SAVE THE LOCATION
PUSH R0B0
JNC SD01 ;DEFAULT IF NOT IN TABLE
JB F0,SDI ;NO DEFAULT FOR DIMENSION
MOV R1,#10
MOV R3,#0
ACALL D_CHK
;
VAR2: ACALL PAREN_INT ;EVALUATE INTEGER IN PARENS
CJNE R3,#0,SD0 ;ERROR IF R3<>0
POP DPL ;GET VAR FOR LOOKUP
POP DPH
MOVX A,@DPTR ;GET DIMENSION
DEC A ;BUMP OFFSET
SUBB A,R1 ;A MUST BE > R1
JC SD0
LCALL DECDP2 ;BUMP POINTER TWICE
ACALL VARB ;CALCULATE THE BASE
;
X3120: XCH A,R1 ;SWAP R2:R0, R3:R1
XCH A,R0
XCH A,R1
XCH A,R3
XCH A,R2
XCH A,R3
RET
;
V4: JB F0,SD0 ;ERROR IF NO LPAR FOR DIM
LCALL F_VAR ;GET SCALAR VARIABLE
CLR C
RET
;
$EJECT
;
SDI: ACALL PAREN_INT ;EVALUATE PAREN EXPRESSION
CJNE R3,#0,SD0 ;ERROR IF NOT ZERO
POP R0B0 ;SET UP R2:R0
POP R2B0
ACALL D_CHK ;DO DIM
ACALL C_TST ;CHECK FOR COMMA
JNC SDIMX ;LOOP IF COMMA
RET ;RETURN IF NO COMMA
;
D_CHK: INC R1 ;BUMP FOR TABLE LOOKUP
MOV A,R1
JZ SD0 ;ERROR IF 0FFFFH
MOV R4,A ;SAVE FOR LATER
MOV DPTR,#MT_ALL ;GET MATRIX ALLOCATION
ACALL VARB ;DO THE CALCULATION
MOV R7,DPH ;SAVE MATRIX ALLOCATION
MOV R6,DPL
MOV DPTR,#ST_ALL ;SEE IF TOO MUCH MEMORY TAKEN
CALL FUL1 ;ST_ALL SHOULD BE > R3:R1
MOV DPTR,#MT_ALL ;SAVE THE NEW MATRIX POINTER
CALL S31DP
MOV DPL,R0 ;GET VARIABLE ADDRESS
MOV DPH,R2
MOV A,R4 ;DIMENSION SIZE
MOVX @DPTR,A ;SAVE IT
CALL DECDP2 ;SAVE TARGET ADDRESS
;
R76S: MOV A,R7
MOVX @DPTR,A
INC DPTR
MOV A,R6 ;ELEMENT SIZE
MOVX @DPTR,A
RET ;R2:R0 STILL HAS SYMBOL TABLE ADDRESS
;
$EJECT
;***************************************************************
;
; The statement action routine - INPUT
;
;***************************************************************
;
SINPUT: ACALL CPS ;PRINT STRING IF THERE
;
ACALL C_TST ;CHECK FOR A COMMA
JNC IN2A ;NO CRLF
ACALL SP0 ;DO A CRLF
;
IN2: MOV R5,#'?' ;OUTPUT A ?
CALL TEROT
;
IN2A: SETB INP_B ;DOING INPUT
CALL INLINE ;INPUT THE LINE
CLR INP_B
MOV TEMP5,#HIGH IBUF
MOV TEMP4,#LOW IBUF
;
IN3: ACALL S_C ;SEE IF A STRING
JC IN3A ;IF CARRY IS SET, NO STRING
ACALL X3120 ;FLIP THE ADDRESSES
MOV R3,TEMP5
MOV R1,TEMP4
ACALL SSOOP
ACALL C_TST ;SEE IF MORE TO DO
JNC IN2
RET
;
IN3A: CALL DTEMP ;GET THE USER LOCATION
CALL GET_NUM ;GET THE USER SUPPLIED NUMBER
JNZ IN5 ;ERROR IF NOT ZERO
CALL TEMPD ;SAVE THE DATA POINTER
ACALL VAR_ER ;GET THE VARIABLE
ACALL XPOP ;SAVE THE VARIABLE
CALL DTEMP ;GET DPTR BACK FROM VAR_ER
ACALL C_TST ;SEE IF MORE TO DO
JC IN6 ;EXIT IF NO COMMA
MOVX A,@DPTR ;GET INPUT TERMINATOR
CJNE A,#',',IN5 ;IF NOT A COMMA DO A CR AND TRY AGAIN
INC DPTR ;BUMP PAST COMMA AND READ NEXT VALUE
CALL TEMPD
SJMP IN3
;
$EJECT
;
IN5: MOV DPTR,#IAN ;PRINT INPUT A NUMBER
CALL CRP ;DO A CR, THEN, PRINT FROM ROM
LJMP CC1 ;TRY IT AGAIN
;
IN6: MOVX A,@DPTR
CJNE A,#CR,EIGP
RET
;
EIGP: MOV DPTR,#EIG
CALL CRP ;PRINT THE MESSAGE AND EXIT
AJMP SP0 ;EXIT WITH A CRLF
;
;***************************************************************
;
SOT: ; On timer interrupt
;
;***************************************************************
;
ACALL TWO ;GET THE NUMBERS
MOV SP_H,R3
MOV SP_L,R1
MOV DPTR,#TIV ;SAVE THE NUMBER
SETB OTS
AJMP R76S ;EXIT
;
;
;***************************************************************
;
SCALL: ; Call a user rountine
;
;***************************************************************
;
ACALL INTERR ;CONVERT INTEGER
CJNE R2,#0,S_C_1 ;SEE IF TRAP
MOV A,R0
JB ACC.7,S_C_1
ADD A,R0
MOV DPTR,#4100H
MOV DPL,A
;
S_C_1: ACALL AC1 ;JUMP TO USER PROGRAM
ANL PSW,#11100111B ;BACK TO BANK 0
RET ;EXIT
;
$EJECT
;**************************************************************
;
THREE: ; Save value for timer function
;
;**************************************************************
;
ACALL ONE ;GET THE FIRST INTEGER
CALL CBIAS ;BIAS FOR TIMER LOAD
MOV T_HH,R3
MOV T_LL,R1
MOV R7,#',' ;WASTE A COMMA
ACALL EATC ;FALL THRU TO TWO
;
;**************************************************************
;
TWO: ; Get two values seperated by a comma off the stack
;
;**************************************************************
;
ACALL EXPRB
MOV R7,#',' ;WASTE THE COMMA
ACALL WE
JMP TWOL ;EXIT
;
;*************************************************************
;
ONE: ; Evaluate an expression and get an integer
;
;*************************************************************
;
ACALL EXPRB ;EVALUATE EXPERSSION
;
IFIXL: CALL IFIX ;INTEGERS IN R3:R1
MOV A,R1
RET
;
;
;*************************************************************
;
I_PI: ; Increment text pointer then get an integer
;
;*************************************************************
;
ACALL GCI1 ;BUMP TEXT, THEN GET INTEGER
;
PAREN_INT:; Get an integer in parens ( )
;
ACALL P_E
SJMP IFIXL
;
$EJECT
;
DP_B: MOV DPH,BOFAH
MOV DPL,BOFAL
RET
;
DP_T: MOV DPH,TXAH
MOV DPL,TXAL
RET
;
CPS: ACALL GC ;GET THE CHARACTER
CJNE A,#'"',NOPASS ;EXIT IF NO STRING
ACALL DP_T ;GET TEXT POINTER
INC DPTR ;BUMP PAST "
MOV R4,#'"'
CALL PN0 ;DO THE PRINT
INC DPTR ;GO PAST QUOTE
CLR C ;PASSED TEST
;
T_DP: MOV TXAH,DPH ;TEXT POINTER GETS DPTR
MOV TXAL,DPL
RET
;
;*************************************************************
;
S_C: ; Check for a string
;
;*************************************************************
;
ACALL GC ;GET THE CHARACTER
CJNE A,#'$',NOPASS ;SET CARRY IF NOT A STRING
AJMP IST_CAL ;CLEAR CARRY, CALCULATE OFFSET
;
;
;
;**************************************************************
;
C_TST: ACALL GC ;GET A CHARACTER
CJNE A,#',',NOPASS ;SEE IF A COMMA
;
$EJECT
;***************************************************************
;
;GC AND GCI - GET A CHARACTER FROM TEXT (NO BLANKS)
; PUT CHARACTER IN THE ACC
;
;***************************************************************
;
IGC: ACALL GCI1 ;BUMP POINTER, THEN GET CHARACTER
;
GC: SETB RS0 ;USE BANK 1
MOV P2,R2 ;SET UP PORT 2
MOVX A,@R0 ;GET EXTERNAL BYTE
CLR RS0 ;BACK TO BANK 0
RET ;EXIT
;
GCI: ACALL GC
;
; This routine bumps txa by one and always clears the carry
;
GCI1: SETB RS0 ;BANK 1
INC R0 ;BUMP TXA
CJNE R0,#0,GCI11
INC R2
GCI11: CLR RS0
RET ;EXIT
;
$EJECT
;**************************************************************
;
; Check delimiters
;
;**************************************************************
;
DELTST: ACALL GC ;GET A CHARACTER
DELTST1:CJNE A,#CR,DT1 ;SEE IF A CR
CLR A
RET
;
DT1: CJNE A,#':',NOPASS ;SET CARRY IF NO MATCH
;
L_RET: RET
;
;
;***************************************************************
;
; FINDC - Find the character in R7, update TXA
;
;***************************************************************
;
FINDCR: MOV R7,#CR ;KILL A STATEMENT LINE
;
FINDC: ACALL DELTST
JNC L_RET
;
CJNE A,R7B0,FNDCL2 ;MATCH?
RET
;
FNDCL2: ACALL GCI1
SJMP FINDC ;LOOP
;
FNDCL3: ACALL GCI1
;
WCR: ACALL DELTST ;WASTE UNTIL A "REAL" CR
JNZ FNDCL3
RET
;
$EJECT
;***************************************************************
;
; VAR_ER - Check for a variable, exit if error
;
;***************************************************************
;
VAR_ER: ACALL VAR
SJMP INTERR1
;
;
;***************************************************************
;
; S_D0 - The Statement Action Routine DO
;
;***************************************************************
;
S_DO: ACALL CSC ;FINISH UP THE LINE
MOV R4,#DTYPE ;TYPE FOR STACK
ACALL SGS1 ;SAVE ON STACK
AJMP ILOOP ;EXIT
;
$EJECT
;***************************************************************
;
; CLN_UP - Clean up the end of a statement, see if at end of
; file, eat character and line count after CR
;
;***************************************************************
;
C_2: CJNE A,#':',C_1 ;SEE IF A TERMINATOR
AJMP GCI1 ;BUMP POINTER AND EXIT, IF SO
;
C_1: CJNE A,#T_ELSE,EP5
ACALL WCR ;WASTE UNTIL A CR
;
CLN_UP: ACALL GC ;GET THE CHARACTER
CJNE A,#CR,C_2 ;SEE IF A CR
ACALL IGC ;GET THE NEXT CHARACTER
CJNE A,#EOF,B_TXA ;SEE IF TERMINATOR
;
NOPASS: SETB C
RET
;
B_TXA: XCH A,TXAL ;BUMP TXA BY THREE
ADD A,#3
XCH A,TXAL
JBC CY,B_TXA1
RET
B_TXA1: INC TXAH
RET
;
$EJECT
;***************************************************************
;
; Get an INTEGER from the text
; sets CARRY if not found
; returns the INTGER value in DPTR and R2:R0
; returns the terminator in ACC
;
;***************************************************************
;
INTERR: ACALL INTGER ;GET THE INTEGER
INTERR1:JC EP5 ;ERROR IF NOT FOUND
RET ;EXIT IF FOUND
;
INTGER: ACALL DP_T
CALL FP_BASE9 ;CONVERT THE INTEGER
ACALL T_DP
MOV DPH,R2 ;PUT THE RETURNED VALUE IN THE DPTR
MOV DPL,R0
;
ITRET: RET ;EXIT
;
;
WE: ACALL EATC ;WASTE THE CHARACTER
;
; Fall thru to evaluate the expression
;
$EJECT
;***************************************************************
;
; EXPRB - Evaluate an expression
;
;***************************************************************
;
EXPRB: MOV R2,#LOW OPBOL ;BASE PRECEDENCE
;
EP1: PUSH R2B0 ;SAVE OPERATOR PRECEDENCE
CLR ARGF ;RESET STACK DESIGNATOR
;
EP2: MOV A,SP ;GET THE STACK POINTER
ADD A,#12 ;NEED AT LEAST 12 BYTES
JNC EP21
LJMP E1XX2
EP21: MOV A,ASTKA ;GET THE ARG STACK
SUBB A,#LOW TM_TOP+12;NEED 12 BYTES ALSO
JNC EP22
LJMP E4YY
EP22: JB ARGF,EP4 ;MUST BE AN OPERATOR, IF SET
ACALL VAR ;IS THE VALUE A VARIABLE?
JNC EP3 ;PUT VARIABLE ON STACK
;
ACALL CONST ;IS THE VALUE A NUMERIC CONSTANT?
JNC EP4 ;IF SO, CONTINUE, IF NOT, SEE WHAT
CALL GC ;GET THE CHARACTER
CJNE A,#T_LPAR,EP4 ;SEE IF A LEFT PAREN
MOV A,#(LOW OPBOL+1)
SJMP XLPAR ;PROCESS THE LEFT PAREN
;
EP3: ACALL PUSHAS ;SAVE VAR ON STACK
;
EP4: ACALL GC ;GET THE OPERATOR
;
CJNE A,#T_LPAR,EP41 ;IS IT AN OPERATOR
EP41: JNC XOP ;PROCESS OPERATOR
CJNE A,#T_UOP,EP42 ;IS IT A UNARY OPERATOR
EP42: JNC XBILT ;PROCESS UNARY (BUILT IN) OPERATOR
POP R2B0 ;GET BACK PREVIOUS OPERATOR PRECEDENCE
JB ARGF,ITRET ;OK IF ARG FLAG IS SET
;
EP5: CLR C ;NO RECOVERY
LJMP E1XX1
;
; Process the operator
;
XOP: ANL A,#1FH ;STRIP OFF THE TOKE BITS
JB ARGF,XOP1 ;IF ARG FLAG IS SET, PROCESS
CJNE A,#T_SUB-T_LPAR,XOP3
MOV A,#T_NEG-T_LPAR
;
$EJECT
XOP1: ADD A,#LOW OPBOL+1 ;BIAS THE TABLE
MOV R2,A
MOV DPTR,#00H
MOVC A,@A+DPTR ;GET THE CURRENT PRECEDENCE
MOV R4,A
POP ACC ;GET THE PREVIOUS PRECEDENCE
MOV R5,A ;SAVE THE PREVIOUS PRECEDENCE
MOVC A,@A+DPTR ;GET IT
CJNE A,R4B0,XOP11 ;SEE WHICH HAS HIGHER PRECEDENCE
CJNE A,#12,ITRET ;SEE IF ANEG
SETB C
XOP11: JNC ITRET ;PROCESS NON-INCREASING PRECEDENCE
;
; Save increasing precedence
;
PUSH R5B0 ;SAVE OLD PRECEDENCE ADDRESS
PUSH R2B0 ;SAVE NEW PRECEDENCE ADDRESS
ACALL GCI1 ;EAT THE OPERATOR
ACALL EP1 ;EVALUATE REMAINING EXPRESSION
XOP12: POP ACC
;
; R2 has the action address, now setup and perform operation
;
XOP2: MOV DPTR,#OPTAB
ADD A,#LOW (NOT OPBOL)
CALL ISTA1 ;SET UP TO RETURN TO EP2
AJMP EP2 ;JUMP TO EVALUATE EXPRESSION
;
; Built-in operator processing
;
XBILT: ACALL GCI1 ;EAT THE TOKEN
ADD A,#LOW (50H+LOW UOPBOL)
JB ARGF,EP5 ;XBILT MUST COME AFTER AN OPERATOR
CJNE A,#STP,XBILT1
XBILT1: JNC XOP2
;
XLPAR: PUSH ACC ;PUT ADDRESS ON THE STACK
ACALL P_E
SJMP XOP12 ;PERFORM OPERATION
;
XOP3: CJNE A,#T_ADD-T_LPAR,EP5
ACALL GCI1
AJMP EP2 ;WASTE + SIGN
;
$EJECT
XPOP: ACALL X3120 ;FLIP ARGS THEN POP
;
;***************************************************************
;
; POPAS - Pop arg stack and copy variable to R3:R1
;
;***************************************************************
;
POPAS: LCALL INC_ASTKA
JMP VARCOP ;COPY THE VARIABLE
;
AXTAL: MOV R2,#HIGH CXTAL
MOV R0,#LOW CXTAL
;
; fall thru
;
;***************************************************************
;
PUSHAS: ; Push the Value addressed by R2:R0 onto the arg stack
;
;***************************************************************
;
CALL DEC_ASTKA
SETB ARGF ;SAYS THAT SOMTHING IS ON THE STACK
LJMP VARCOP
;
;
;***************************************************************
;
ST_A: ; Store at expression
;
;***************************************************************
;
ACALL ONE ;GET THE EXPRESSION
SJMP POPAS ;SAVE IT
;
;
;***************************************************************
;
LD_A: ; Load at expression
;
;***************************************************************
;
ACALL ONE ;GET THE EXPRESSION
ACALL X3120 ;FLIP ARGS
SJMP PUSHAS
;
$EJECT
;***************************************************************
;
CONST: ; Get a constant fron the text
;
;***************************************************************
;
CALL GC ;FIRST SEE IF LITERAL
CJNE A,#T_ASC,C0C ;SEE IF ASCII TOKEN
CALL IGC ;GET THE CHARACTER AFTER TOKEN
CJNE A,#'$',CN0 ;SEE IF A STRING
;
CNX: CALL CSY ;CALCULATE IT
JMP AXBYTE1 ;SAVE IT ON THE STACK
;
CN0: CALL TWO_R2 ;PUT IT ON THE STACK
CALL GCI1 ;BUMP THE POINTER
JMP ERPAR ;WASTE THE RIGHT PAREN
;
;
C0C: CALL DP_T ;GET THE TEXT POINTER
CALL GET_NUM ;GET THE NUMBER
CJNE A,#0FFH,C1C ;SEE IF NO NUMBER
SETB C
C2C: RET
;
C1C: JNZ FPTST
CLR C
SETB ARGF
;
C3C: JMP T_DP
;
FPTST: ANL A,#00001011B ;CHECK FOR ERROR
JZ C2C ;EXIT IF ZERO
;
; Handle the error condition
;
MOV DPTR,#E2X ;DIVIDE BY ZERO
JNB ACC.0,FPTST1 ;UNDERFLOW
MOV DPTR,#E7X
FPTST1: JNB ACC.1,FPTS ;OVERFLOW
MOV DPTR,#E11X
;
FPTS: JMP ERROR
;
$EJECT
;***************************************************************
;
; The Command action routine - LIST
;
;***************************************************************
;
CLIST: CALL NUMC ;SEE IF TO LINE PORT
ACALL FSTK ;PUT 0FFFFH ON THE STACK
CALL INTGER ;SEE IF USER SUPPLIES LN
CLR A ;LN = 0 TO START
MOV R3,A
MOV R1,A
JC CL1 ;START FROM ZERO
;
CALL TEMPD ;SAVE THE START ADDTESS
CALL GCI ;GET THE CHARACTER AFTER LIST
CJNE A,#T_SUB,CLIST1 ;CHECK FOR TERMINATION ADDRESS '-'
ACALL INC_ASTKA ;WASTE 0FFFFH
LCALL INTERR ;GET TERMINATION ADDRESS
ACALL TWO_EY ;PUT TERMINATION ON THE ARG STACK
CLIST1: MOV R3,TEMP5 ;GET THE START ADDTESS
MOV R1,TEMP4
;
CL1: CALL GETLIN ;GET THE LINE NO IN R3:R1
JZ CL3 ;RET IF AT END
;
CL2: ACALL C3C ;SAVE THE ADDRESS
INC DPTR ;POINT TO LINE NUMBER
ACALL PMTOP1 ;PUT LINE NUMBER ON THE STACK
ACALL CMPLK ;COMPARE LN TO END ADDRESS
JC CL3 ;EXIT IF GREATER
CALL BCK ;CHECK FOR A CONTROL C
ACALL DEC_ASTKA ;SAVE THE COMPARE ADDRESS
CALL DP_T ;RESTORE ADDRESS
ACALL UPPL ;UN-PROCESS THE LINE
ACALL C3C ;SAVE THE CR ADDRESS
ACALL CL6 ;PRINT IT
INC DPTR ;BUMP POINTER TO NEXT LINE
MOVX A,@DPTR ;GET LIN LENGTH
DJNZ ACC,CL2 ;LOOP
ACALL INC_ASTKA ;WASTE THE COMPARE BYTE
;
CL3: AJMP CMND1 ;BACK TO COMMAND PROCESSOR
;
CL6: MOV DPTR,#IBUF ;PRINT IBUF
CALL PRNTCR ;PRINT IT
CALL DP_T
;
CL7: JMP CRLF
;
UPPL0: LCALL X31DP
$EJECT
;***************************************************************
;
;UPPL - UN PREPROCESS A LINE ADDRESSED BY DPTR INTO IBUF
; RETURN SOURCE ADDRESS OF CR IN DPTR ON RETURN
;
;***************************************************************
;
UPPL: MOV R3,#HIGH IBUF ;POINT R3 AT HIGH IBUF
MOV R1,#LOW IBUF ;POINT R1 AT IBUF
INC DPTR ;SKIP OVER LINE LENGTH
ACALL C3C ;SAVE THE DPTR (DP_T)
CALL L20DPI ;PUT LINE NUMBER IN R2:R0
CALL FP_BASE8 ;CONVERT R2:R0 TO INTEGER
CALL DP_T
INC DPTR ;BUMP DPTR PAST THE LINE NUMBER
;
UPP0: CJNE R1,#LOW IBUF+6,UPP01
UPP01: JC UPP91 ;PUT SPACES IN TEXT
INC DPTR ;BUMP PAST LN HIGH
MOVX A,@DPTR ;GET USER TEXT
MOV R6,A ;SAVE A IN R6 FOR TOKE COMPARE
JB ACC.7,UPP1 ;IF TOKEN, PROCESS
CJNE A,#20H,UPP02 ;TRAP THE USER TOKENS
UPP02: JNC UPP03
CJNE A,#CR,UPP1 ;DO IT IF NOT A CR
UPP03: CJNE A,#'"',UPP9 ;SEE IF STRING
ACALL UPP7 ;SAVE IT
UPP04: ACALL UPP8 ;GET THE NEXT CHARACTER AND SAVE IT
CJNE A,#'"',UPP04 ;LOOP ON QUOTES
SJMP UPP0
;
UPP9: CJNE A,#':',UPP1A ;PUT A SPACE IN DELIMITER
ACALL UPP7A
MOV A,R6
ACALL UPP7
UPP91: ACALL UPP7A
SJMP UPP0
;
UPP1A: ACALL UPP81 ;SAVE THE CHARACTER, UPDATE POINTER
SJMP UPP0 ;EXIT IF A CR, ELSE LOOP
;
UPP1: ACALL C3C ;SAVE THE TEXT POINTER
MOV C,XBIT
MOV F0,C ;SAVE XBIT IN F0
UPP11: MOV DPTR,#TOKTAB ;POINT AT TOKEN TABLE
JNB F0,UPP2
LCALL 2078H ;SET UP DPTR FOR LOOKUP
;
UPP2: CLR A ;ZERO A FOR LOOKUP
MOVC A,@A+DPTR ;GET TOKEN
INC DPTR ;ADVANCE THE TOKEN POINTER
CJNE A,#0FFH,UP_2 ;SEE IF DONE
JBC F0,UPP11 ;NOW DO NORMAL TABLE
AJMP CMND1 ;EXIT IF NOT FOUND
;
UP_2: CJNE A,R6B0,UPP2 ;LOOP UNTIL THE SAME
;
UP_3: CJNE A,#T_UOP,UP_4
UP_4: JNC UPP3
ACALL UPP7A ;PRINT THE SPACE IF OK
;
UPP3: CLR A ;DO LOOKUP
MOVC A,@A+DPTR
JB ACC.7,UPP4 ;EXIT IF DONE, ELSE SAVE
JZ UPP4 ;DONE IF ZERO
ACALL UPP7 ;SAVE THE CHARACTER
INC DPTR
SJMP UPP3 ;LOOP
;
UPP4: CALL DP_T ;GET IT BACK
MOV A,R6 ;SEE IF A REM TOKEN
XRL A,#T_REM
JNZ UPP42
UPP41: ACALL UPP8
SJMP UPP41
UPP42: JNC UPP0 ;START OVER AGAIN IF NO TOKEN
ACALL UPP7A ;PRINT THE SPACE IF OK
SJMP UPP0 ;DONE
;
UPP7A: MOV A,#' ' ;OUTPUT A SPACE
;
UPP7: AJMP PPL91 ;SAVE A
;
UPP8: INC DPTR
MOVX A,@DPTR
UPP81: CJNE A,#CR,UPP7
AJMP PPL71
;
$EJECT
;**************************************************************
;
; This table contains all of the floating point constants
;
; The constants in ROM are stored "backwards" from the way
; basic normally treats floating point numbers. Instead of
; loading from the exponent and decrementing the pointer,
; ROM constants pointers load from the most significant
; digits and increment the pointers. This is done to 1) make
; arg stack loading faster and 2) compensate for the fact that
; no decrement data pointer instruction exsist.
;
; The numbers are stored as follows:
;
; BYTE X+5 = MOST SIGNIFICANT DIGITS IN BCD
; BYTE X+4 = NEXT MOST SIGNIFICANT DIGITS IN BCD
; BYTE X+3 = NEXT LEAST SIGNIFICANT DIGITS IN BCD
; BYTE X+2 = LEAST SIGNIFICANT DIGITS IN BCD
; BYTE X+1 = SIGN OF THE ABOVE MANTISSA 0 = +, 1 = -
; BYTE X = EXPONENT IN TWO'S COMPLEMENT BINARY
; ZERO EXPONENT = THE NUMBER ZERO
;
;**************************************************************
;
ATTAB: DB 128-2 ; ARCTAN LOOKUP
DB 00H
DB 57H
DB 22H
DB 66H
DB 28H
;
DB 128-1
DB 01H
DB 37H
DB 57H
DB 16H
DB 16H
;
DB 128-1
DB 00H
DB 14H
DB 96H
DB 90H
DB 42H
;
DB 128-1
DB 01H
DB 40H
DB 96H
DB 28H
DB 75H
;
DB 128
DB 00H
DB 64H
DB 62H
DB 65H
DB 10H
;
DB 128
DB 01H
DB 99H
DB 88H
DB 20H
DB 14H
;
DB 128
DB 00H
DB 51H
DB 35H
DB 99H
DB 19H
;
DB 128
DB 01H
DB 45H
DB 31H
DB 33H
DB 33H
;
DB 129
DB 00H
DB 00H
DB 00H
DB 00H
DB 10H
;
DB 0FFH ;END OF TABLE
;
NTWO: DB 129
DB 0
DB 0
DB 0
DB 0
DB 20H
;
TTIME: DB 128-4 ; CLOCK CALCULATION
DB 00H
DB 00H
DB 00H
DB 04H
DB 13H
;
$EJECT
;***************************************************************
;
; COSINE - Add pi/2 to stack, then fall thru to SIN
;
;***************************************************************
;
ACOS: ACALL POTWO ;PUT PI/2 ON THE STACK
ACALL AADD ;TOS = TOS+PI/2
;
;***************************************************************
;
; SINE - use taylor series to calculate sin function
;
;***************************************************************
;
ASIN: ACALL PIPI ;PUT PI ON THE STACK
ACALL RV ;REDUCE THE VALUE
MOV A,MT2 ;CALCULATE THE SIGN
ANL A,#01H ;SAVE LSB
XRL MT1,A ;SAVE SIGN IN MT1
ACALL CSTAKA ;NOW CONVERT TO ONE QUADRANT
ACALL POTWO
ACALL CMPLK ;DO COMPARE
JC ASIN1
ACALL PIPI
ACALL ASUB
ASIN1: ACALL AABS
MOV DPTR,#SINTAB ;SET UP LOOKUP TABLE
ACALL POLYC ;CALCULATE THE POLY
ACALL STRIP
AJMP SIN0
;
; Put PI/2 on the stack
;
POTWO: ACALL PIPI ;PUT PI ON THE STACK, NOW DIVIDE
;
DBTWO: MOV DPTR,#NTWO
ACALL PUSHC
;MOV A,#2 ;BY TWO
;ACALL TWO_R2
AJMP ADIV
;
$EJECT
;*************************************************************
;
POLYC: ; Expand a power series to calculate a polynomial
;
;*************************************************************
;
ACALL CSTAKA2 ;COPY THE STACK
ACALL AMUL ;SQUARE THE STACK
ACALL POP_T1 ;SAVE X*X
ACALL PUSHC ;PUT CONSTANT ON STACK
;
POLY1: ACALL PUSH_T1 ;PUT COMPUTED VALUE ON STACK
ACALL AMUL ;MULTIPLY CONSTANT AND COMPUTED VALUE
ACALL PUSHC ;PUT NEXT CONSTANT ON STACK
ACALL AADD ;ADD IT TO THE OLD VALUE
CLR A ;CHECK TO SEE IF DONE
MOVC A,@A+DPTR
CJNE A,#0FFH,POLY1 ;LOOP UNTIL DONE
;
AMUL: LCALL FP_BASE3
AJMP FPTST
;
;*************************************************************
;
RV: ; Reduce a value for Trig and A**X functions
;
; value = (value/x - INT(value/x)) * x
;
;*************************************************************
;
ACALL C2_T2 ;COPY TOS TO T2
ACALL ADIV ;TOS = TOS/TEMP2
ACALL AABS ;MAKE THE TOS A POSITIVE NUMBER
MOV MT1,A ;SAVE THE SIGN
ACALL CSTAKA2 ;COPY THE STACK TWICE
ACALL IFIX ;PUT THE NUMBER IN R3:R1
PUSH R3B0 ;SAVE R3
MOV MT2,R1 ;SAVE THE LS BYTE IN MT2
ACALL AINT ;MAKE THE TOS AN INTEGER
ACALL ASUB ;TOS = TOS/T2 - INT(TOS/T2)
ACALL P_T2 ;TOS = T2
ACALL AMUL ;TOS = T2*(TOS/T2 - INT(TOS/T2)
POP R3B0 ;RESTORE R3
RET ;EXIT
;
$EJECT
;**************************************************************
;
; TAN
;
;**************************************************************
;
ATAN: ACALL CSTAKA ;DUPLACATE STACK
ACALL ASIN ;TOS = SIN(X)
ACALL SWAP_ASTKA ;TOS = X
ACALL ACOS ;TOS = COS(X)
AJMP ADIV ;TOS = SIN(X)/COS(X)
;
STRIP: ACALL SETREG ;SETUP R0
MOV R3,#1 ;LOOP COUNT
AJMP AI11 ;WASTE THE LSB
;
;************************************************************
;
; ARC TAN
;
;************************************************************
;
AATAN: ACALL AABS
MOV MT1,A ;SAVE THE SIGN
ACALL SETREG ;GET THE EXPONENT
ADD A,#7FH ;BIAS THE EXPONENT
MOV UBIT,C ;SAVE CARRY STATUS
JNC AATAN1 ;SEE IF > 1
ACALL RECIP ;IF > 1, TAKE RECIP
AATAN1: MOV DPTR,#ATTAB ;SET UP TO CALCULATE THE POLY
ACALL POLYC ;CALCULATE THE POLY
JNB UBIT,SIN0 ;JUMP IF NOT SET
ACALL ANEG ;MAKE X POLY NEGATIVE
ACALL POTWO ;SUBTRACT PI/2
ACALL AADD
;
SIN0: MOV A,MT1 ;GET THE SIGN
JZ SRT
AJMP ANEG
;
$EJECT
;*************************************************************
;
; FCOMP - COMPARE 0FFFFH TO TOS
;
;*************************************************************
;
FCMP: ACALL CSTAKA ;COPY THE STACK
ACALL FSTK ;MAKE THE TOS = 0FFFFH
ACALL SWAP_ASTKA ;NOW COMPARE IS 0FFFFH - X
;
CMPLK: JMP FP_BASE2 ;DO THE COMPARE
;
;*************************************************************
;
DEC_ASTKA: ;Push ARG STACK and check for underflow
;
;*************************************************************
;
MOV A,#-FPSIZ
ADD A,ASTKA
CJNE A,#LOW TM_TOP+6,DEC_ASTKA1
DEC_ASTKA1:
JC E4YY
MOV ASTKA,A
MOV R1,A
MOV R3,#ASTKAH
;
SRT: RET
;
E4YY: MOV DPTR,#EXA
AJMP FPTS ;ARG STACK ERROR
;
;
AXTAL3: ACALL PUSHC ;PUSH CONSTANT, THEN MULTIPLY
ACALL AMUL
;
; Fall thru to IFIX
;
$EJECT
;***************************************************************
;
IFIX: ; Convert a floating point number to an integer, put in R3:R1
;
;***************************************************************
;
CLR A ;RESET THE START
MOV R3,A
MOV R1,A
MOV R0,ASTKA ;GET THE ARG STACK
MOV P2,#ASTKAH
MOVX A,@R0 ;READ EXPONENT
CLR C
SUBB A,#81H ;BASE EXPONENT
MOV R4,A ;SAVE IT
DEC R0 ;POINT AT SIGN
MOVX A,@R0 ;GET THE SIGN
JNZ SQ_ERR ;ERROR IF NEGATIVE
JC INC_ASTKA ;EXIT IF EXPONENT IS < 81H
INC R4 ;ADJUST LOOP COUNTER
MOV A,R0 ;BUMP THE POINTER REGISTER
SUBB A,#FPSIZ-1
MOV R0,A
;
I2: INC R0 ;POINT AT DIGIT
MOVX A,@R0 ;GET DIGIT
SWAP A ;FLIP
CALL FP_BASE10 ;ACCUMULATE
JC SQ_ERR
DJNZ R4,I21
SJMP INC_ASTKA
I21: MOVX A,@R0 ;GET DIGIT
CALL FP_BASE10
JC SQ_ERR
DJNZ R4,I2
;
$EJECT
;************************************************************
;
INC_ASTKA: ; Pop the ARG STACK and check for overflow
;
;************************************************************
;
MOV A,#FPSIZ ;NUMBER TO POP
SJMP SETREG1
;
SETREG: CLR A ;DON'T POP ANYTHING
SETREG1:MOV R0,ASTKA
MOV R2,#ASTKAH
MOV P2,R2
ADD A,R0
JC E4YY
MOV ASTKA,A
MOVX A,@R0
A_D: RET
;
;************************************************************
;
; EBIAS - Bias a number for E to the X calculations
;
;************************************************************
;
EBIAS: ACALL PUSH_ONE
ACALL RV
CJNE R3,#00H,SQ_ERR ;ERROR IF R3 <> 0
ACALL C2_T2 ;TEMP 2 GETS FRACTIONS
ACALL INC_ASTKA
ACALL POP_T1
ACALL PUSH_ONE
;
AELP: MOV A,MT2
JNZ AEL1
;
MOV A,MT1
JZ A_D
MOV DPTR,#FPT2-1
MOVX @DPTR,A ;MAKE THE FRACTIONS NEGATIVE
;
RECIP: ACALL PUSH_ONE
ACALL SWAP_ASTKA
AJMP ADIV
;
AEL1: DEC MT2
ACALL PUSH_T1
ACALL AMUL
SJMP AELP
;
SQ_ERR: LJMP E3XX ;LINK TO BAD ARG
;
$EJECT
;************************************************************
;
; SQUARE ROOT
;
;************************************************************
;
ASQR: ACALL AABS ;GET THE SIGN
JNZ SQ_ERR ;ERROR IF NEGATIVE
ACALL C2_T2 ;COPY VARIABLE TO T2
ACALL POP_T1 ;SAVE IT IN T1
MOV R0,#LOW FPT1
MOVX A,@R0 ;GET EXPONENT
JZ SQR41 ;EXIT IF ZERO
ADD A,#128 ;BIAS THE EXPONENT
JNC SQR1 ;SEE IF < 80H
RR A
ANL A,#127
SJMP SQR2
;
SQR1: CPL A ;FLIP BITS
INC A
RR A
ANL A,#127 ;STRIP MSB
CPL A
INC A
;
SQR2: ADD A,#128 ;BIAS EXPONENT
MOVX @R0,A ;SAVE IT
;
; NEWGUESS = ( X/OLDGUESS + OLDGUESS) / 2
;
SQR4: ACALL P_T2 ;TOS = X
ACALL PUSH_T1 ;PUT NUMBER ON STACK
ACALL ADIV ;TOS = X/GUESS
ACALL PUSH_T1 ;PUT ON AGAIN
ACALL AADD ;TOS = X/GUESS + GUESS
ACALL DBTWO ;TOS = ( X/GUESS + GUESS ) / 2
ACALL TEMP_COMP ;SEE IF DONE
JNB F0,SQR4
;
SQR41: AJMP PUSH_T1 ;PUT THE ANSWER ON THE STACK
;
$EJECT
;*************************************************************
;
; NATURAL LOG
;
;*************************************************************
;
ALN: ACALL AABS ;MAKE SURE THAT NUM IS POSITIVE
JNZ SQ_ERR ;ERROR IF NOT
MOV MT2,A ;CLEAR FOR LOOP
INC R0 ;POINT AT EXPONENT
MOVX A,@R0 ;READ THE EXPONENT
JZ SQ_ERR ;ERROR IF EXPONENT IS ZERO
CJNE A,#81H,ALN1 ;SEE IF NUM >= 1
ALN1: MOV UBIT,C ;SAVE CARRY STATUS
JC ALNL ;TAKE RECIP IF >= 1
ACALL RECIP
;
; Loop to reduce
;
ALNL: ACALL CSTAKA ;COPY THE STACK FOR COMPARE
ACALL PUSH_ONE ;COMPARE NUM TO ONE
ACALL CMPLK
JNC ALNO ;EXIT IF DONE
ACALL SETREG ;GET THE EXPONENT
ADD A,#85H ;SEE HOW BIG IT IS
JNC ALN11 ;BUMP BY EXP(11) IF TOO SMALL
ACALL PLNEXP ;PUT EXP(1) ON STACK
MOV A,#1 ;BUMP COUNT
;
ALNE: ADD A,MT2
JC SQ_ERR
MOV MT2,A
ACALL AMUL ;BIAS THE NUMBER
SJMP ALNL
;
ALN11: MOV DPTR,#EXP11 ;PUT EXP(11) ON STACK
ACALL PUSHC
MOV A,#11
SJMP ALNE
;
$EJECT
ALNO: ACALL C2_T2 ;PUT NUM IN TEMP 2
ACALL PUSH_ONE ;TOS = 1
ACALL ASUB ;TOS = X - 1
ACALL P_T2 ;TOS = X
ACALL PUSH_ONE ;TOS = 1
ACALL AADD ;TOS = X + 1
ACALL ADIV ;TOS = (X-1)/(X+1)
MOV DPTR,#LNTAB ;LOG TABLE
ACALL POLYC
INC DPTR ;POINT AT LN(10)
ACALL PUSHC
ACALL AMUL
MOV A,MT2 ;GET THE COUNT
ACALL TWO_R2 ;PUT IT ON THE STACK
ACALL ASUB ;INT - POLY
ACALL STRIP
JNB UBIT,AABS
;
LN_D: RET
;
;*************************************************************
;
TEMP_COMP: ; Compare FPTEMP1 to TOS, FPTEMP1 gets TOS
;
;*************************************************************
;
ACALL PUSH_T1 ;SAVE THE TEMP
ACALL SWAP_ASTKA ;TRADE WITH THE NEXT NUMBER
ACALL CSTAKA ;COPY THE STACK
ACALL POP_T1 ;SAVE THE NEW NUMBER
JMP FP_BASE2 ;DO THE COMPARE
;
$EJECT
AETOX: ACALL PLNEXP ;EXP(1) ON TOS
ACALL SWAP_ASTKA ;X ON TOS
;
AEXP: ;EXPONENTIATION
;
ACALL EBIAS ;T1=BASE,T2=FRACTIONS,TOS=INT MULTIPLIED
MOV DPTR,#FPT2 ;POINT AT FRACTIONS
MOVX A,@DPTR ;READ THE EXP OF THE FRACTIONS
JZ LN_D ;EXIT IF ZERO
ACALL P_T2 ;TOS = FRACTIONS
ACALL PUSH_T1 ;TOS = BASE
ACALL SETREG ;SEE IF BASE IS ZERO
JZ AEXP1
ACALL ALN ;TOS = LN(BASE)
AEXP1: ACALL AMUL ;TOS = FRACTIONS * LN(BASE)
ACALL PLNEXP ;TOS = EXP(1)
ACALL SWAP_ASTKA ;TOS = FRACTIONS * LN(BASE)
ACALL EBIAS ;T2 = FRACTIONS, TOS = INT MULTIPLIED
MOV MT2,#00H ;NOW CALCULATE E**X
ACALL PUSH_ONE
ACALL CSTAKA
ACALL POP_T1 ;T1 = 1
;
AEXL: ACALL P_T2 ;TOS = FRACTIONS
ACALL AMUL ;TOS = FRACTIONS * ACCUMLATION
INC MT2 ;DO THE DEMONIATOR
MOV A,MT2
ACALL TWO_R2
ACALL ADIV
ACALL CSTAKA ;SAVE THE ITERATION
ACALL PUSH_T1 ;NOW ACCUMLATE
ACALL AADD ;ADD ACCUMLATION
ACALL TEMP_COMP
JNB F0,AEXL ;LOOP UNTIL DONE
;
ACALL INC_ASTKA
ACALL PUSH_T1
ACALL AMUL ;LAST INT MULTIPLIED
;
MU1: AJMP AMUL ;FIRST INT MULTIPLIED
;
$EJECT
;***************************************************************
;
; integer operator - INT
;
;***************************************************************
;
AINT: ACALL SETREG ;SET UP THE REGISTERS, CLEAR CARRY
SUBB A,#129 ;SUBTRACT EXPONENT BIAS
JNC AI1 ;JUMP IF ACC > 81H
;
; Force the number to be a zero
;
ACALL INC_ASTKA ;BUMP THE STACK
;
P_Z: MOV DPTR,#ZRO ;PUT ZERO ON THE STACK
AJMP PUSHC
;
AI1: SUBB A,#7
JNC AI3
CPL A
INC A
MOV R3,A
AI11: DEC R0 ;POINT AT SIGN
;
AI2: DEC R0 ;NOW AT LSB'S
MOVX A,@R0 ;READ BYTE
ANL A,#0F0H ;STRIP NIBBLE
MOVX @R0,A ;WRITE BYTE
DJNZ R3,AI21
RET
AI21: CLR A
MOVX @R0,A ;CLEAR THE LOCATION
DJNZ R3,AI2
;
AI3: RET ;EXIT
;
$EJECT
;***************************************************************
;
AABS: ; Absolute value - Make sign of number positive
; return sign in ACC
;
;***************************************************************
;
ACALL ANEG ;CHECK TO SEE IF + OR -
JNZ ALPAR ;EXIT IF NON ZERO, BECAUSE THE NUM IS
MOVX @R0,A ;MAKE A POSITIVE SIGN
RET
;
;***************************************************************
;
ASGN: ; Returns the sign of the number 1 = +, -1 = -
;
;***************************************************************
;
ACALL INC_ASTKA ;POP STACK, GET EXPONENT
JZ P_Z ;EXIT IF ZERO
DEC R0 ;BUMP TO SIGN
MOVX A,@R0 ;GET THE SIGN
MOV R7,A ;SAVE THE SIGN
ACALL PUSH_ONE ;PUT A ONE ON THE STACK
MOV A,R7 ;GET THE SIGN
JZ ALPAR ;EXIT IF ZERO
;
; Fall thru to ANEG
;
;***************************************************************
;
ANEG: ; Flip the sign of the number on the tos
;
;***************************************************************
;
ACALL SETREG
DEC R0 ;POINT AT THE SIGN OF THE NUMBER
JZ ALPAR ;EXIT IF ZERO
MOVX A,@R0
XRL A,#01H ;FLIP THE SIGN
MOVX @R0,A
XRL A,#01H ;RESTORE THE SIGN
;
ALPAR: RET
;
$EJECT
;***************************************************************
;
ACBYTE: ; Read the ROM
;
;***************************************************************
;
ACALL IFIX ;GET EXPRESSION
CALL X31DP ;PUT R3:R1 INTO THE DP
CLR A
MOVC A,@A+DPTR
AJMP TWO_R2
;
;***************************************************************
;
ADBYTE: ; Read internal memory
;
;***************************************************************
;
ACALL IFIX ;GET THE EXPRESSION
CALL R3CK ;MAKE SURE R3 = 0
MOV A,@R1
AJMP TWO_R2
;
;***************************************************************
;
AXBYTE: ; Read external memory
;
;***************************************************************
;
ACALL IFIX ;GET THE EXPRESSION
AXBYTE1:MOV P2,R3
MOVX A,@R1
AJMP TWO_R2
;
$EJECT
;***************************************************************
;
; The relational operators - EQUAL (=)
; GREATER THAN (>)
; LESS THAN (<)
; GREATER THAN OR EQUAL (>=)
; LESS THAN OR EQUAL (<=)
; NOT EQUAL (<>)
;
;***************************************************************
;
AGT: ACALL CMPLK
ORL C,F0 ;SEE IF EITHER IS A ONE
AGT1: JC P_Z
;
FSTK: MOV DPTR,#FS
AJMP PUSHC
;
FS: DB 85H
DB 00H
DB 00H
DB 50H
DB 53H
DB 65H
;
ALT: ACALL CMPLK
ALT1: CPL C
SJMP AGT1
;
AEQ: ACALL CMPLK
AEQ1: MOV C,F0
SJMP ALT1
;
ANE: ACALL CMPLK
CPL F0
SJMP AEQ1
;
AGE: ACALL CMPLK
SJMP AGT1
;
ALE: ACALL CMPLK
ORL C,F0
SJMP ALT1
;
$EJECT
;***************************************************************
;
ARND: ; Generate a random number
;
;***************************************************************
;
MOV DPTR,#RCELL ;GET THE BINARY SEED
CALL L31DPI
MOV A,R1
CLR C
RRC A
MOV R0,A
MOV A,#6
RRC A
ADD A,R1
XCH A,R0
ADDC A,R3
MOV R2,A
DEC DPL ;SAVE THE NEW SEED
ACALL S20DP
ACALL TWO_EY
ACALL FSTK
;
ADIV: LCALL FP_BASE4
AJMP FPTST
;
$EJECT
;***************************************************************
;
SONERR: ; ON ERROR Statement
;
;***************************************************************
;
LCALL INTERR ;GET THE LINE NUMBER
SETB ON_ERR
MOV DPTR,#ERRNUM ;POINT AT THR ERROR LOCATION
SJMP S20DP
;
;
;**************************************************************
;
SONEXT: ; ON EXT1 Statement
;
;**************************************************************
;
LCALL INTERR
SETB INTBIT
ORL IE,#10000100B ;ENABLE INTERRUPTS
MOV DPTR,#INTLOC
;
S20DP: MOV A,R2 ;SAVE R2:R0 @DPTR
MOVX @DPTR,A
INC DPTR
MOV A,R0
MOVX @DPTR,A
RET
;
$EJECT
;***************************************************************
;
; CASTAK - Copy and push another top of arg stack
;
;***************************************************************
;
CSTAKA2:ACALL CSTAKA ;COPY STACK TWICE
;
CSTAKA: ACALL SETREG ;SET UP R2:R0
SJMP PUSH_T12
;
PLNEXP: MOV DPTR,#EXP1
;
;***************************************************************
;
; PUSHC - Push constant on to the arg stack
;
;***************************************************************
;
PUSHC: ACALL DEC_ASTKA
MOV P2,R3
MOV R3,#FPSIZ ;LOOP COUNTER
;
PCL: CLR A ;SET UP A
MOVC A,@A+DPTR ;LOAD IT
MOVX @R1,A ;SAVE IT
INC DPTR ;BUMP POINTERS
DEC R1
DJNZ R3,PCL ;LOOP
;
SETB ARGF
RET ;EXIT
;
PUSH_ONE:;
;
MOV DPTR,#FPONE
AJMP PUSHC
;
$EJECT
;
POP_T1:
;
MOV R3,#HIGH FPT1
MOV R1,#LOW FPT1
JMP POPAS
;
PUSH_T1:
;
MOV R0,#LOW FPT1
PUSH_T11:
MOV R2,#HIGH FPT1
PUSH_T12:
LJMP PUSHAS
;
P_T2: MOV R0,#LOW FPT2
SJMP PUSH_T11 ;JUMP TO PUSHAS
;
;****************************************************************
;
SWAP_ASTKA: ; SWAP TOS<>TOS-1
;
;****************************************************************
;
ACALL SETREG ;SET UP R2:R0 AND P2
MOV A,#FPSIZ ;PUT TOS+1 IN R1
MOV R2,A
ADD A,R0
MOV R1,A
;
S_L: MOVX A,@R0
MOV R3,A
MOVX A,@R1
MOVX @R0,A
MOV A,R3
MOVX @R1,A
DEC R1
DEC R0
DJNZ R2,S_L
RET
;
$EJECT
;
C2_T2: ACALL SETREG ;SET UP R2:R0
MOV R3,#HIGH FPT2
MOV R1,#LOW FPT2 ;TEMP VALUE
;
; Fall thru
;
;***************************************************************
;
; VARCOP - Copy a variable from R2:R0 to R3:R1
;
;***************************************************************
;
VARCOP: MOV R4,#FPSIZ ;LOAD THE LOOP COUNTER
;
V_C: MOV P2,R2 ;SET UP THE PORTS
MOVX A,@R0 ;READ THE VALUE
MOV P2,R3 ;PORT TIME AGAIN
MOVX @R1,A ;SAVE IT
ACALL DEC3210 ;BUMP POINTERS
DJNZ R4,V_C ;LOOP
RET ;EXIT
;
PIPI: MOV DPTR,#PIE
AJMP PUSHC
;
$EJECT
;***************************************************************
;
; The logical operators ANL, ORL, XRL, NOT
;
;***************************************************************
;
AANL: ACALL TWOL ;GET THE EXPRESSIONS
MOV A,R3 ;DO THE AND
ANL A,R7
MOV R2,A
MOV A,R1
ANL A,R6
SJMP TWO_EX
;
AORL: ACALL TWOL ;SAME THING FOR OR
MOV A,R3
ORL A,R7
MOV R2,A
MOV A,R1
ORL A,R6
SJMP TWO_EX
;
ANOT: ACALL FSTK ;PUT 0FFFFH ON THE STACK
;
AXRL: ACALL TWOL
MOV A,R3
XRL A,R7
MOV R2,A
MOV A,R1
XRL A,R6
SJMP TWO_EX
;
TWOL: ACALL IFIX
MOV R7,R3B0
MOV R6,R1B0
AJMP IFIX
;
$EJECT
;*************************************************************
;
AGET: ; READ THE BREAK BYTE AND PUT IT ON THE ARG STACK
;
;*************************************************************
;
MOV DPTR,#GTB ;GET THE BREAK BYTE
MOVX A,@DPTR
JBC GTRD,TWO_R2
CLR A
;
TWO_R2: MOV R2,#00H ;ACC GOES TO STACK
;
;
TWO_EX: MOV R0,A ;R2:ACC GOES TO STACK
;
;
TWO_EY: SETB ARGF ;R2:R0 GETS PUT ON THE STACK
JMP FP_BASE12 ;DO IT
;
$EJECT
;*************************************************************
;
; Put directs onto the stack
;
;**************************************************************
;
A_IE: MOV A,IE ;IE
SJMP TWO_R2
;
A_IP: MOV A,IP ;IP
SJMP TWO_R2
;
ATIM0: MOV R2,TH0 ;TIMER 0
MOV R0,TL0
SJMP TWO_EY
;
ATIM1: MOV R2,TH1 ;TIMER 1
MOV R0,TL1
SJMP TWO_EY
;
ATIM2: MOV R2,TH2
MOV R0,TL2
; DB 0AAH ;MOV R2 DIRECT OP CODE
; DB 0CDH ;T2 HIGH
; DB 0A8H ;MOV R0 DIRECT OP CODE
; DB 0CCH ;T2 LOW
SJMP TWO_EY ;TIMER 2
;
AT2CON: MOV A,T2CON
; DB 0E5H ;MOV A,DIRECT OPCODE
; DB 0C8H ;T2CON LOCATION
SJMP TWO_R2
;
ATCON: MOV A,TCON ;TCON
SJMP TWO_R2
;
ATMOD: MOV A,TMOD ;TMOD
SJMP TWO_R2
;
ARCAP2: MOV R2,RCAPH2
MOV R0,RCAPL2
; DB 0AAH ;MOV R2, DIRECT OP CODE
; DB 0CBH ;RCAP2H LOCATION
; DB 0A8H ;MOV R0, DIRECT OP CODE
; DB 0CAH ;R2CAPL LOCATION
SJMP TWO_EY
;
AP1: MOV A,P1 ;GET P1
SJMP TWO_R2 ;PUT IT ON THE STACK
;
APCON: MOV A,PCON
; DB 0E5H ;MOV A, DIRECT OP CODE
; DB 87H ;ADDRESS OF PCON
SJMP TWO_R2 ;PUT PCON ON THE STACK
;
$EJECT
;***************************************************************
;
;THIS IS THE LINE EDITOR
;
;TAKE THE PROCESSED LINE IN IBUF AND INSERT IT INTO THE
;BASIC TEXT FILE.
;
;***************************************************************
;
LINE0: LJMP NOGO ;CAN'T EDIT A ROM
;
LINE: MOV A,BOFAH
CJNE A,#HIGH PSTART,LINE0
CALL G4 ;GET END ADDRESS FOR EDITING
MOV R4,DPL
MOV R5,DPH
MOV R3,TEMP5 ;GET HIGH ORDER IBLN
MOV R1,TEMP4 ;LOW ORDER IBLN
;
CALL GETLIN ;FIND THE LINE
JNZ INSR ;INSERT IF NOT ZERO, ELSE APPEND
;
;APPEND THE LINE AT THE END
;
MOV A,TEMP3 ;PUT IBCNT IN THE ACC
CJNE A,#4H,LINE1 ;SEE IF NO ENTRY
RET ;RET IF NO ENTRY
;
LINE1: ACALL FULL ;SEE IF ENOUGH SPACE LEFT
MOV R2,R5B0 ;PUT END ADDRESS A INTO TRANSFER
MOV R0,R4B0 ;REGISTERS
ACALL IMOV ;DO THE BLOCK MOVE
;
UE: MOV A,#EOF ;SAVE EOF CHARACTER
AJMP TBR
;
;INSERT A LINE INTO THE FILE
;
INSR: MOV R7,A ;SAVE IT IN R7
CALL TEMPD ;SAVE INSERATION ADDRESS
MOV A,TEMP3 ;PUT THE COUNT LENGTH IN THE ACC
JC LTX ;JUMP IF NEW LINE # NOT = OLD LINE #
CJNE A,#04H,INSR1 ;SEE IF NULL
CLR A
;
INSR1: SUBB A,R7 ;SUBTRACT LINE COUNT FROM ACC
JZ LIN1 ;LINE LENGTHS EQUAL
JC GTX ;SMALLER LINE
;
$EJECT
;
;EXPAND FOR A NEW LINE OR A LARGER LINE
;
LTX: MOV R7,A ;SAVE A IN R7
MOV A,TEMP3 ;GET THE COUNT IN THE ACC
CJNE A,#04H,LTX1 ;DO NO INSERTATION IF NULL LINE
RET ;EXIT IF IT IS
;
LTX1: MOV A,R7 ;GET THE COUNT BACK - DELTA IN A
ACALL FULL ;SEE IF ENOUGH MEMORY NEW EOFA IN R3:R1
CALL DTEMP ;GET INSERATION ADDRESS
ACALL NMOV ;R7:R6 GETS (EOFA)-DPTR
CALL X3120
MOV R1,R4B0 ;EOFA LOW
MOV R3,R5B0 ;EOFA HIGH
INC R6 ;INCREMENT BYTE COUNT
CJNE R6,#00,LTX2 ;NEED TO BUMP HIGH BYTE?
INC R7
;
LTX2: ACALL RMOV ;GO DO THE INSERTION
SJMP LIN1 ;INSERT THE CURRENT LINE
;
GTX: CPL A ;FLIP ACC
INC A ;TWOS COMPLEMENT
CALL ADDPTR ;DO THE ADDITION
ACALL NMOV ;R7:R6 GETS (EOFA)-DPTR
MOV R1,DPL ;SET UP THE REGISTERS
MOV R3,DPH
MOV R2,TEMP5 ;PUT INSERTATION ADDRESS IN THE RIGHT REG
MOV R0,TEMP4
JZ GTX1 ;IF ACC WAS ZERO FROM NMOV, JUMP
ACALL LMOV ;IF NO ZERO DO A LMOV
;
GTX1: ACALL UE ;SAVE NEW END ADDRESS
;
LIN1: MOV R2,TEMP5 ;GET THE INSERTATION ADDRESS
MOV R0,TEMP4
MOV A,TEMP3 ;PUT THE COUNT LENGTH IN ACC
CJNE A,#04H,IMOV ;SEE IF NULL
RET ;EXIT IF NULL
$EJECT
;***************************************************************
;
;INSERT A LINE AT ADDRESS R2:R0
;
;***************************************************************
;
IMOV: CLR A ;TO SET UP
MOV R1,#LOW IBCNT ;INITIALIZE THE REGISTERS
MOV R3,A
MOV R6,TEMP3 ;PUT THE BYTE COUNT IN R6 FOR LMOV
MOV R7,A ;PUT A 0 IN R7 FOR LMOV
;
;***************************************************************
;
;COPY A BLOCK FROM THE BEGINNING
;
;R2:R0 IS THE DESTINATION ADDRESS
;R3:R1 IS THE SOURCE ADDRESS
;R7:R6 IS THE COUNT REGISTER
;
;***************************************************************
;
LMOV: ACALL TBYTE ;TRANSFER THE BYTE
ACALL INC3210 ;BUMP THE POINTER
ACALL DEC76 ;BUMP R7:R6
JNZ LMOV ;LOOP
RET ;GO BACK TO CALLING ROUTINE
;
INC3210:INC R0
CJNE R0,#00H,INC3211
INC R2
;
INC3211:INC R1
CJNE R1,#00H,INC3212
INC R3
INC3212:RET
;
$EJECT
;***************************************************************
;
;COPY A BLOCK STARTING AT THE END
;
;R2:R0 IS THE DESTINATION ADDRESS
;R3:R1 IS THE SOURCE ADDRESS
;R6:R7 IS THE COUNT REGISTER
;
;***************************************************************
;
RMOV: ACALL TBYTE ;TRANSFER THE BYTE
ACALL DEC3210 ;DEC THE LOCATIONS
ACALL DEC76 ;BUMP THE COUNTER
JNZ RMOV ;LOOP
;
DEC_R: NOP ;CREATE EQUAL TIMING
RET ;EXIT
;
DEC3210:DEC R0 ;BUMP THE POINTER
CJNE R0,#0FFH,DEC3212;SEE IF OVERFLOWED
DEC3211:DEC R2 ;BUMP THE HIGH BYTE
DEC3212:DEC R1 ;BUMP THE POINTER
CJNE R1,#0FFH,DEC_R ;SEE IF OVERFLOWED
DEC R3 ;CHANGE THE HIGH BYTE
RET ;EXIT
;
;***************************************************************
;
;TBYTE - TRANSFER A BYTE
;
;***************************************************************
;
TBYTE: MOV P2,R3 ;OUTPUT SOURCE REGISTER TO PORT
MOVX A,@R1 ;PUT BYTE IN ACC
;
TBR: MOV P2,R2 ;OUTPUT DESTINATION TO PORT
MOVX @R0,A ;SAVE THE BYTE
RET ;EXIT
;
$EJECT
;***************************************************************
;
;NMOV - R7:R6 = END ADDRESS - DPTR
;
;ACC GETS CLOBBERED
;
;***************************************************************
;
NMOV: MOV A,R4 ;THE LOW BYTE OF EOFA
CLR C ;CLEAR THE CARRY FOR SUBB
SUBB A,DPL ;SUBTRACT DATA POINTER LOW
MOV R6,A ;PUT RESULT IN R6
MOV A,R5 ;HIGH BYTE OF EOFA
SUBB A,DPH ;SUBTRACT DATA POINTER HIGH
MOV R7,A ;PUT RESULT IN R7
ORL A,R6 ;SEE IF ZERO
NMOV1: RET ;EXIT
;
;***************************************************************
;
;CHECK FOR A FILE OVERFLOW
;LEAVES THE NEW END ADDRESS IN R3:R1
;A HAS THE INCREASE IN SIZE
;
;***************************************************************
;
FULL: ADD A,R4 ;ADD A TO END ADDRESS
MOV R1,A ;SAVE IT
CLR A
ADDC A,R5 ;ADD THE CARRY
MOV R3,A
MOV DPTR,#VARTOP ;POINT AT VARTOP
;
FUL1: CALL DCMPX ;COMPARE THE TWO
JC NMOV1 ;OUT OF ROOM
;
TB: MOV DPTR,#E5X ;OUT OF MEMORY
AJMP FPTS
;
$EJECT
;***************************************************************
;
; PP - Preprocesses the line in IBUF back into IBUF
; sets F0 if no line number
; leaves the correct length of processed line in IBCNT
; puts the line number in IBLN
; wastes the text address TXAL and TXAH
;
;***************************************************************
;
PP: ACALL T_BUF ;TXA GETS IBUF
CALL INTGER ;SEE IF A NUMBER PRESENT
CALL TEMPD ;SAVE THE INTEGER IN TEMP5:TEMP4
MOV F0,C ;SAVE INTEGER IF PRESENT
MOV DPTR,#IBLN ;SAVE THE LINE NUMBER, EVEN IF NONE
ACALL S20DP
MOV R0,TXAL ;TEXT POINTER
MOV R1,#LOW IBUF ;STORE POINTER
;
; Now process the line back into IBUF
;
PPL: CLR ARGF ;FIRST PASS DESIGNATOR
MOV DPTR,#TOKTAB ;POINT DPTR AT LOOK UP TABLE
;
PPL1: MOV R5B0,R0 ;SAVE THE READ POINTER
CLR A ;ZERO A FOR LOOKUP
MOVC A,@A+DPTR ;GET THE TOKEN
MOV R7,A ;SAVE TOKEN IN CASE OF MATCH
;
PPL2: MOVX A,@R0 ;GET THE USER CHARACTER
MOV R3,A ;SAVE FOR REM
CJNE A,#'a',PPL21
PPL21: JC PPX ;CONVERT LOWER TO UPPER CASE
CJNE A,#('z'+1),PPL22
PPL22: JNC PPX
CLR ACC.5
;
PPX: MOV R2,A
MOVX @R0,A ;SAVE UPPER CASE
INC DPTR ;BUMP THE LOOKUP POINTER
CLR A
MOVC A,@A+DPTR
CJNE A,R2B0,PPL3 ;LEAVE IF NOT THE SAME
INC R0 ;BUMP THE USER POINTER
SJMP PPL2 ;CONTINUE TO LOOP
;
PPL3: JB ACC.7,PPL6 ;JUMP IF FOUND MATCH
JZ PPL6 ;USER MATCH
;
;
; Scan to the next TOKTAB entry
;
PPL4: INC DPTR ;ADVANCE THE POINTER
CLR A ;ZERO A FOR LOOKUP
MOVC A,@A+DPTR ;LOAD A WITH TABLE
JB ACC.7,PPL41 ;KEEP SCANNING IF NOT A RESERVED WORD
JNZ PPL4
INC DPTR
;
; See if at the end of TOKTAB
;
PPL41: MOV R0,R5B0 ;RESTORE THE POINTER
CJNE A,#0FFH,PPL1 ;SEE IF END OF TABLE
;
; Character not in TOKTAB, so see what it is
;
CJNE R2,#' ',PPLX ;SEE IF A SPACE
INC R0 ;BUMP USER POINTER
SJMP PPL ;TRY AGAIN
;
PPLX: JNB XBIT,PPLY ;EXTERNAL TRAP
JB ARGF,PPLY
SETB ARGF ;SAYS THAT THE USER HAS TABLE
LCALL 2078H ;SET UP POINTER
AJMP PPL1
;
PPLY: ACALL PPL7 ;SAVE CHARACTER, EXIT IF A CR
CJNE A,#'"',PPL ;SEE IF QUOTED STRING, START AGAIN IF NOT
;
; Just copy a quoted string
;
PPLY1: ACALL PPL7 ;SAVE THE CHARACTER, TEST FOR CR
CJNE A,#'"',PPLY1 ;IS THERE AN ENDQUOTE, IF NOT LOOP
SJMP PPL ;DO IT AGAIN IF ENDQUOTE
;
PPL6: MOV A,R7 ;GET THE TOKEN
ACALL PPL91 ;SAVE THE TOKEN
CJNE A,#T_REM,PPL ;SEE IF A REM TOKEN
MOV A,R3
ACALL PPL71 ;WASTE THE REM STATEMENT
PPL61: ACALL PPL7 ;LOOP UNTIL A CR
SJMP PPL61
;
PPL7: MOVX A,@R0 ;GET THE CHARACTER
PPL71: CJNE A,#CR,PPL9 ;FINISH IF A CR
POP R0B0 ;WASTE THE CALLING STACK
POP R0B0
MOVX @R1,A ;SAVE CR IN MEMORY
INC R1 ;SAVE A TERMINATOR
MOV A,#EOF
MOVX @R1,A
MOV A,R1 ;SUBTRACT FOR LENGTH
SUBB A,#4
MOV TEMP3,A ;SAVE LENGTH
MOV R1,#LOW IBCNT ;POINT AT BUFFER COUNT
;
PPL9: INC R0
PPL91: MOVX @R1,A ;SAVE THE CHARACTER
INC R1 ;BUMP THE POINTERS
RET ;EXIT TO CALLING ROUTINE
;
;
;***************************************************************
;
;DEC76 - DECREMENT THE REGISTER PAIR R7:R6
;
;ACC = ZERO IF R7:R6 = ZERO ; ELSE ACC DOES NOT
;
;***************************************************************
;
DEC76: DEC R6 ;BUMP R6
CJNE R6,#0FFH,DEC77 ;SEE IF RAPPED AROUND
DEC R7
DEC77: MOV A,R7 ;SEE IF ZERO
ORL A,R6
RET ;EXIT
;
;***************************************************************
;
; MTOP - Get or Put the top of assigned memory
;
;***************************************************************
;
PMTOP: MOV DPTR,#MEMTOP
PMTOP1: CALL L20DPI
AJMP TWO_EY ;PUT R2:R0 ON THE STACK
;
$EJECT
;*************************************************************
;
; AXTAL - Crystal value calculations
;
;*************************************************************
;
AXTAL0: MOV DPTR,#XTALV ;CRYSTAL VALUE
ACALL PUSHC
;
AXTAL1: ACALL CSTAKA2 ;COPY CRYSTAL VALUE TWICE
ACALL CSTAKA
MOV DPTR,#PTIME ;PROM TIMER
ACALL AXTAL2
MOV DPTR,#PROGS
ACALL S31L
MOV DPTR,#IPTIME ;IPROM TIMER
ACALL AXTAL2
MOV DPTR,#IPROGS
ACALL S31L
MOV DPTR,#TTIME ;CLOCK CALCULATION
ACALL AXTAL3
MOV A,R1
CPL A
INC A
MOV SAVE_T,A
MOV R3,#HIGH CXTAL
MOV R1,#LOW CXTAL
JMP POPAS
;
AXTAL2: ACALL AXTAL3
;
CBIAS: ;Bias the crystal calculations
;
MOV A,R1 ;GET THE LOW COUNT
CPL A ;FLIP IT FOR TIMER LOAD
ADD A,#15 ;BIAS FOR CALL AND LOAD TIMES
MOV R1,A ;RESTORE IT
MOV A,R3 ;GET THE HIGH COUNT
CPL A ;FLIP IT
ADDC A,#00H ;ADD THE CARRY
MOV R3,A ;RESTORE IT
RET
;
$EJECT
;$INCLUDE(:F2:BAS52.PWM)
;BEGINNING
;**************************************************************
;
STONE: ; Toggle the I/O port
;
;**************************************************************
;
CALL THREE ;GET THE NUMBERS
ACALL CBIAS ;BIAS R3:R1 FOR COUNT LOOP
;
STONE1: CLR T_BIT ;TOGGLE THE BIT
CLR TR1 ;STOP THE TIMER
MOV TH1,R3 ;LOAD THE TIMER
MOV TL1,R1
CLR TF1 ;CLEAR THE OVERFLOW FLAG
SETB TR1 ;TURN IT ON
ACALL DEC76
JNB TF1,$ ;WAIT
ACALL ALPAR
SETB T_BIT ;BACK TO A ONE
CALL TIMER_LOAD1 ;LOAD THE HIGH VALUE
JNB TF1,$ ;WAIT
JNZ STONE1 ;LOOP
RET
;
;END
;$INCLUDE(:F2:BAS52.PWM)
$EJECT
;LNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLN
;
LNTAB: ; Natural log lookup table
;
;LNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLN
;
DB 80H
DB 00H
DB 71H
DB 37H
DB 13H
DB 19H
;
DB 7FH
DB 00H
DB 76H
DB 64H
DB 37H
DB 94H
;
DB 80H
DB 00H
DB 07H
DB 22H
DB 75H
DB 17H
;
DB 80H
DB 00H
DB 52H
DB 35H
DB 93H
DB 28H
;
DB 80H
DB 00H
DB 71H
DB 91H
DB 85H
DB 86H
;
DB 0FFH
;
DB 81H
DB 00H
DB 51H
DB 58H
DB 02H
DB 23H
;
$EJECT
;SINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSIN
;
SINTAB: ; Sin lookup table
;
;SINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSIN
;
DB 128-9
DB 00H
DB 44H
DB 90H
DB 05H
DB 16H
;
DB 128-7
DB 01H
DB 08H
DB 21H
DB 05H
DB 25H
;
DB 128-5
DB 00H
DB 19H
DB 73H
DB 55H
DB 27H
;
$EJECT
;
DB 128-3
DB 01H
DB 70H
DB 12H
DB 84H
DB 19H
;
DB 128-2
DB 00H
DB 33H
DB 33H
DB 33H
DB 83H
;
DB 128
DB 01H
DB 67H
DB 66H
DB 66H
DB 16H
;
FPONE: DB 128+1
DB 00H
DB 00H
DB 00H
DB 00H
DB 10H
;
DB 0FFH ;END OF TABLE
;
$EJECT
;
SBAUD: CALL AXTAL ;PUT CRYSTAL ON THE STACK
CALL EXPRB ;PUT THE NUMBER AFTER BAUD ON STACK
MOV A,#12
ACALL TWO_R2 ;TOS = 12
ACALL AMUL ;TOS = 12*BAUD
ACALL ADIV ;TOS = XTAL/(12*BAUD)
ACALL IFIX
ACALL CBIAS
MOV DPTR,#SPV
;
S31L: JMP S31DP
;
AFREE: CALL PMTOP ;PUT MTOP ON STACK
CALL G4 ;GET END ADDRESS
MOV R0,DPL
MOV R2,DPH
ACALL TWO_EY
;
ASUB: LCALL FP_BASE1 ;DO FP SUB
AJMP FPTST
;
ALEN: CALL CCAL ;CALCULATE THE LEN OF THE SELECTED PROGRAM
MOV R2,R7B0 ;SAVE THE HIGH BYTE
MOV A,R6 ;SAVE THE LOW BYTE
AJMP TWO_EX ;PUT IT ON THE STACK
;
ATIME: MOV C,EA ;SAVE INTERRUTS
CLR EA
PUSH MILLIV ;SAVE MILLI VALUE
MOV R2,TVH ;GET THE TIMER
MOV A,TVL
MOV EA,C ;SAVE INTERRUPTS
ACALL TWO_EX ;PUT TIMER ON THE STACK
POP ACC ;GET MILLI
ACALL TWO_R2 ;PUT MILLI ON STACK
MOV A,#200
ACALL TWO_R2 ;DIVIDE MILLI BY 200
ACALL ADIV
;
AADD: LCALL FP_BASE ;DO FP ADDITION
AJMP FPTST ;CHECK FOR ERRORS
;
$EJECT
;**************************************************************
;
; Here are some error messages that were moved
;
;**************************************************************
;
;
E1X: DB 'BAD SYNTAX"'
E2X: DB 128+10
DB 'DIVIDE BY ZERO"'
;
E6X: DB 'ARRAY SIZE"'
;
$EJECT
;**************************************************************
;
T_BUF: ; TXA gets IBUF
;
;**************************************************************
;
MOV TXAH,#HIGH IBUF
MOV TXAL,#LOW IBUF
RET
;
;
;***************************************************************
;
CXFER: ; Transfer a program from rom to ram
;
;***************************************************************
;
CALL CCAL ;GET EVERYTHING SET UP
MOV R2,#HIGH PSTART
MOV R0,#LOW PSTART
ACALL LMOV ;DO THE TRANSFER
CALL RCLEAR ;CLEAR THE MEMORY
;
; Fall thru to CRAM
;
;***************************************************************
;
CRAM: ; The command action routine - RAM - Run out of ram
;
;***************************************************************
;
CLR CONB ;CAN'T CONTINUE IF MODE CHANGE
MOV BOFAH,#HIGH PSTART
MOV BOFAL,#LOW PSTART
;
; Fall thru to Command Processor
;
$EJECT
;***************************************************************
;
CMND1: ; The entry point for the command processor
;
;***************************************************************
;
LCALL SPRINT1 ;WASTE AT AND HEX
CLR XBIT ;TO RESET IF NEEDED
CLR A
MOV DPTR,#2002H ;CHECK FOR EXTERNAL TRAP PACKAGE
MOVC A,@A+DPTR
CJNE A,#5AH,CMND11
LCALL 2048H ;IF PRESENT JUMP TO LOCATION 200BH
CMND11: MOV DPTR,#RDYS ;PRINT THE READY MESSAGE
CALL CRP ;DO A CR, THEN, PRINT FROM THE ROM
;
CMNDR: SETB DIRF ;SET THE DIRECT INPUT BIT
MOV SP,SPSAV ;LOAD THE STACK
ACALL CL7 ;DO A CRLF
;
CMNX: CLR GTRD ;CLEAR BREAK
MOV DPTR,#5EH ;DO RUN TRAP
MOVX A,@DPTR
XRL A,#52
JNZ CMNX1
LJMP CRUN
CMNX1: MOV R5,#'>' ;OUTPUT A PROMPT
LCALL TEROT
CALL INLINE ;INPUT A LINE INTO IBUF
CALL PP ;PRE-PROCESS THE LINE
JB F0,CMND3 ;NO LINE NUMBER
CALL LINE ;PROCESS THE LINE
LCALL LCLR
JB LINEB,CMNX ;DON'T CLEAR MEMORY IF NO NEED
SETB LINEB
LCALL RCLEAR ;CLEAR THE MEMORY
SJMP CMNX ;LOOP BACK
;
CMND3: CALL T_BUF ;SET UP THE TEXT POINTER
CALL DELTST ;GET THE CHARACTER
JZ CMNDR ;IF CR, EXIT
MOV DPTR,#CMNDD ;POINT AT THE COMMAND LOOKUP
CJNE A,#T_CMND,CMND31;PROCESS STATEMENT IF NOT A COMMAND
CMND31: JC CMND5
CALL GCI1 ;BUMP TXA
ANL A,#0FH ;STRIP MSB'S FOR LOOKUP
LCALL ISTA1 ;PROCESS COMMAND
SJMP CMNDR
;
CMND5: LJMP ILOOP ;CHECK FOR A POSSIBLE BREAK
;
;
;
;CONSTANTS
;
XTALV: DB 128+8 ; DEFAULT CRYSTAL VALUE
DB 00H
DB 00H
DB 92H
DB 05H
DB 11H
;
EXP11: DB 85H
DB 00H
DB 42H
DB 41H
DB 87H
DB 59H
;
EXP1: DB 128+1 ; EXP(1)
DB 00H
DB 18H
DB 28H
DB 18H
DB 27H
;
IPTIME: DB 128-4 ;FPROG TIMING
DB 00H
DB 00H
DB 00H
DB 75H
DB 83H
;
PIE: DB 128+1 ;PI
DB 00H
DB 26H
DB 59H
DB 41H
DB 31H ; 3.1415926
;
$EJECT
;***************************************************************
;
; The error messages, some have been moved
;
;***************************************************************
;
E7X: DB 128+30
DB 'ARITH. UNDERFLOW"'
;
E5X: DB 'MEMORY ALLOCATION"'
;
E3X: DB 128+40
DB 'BAD ARGUMENT"'
;
EXI: DB 'I-STACK"'
;
$EJECT
;***************************************************************
;
; The command action routine - CONTINUE
;
;***************************************************************
;
CCONT: MOV DPTR,#E15X
JNB CONB,ERROR ;ERROR IF CONTINUE IS NOT SET
;
CC1: ;used for input statement entry
;
MOV TXAH,INTXAH ;RESTORE TXA
MOV TXAL,INTXAL
JMP CILOOP ;EXECUTE
;
DTEMP: MOV DPH,TEMP5 ;RESTORE DPTR
MOV DPL,TEMP4
RET
;
TEMPD: MOV TEMP5,DPH
MOV TEMP4,DPL
RET
;
$EJECT
;**************************************************************
;
I_DL: ; IDLE
;
;**************************************************************
;
JB DIRF,E1XX ;SYNTAX ERROR IN DIRECT INPUT
CLR DACK ;ACK IDLE
;
U_ID1: ORL PCON,#01H
; DB 01000011B ;ORL DIRECT OP CODE
; DB 87H ;PCON ADDRESS
; DB 01H ;SET IDLE BIT
JB INTPEN,I_RET ;EXIT IF EXTERNAL INTERRUPT
JBC U_IDL,I_RET ;EXIT IF USER WANTS TO
JNB OTS,U_ID1 ;LOOP IF TIMER NOT ENABLED
LCALL T_CMP ;CHECK THE TIMER
JC U_ID1 ;LOOP IF TIME NOT BIG ENOUGH
;
I_RET: SETB DACK ;RESTORE EXECUTION
RET ;EXIT IF IT IS
;
;
;
ER0: INC DPTR ;BUMP TO TEXT
JB DIRF,ERROR0 ;CAN'T GET OUT OF DIRECT MODE
JNB ON_ERR,ERROR0 ;IF ON ERROR ISN'T SET, GO BACK
MOV DPTR,#ERRLOC ;SAVE THE ERROR CODE
CALL RC2 ;SAVE ERROR AND SET UP THE STACKS
INC DPTR ;POINT AT ERRNUM
JMP ERL4 ;LOAD ERR NUM AND EXIT
;
$EJECT
;
; Syntax error
;
E1XX: MOV C,DIRF ;SEE IF IN DIRECT MODE
E1XX1: MOV DPTR,#E1X ;ERROR MESSAGE
SJMP ERROR1 ;TRAP ON SET DIRF
;
E1XX2: MOV DPTR,#EXI ;STACK ERROR
;
; Falls through
;
;***************************************************************
;
;ERROR PROCESSOR - PRINT OUT THE ERROR TYPE, CHECK TO SEE IF IN
; RUN OR COMMAND MODE, FIND AND PRINT OUT THE
; LINE NUMBER IF IN RUN MODE
;
;***************************************************************
;
ERROR: CLR C ;RESET STACK
ERROR1: MOV SP,SPSAV ;RESET THE STACK
LCALL SPRINT1 ;CLEAR LINE AND AT MODE
CLR A ;SET UP TO GET ERROR CODE
MOVC A,@A+DPTR
JBC ACC.7,ER0 ;PROCESS ERROR
;
ERROR0: ACALL TEMPD ;SAVE THE DATA POINTER
JC ERROR01 ;NO RESET IF CARRY IS SET
LCALL RC1 ;RESET THE STACKS
ERROR01:CALL CRLF2 ;DO TWO CARRIAGE RET - LINE FEED
MOV DPTR,#ERS ;OUTPUT ERROR MESSAGE
CALL ROM_P
CALL DTEMP ;GET THE ERROR MESSAGE BACK
;
ERRS: CALL ROM_P ;PRINT ERROR TYPE
JNB DIRF,ER1 ;DO NOT PRINT IN LINE IF DIRF=1
;
SERR1: CLR STOPBIT ;PRINT STOP THEN EXIT, FOR LIST
JMP CMND1
;
ER1: MOV DPTR,#INS ;OUTPUT IN LINE
CALL ROM_P
;
;NOW, FIND THE LINE NUMBER
;
;
$EJECT
;
;
CALL DP_B ;GET THE FIRST ADDRESS OF THE PROGRAM
CLR A ;FOR INITIALIZATION
;
ER2: ACALL TEMPD ;SAVE THE DPTR
CALL ADDPTR ;ADD ACC TO DPTR
ACALL ER4 ;R3:R1 = TXA-DPTR
JC ER3 ;EXIT IF DPTR>TXA
JZ ER3 ;EXIT IF DPTR=TXA
MOVX A,@DPTR ;GET LENGTH
CJNE A,#EOF,ER2 ;SEE IF AT THE END
;
ER3: ACALL DTEMP ;PUT THE LINE IN THE DPTR
ACALL ER4 ;R3:R1 = TXA - BEGINNING OF LINE
MOV A,R1 ;GET LENGTH
ADD A,#10 ;ADD 10 TO LENGTH, DPTR STILL HAS ADR
MOV MT1,A ;SAVE THE COUNT
INC DPTR ;POINT AT LINE NUMBER HIGH BYTE
CALL PMTOP1 ;LOAD R2:R0, PUT IT ON THE STACK
ACALL FP_BASE7 ;OUTPUT IT
JB STOPBIT,SERR1 ;EXIT IF STOP BIT SET
CALL CRLF2 ;DO SOME CRLF'S
CALL DTEMP
CALL UPPL ;UNPROCESS THE LINE
CALL CL6 ;PRINT IT
ER31: MOV R5,#'-' ;OUTPUT DASHES, THEN AN X
ACALL T_L ;PRINT AN X IF ERROR CHARACTER FOUND
DJNZ MT1,ER31 ;LOOP UNTIL DONE
MOV R5,#'X'
ACALL T_L
AJMP SERR1
;
ER4: MOV R3,TXAH ;GET TEXT POINTER AND PERFORM SUBTRACTION
MOV R1,TXAL
JMP DUBSUB
;
$EJECT
;**************************************************************
;
; Interrupt driven timer
;
;**************************************************************
;
I_DR: MOV TH0,SAVE_T ;LOAD THE TIMER
XCH A,MILLIV ;SAVE A, GET MILLI COUNTER
INC A ;BUMP COUNTER
CJNE A,#200,TR ;CHECK OUT TIMER VALUE
CLR A ;FORCE ACC TO BE ZERO
INC TVL ;INCREMENT LOW TIMER
CJNE A,TVL,TR ;CHECK LOW VALUE
INC TVH ;BUMP TIMER HIGH
;
TR: XCH A,MILLIV
POP PSW
RETI
;
$EJECT
;$INCLUDE(:F2:BAS52.CLK)
;BEGINNING
;**************************************************************
;
; The statement action routine - CLOCK
;
;**************************************************************
;
SCLOCK: ACALL OTST ;GET CHARACTER AFTER CLOCK TOKEN
CLR ET0
CLR C_BIT
JNC SC_R ;EXIT IF A ZERO
ANL TMOD,#0F0H ;SET UP THE MODE
SETB C_BIT ;USER INTERRUPTS
ORL IE,#82H ;ENABLE ET0 AND EA
SETB TR0 ;TURN ON THE TIMER
;
SC_R: RET
;
;END
;$INCLUDE(:F2:BAS52.CLK)
;***************************************************************
;
SUI: ; Statement USER IN action routine
;
;***************************************************************
;
ACALL OTST
MOV CIUB,C ;SET OR CLEAR CIUB
RET
;
;***************************************************************
;
SUO: ; Statement USER OUT action routine
;
;***************************************************************
;
ACALL OTST
MOV COUB,C
RET
;
OTST: ; Check for a one
;
LCALL GCI ;GET THE CHARACTER, CLEARS CARRY
SUBB A,#'1' ;SEE IF A ONE
CPL C ;SETS CARRY IF ONE, CLEARS IT IF ZERO
OTST1: RET
;
$EJECT
;**************************************************************
;
; IBLK - EXECUTE USER SUPPLIED TOKEN
;
;**************************************************************
;
IBLK: JB PSW.4,OTST1 ;EXIT IF REGISTER BANK <> 0
JB PSW.3,OTST1
JBC ACC.7,IBLK1 ;SEE IF BIT SEVEN IS SET
MOV DPTR,#USENT ;USER ENTRY LOCATION
LJMP ISTA1
;
IBLK1: JB ACC.0,FP_BASE6 ;FLOATING POINT INPUT
JZ T_L ;DO OUTPUT ON 80H
MOV DPTR,#FP_BASE-2
JMP @A+DPTR
;
;
;**************************************************************
;
; GET_NUM - GET A NUMBER, EITHER HEX OR FLOAT
;
;**************************************************************
;
GET_NUM:ACALL FP_BASE5 ;SCAN FOR HEX
JNC FP_BASE6 ;DO FP INPUT
;
ACALL FP_BASE9 ;ASCII STRING TO R2:R0
JNZ H_RET
PUSH DPH ;SAVE THE DATA_POINTER
PUSH DPL
ACALL FP_BASE12 ;PUT R2:R0 ON THE STACK
POP DPL ;RESTORE THE DATA_POINTER
POP DPH
CLR A ;NO ERRORS
RET ;EXIT
;
$EJECT
; START OF BAUD RATE MODIFICATIONS BY DANIEL WALLNER
TIB1:MOV ACC,TL2
JB ACC.3,TIB1
CALL DEC3211
TIB2: MOV ACC,TL2
JNB ACC.3,TIB2
JNB RXD,TIB1 ;16x12 CLOCKS, LOOP UNTIL DONE
JB RXD,$ ;WAIT FOR STOP CHARACTER TO END
RET
;**************************************************************
;
; WB - THE EGO MESSAGE
;
;**************************************************************
;
WB:
; DB 'W'+80H,'R'+80H
; DB 'I'+80H,'T'+80H,'T','E'+80H,'N'+80H
; DB ' ','B'+80H,'Y'+80H,' '
; DB 'J'+80H,'O'+80H,'H'+80H,'N'+80H,' '+80H
; DB 'K','A'+80H,'T'+80H,'A'+80H,'U'+80H
; DB 'S','K'+80H,'Y'+80H
; END OF BAUD RATE MODIFICATIONS BY DANIEL WALLNER
DB ', I','N'+80H,'T'+80H,'E'+80H,'L'+80H
DB ' '+80H,'C'+80H,'O'+80H,'R'+80H,'P'+80H
DB '. 1','9'+80H,'85'
H_RET: RET
;
$EJECT
ORG 1990H
;
OUTPUT:
T_L: LJMP TEROT
;
ORG 1F78H
;
CKS_I: JB CKS_B,CS_I
LJMP 401BH
;
CS_I: LJMP 2088H
;
E14X: DB 'NO DATA"'
;
E11X: DB 128+20
DB 'ARITH. OVERFLOW"'
;
E16X: DB 'PROGRAMMING"'
;
E15X: DB 'CAN'
DB 27H
DB 'T CONTINUE"'
;
E10X: DB 'INVALID LINE NUMBER"'
;
NOROM: DB 'PROM MODE"'
;
S_N: DB '*MCS-51(tm) BASIC V1.1*"'
;
ORG 1FF8H
;
ERS: DB 'ERROR: "'
;
$EJECT
;************************************************************
;
; This is a complete BCD floating point package for the 8051 micro-
; controller. It provides 8 digits of accuracy with exponents that
; range from +127 to -127. The mantissa is in packed BCD, while the
; exponent is expressed in pseudo-twos complement. A ZERO exponent
; is used to express the number ZERO. An exponent value of 80H or
; greater than means the exponent is positive, i.e. 80H = E 0,
; 81H = E+1, 82H = E+2 and so on. If the exponent is 7FH or less,
; the exponent is negative, 7FH = E-1, 7EH = E-2, and so on.
; ALL NUMBERS ARE ASSUMED TO BE NORMALIZED and all results are
; normalized after calculation. A normalized mantissa is >=.10 and
; <=.99999999.
;
; The numbers in memory assumed to be stored as follows:
;
; EXPONENT OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE
; SIGN OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-1
; DIGIT 78 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-2
; DIGIT 56 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-3
; DIGIT 34 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-4
; DIGIT 12 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-5
;
; EXPONENT OF ARGUMENT 1 = VALUE OF ARG_STACK
; SIGN OF ARGUMENT 1 = VALUE OF ARG_STACK-1
; DIGIT 78 OF ARGUMENT 1 = VALUE OF ARG_STACK-2
; DIGIT 56 OF ARGUMENT 1 = VALUE OF ARG_STACK-3
; DIGIT 34 OF ARGUMENT 1 = VALUE OF ARG_STACK-4
; DIGIT 12 OF ARGUMENT 1 = VALUE OF ARG_STACK-5
;
; The operations are performed thusly:
;
; ARG_STACK+FP_NUMBER_SIZE = ARG_STACK+FP_NUMBER_SIZE # ARG_STACK
;
; Which is ARGUMENT 2 = ARGUMENT 2 # ARGUMENT 1
;
; Where # can be ADD, SUBTRACT, MULTIPLY OR DIVIDE.
;
; Note that the stack gets popped after an operation.
;
; The FP_COMP instruction POPS the ARG_STACK TWICE and returns status.
;
;**********************************************************************
;
$EJECT
;**********************************************************************
;
; STATUS ON RETURN - After performing an operation (+, -, *, /)
; the accumulator contains the following status
;
; ACCUMULATOR - BIT 0 - FLOATING POINT UNDERFLOW OCCURED
;
; - BIT 1 - FLOATING POINT OVERFLOW OCCURED
;
; - BIT 2 - RESULT WAS ZER0
;
; - BIT 3 - DIVIDE BY ZERO ATTEMPTED
;
; - BIT 4 - NOT USED, 0 RETURNED
;
; - BIT 5 - NOT USED, 0 RETURNED
;
; - BIT 6 - NOT USED, 0 RETURNED
;
; - BIT 7 - NOT USED, 0 RETURNED
;
; NOTE: When underflow occures, a ZERO result is returned.
; When overflow or divide by zero occures, a result of
; .99999999 E+127 is returned and it is up to the user
; to handle these conditions as needed in the program.
;
; NOTE: The Compare instruction returns F0 = 0 if ARG 1 = ARG 2
; and returns a CARRY FLAG = 1 if ARG 1 is > ARG 2
;
;***********************************************************************
;
$EJECT
;***********************************************************************
;
; The following values MUST be provided by the user
;
;***********************************************************************
;
ARG_STACK EQU 9 ;ARGUMENT STACK POINTER
ARG_STACK_PAGE EQU 1
;OUTPUT EQU 1990H ;CALL LOCATION TO OUTPUT A CHARACTER
CONVERT EQU 58H ;LOCATION TO CONVERT NUMBERS
INTGRC BIT 25 ;BIT SET IF INTGER ERROR
;
;***********************************************************************
;
; The following equates are used internally
;
;***********************************************************************
;
FP_NUMBER_SIZE EQU 6
UNDERFLOW EQU 0
OVERFLOW EQU 1
ZERO EQU 2
ZERO_DIVIDE EQU 3
;
;***********************************************************************
$EJECT
;**************************************************************
;
; The following internal locations are used by the math pack
; ordering is important and the FP_DIGITS must be bit
; addressable
;
;***************************************************************
;
FP_STATUS EQU 28H ;NOT USED
FP_TEMP EQU FP_STATUS+1 ;NOT USED
FP_CARRY EQU FP_STATUS+2 ;USED FOR BITS
ADD_IN BIT 35 ;DCMPXZ IN BASIC BACKAGE
XSIGN BIT FP_CARRY.0
FOUND_RADIX BIT FP_CARRY.1
FIRST_RADIX BIT FP_CARRY.2
DONE_LOAD BIT FP_CARRY.3
FP_DIG12 EQU FP_CARRY+1
FP_DIG34 EQU FP_CARRY+2
FP_DIG56 EQU FP_CARRY+3
FP_DIG78 EQU FP_CARRY+4
FP_SIGN EQU FP_CARRY+5
MSIGN BIT FP_SIGN.0
FP_EXP EQU FP_CARRY+6
FP_NIB1 EQU FP_DIG12
FP_NIB2 EQU FP_NIB1+1
FP_NIB3 EQU FP_NIB1+2
FP_NIB4 EQU FP_NIB1+3
FP_NIB5 EQU FP_NIB1+4
FP_NIB6 EQU FP_NIB1+5
FP_NIB7 EQU FP_NIB1+6
FP_NIB8 EQU FP_NIB1+7
FP_ACCX EQU FP_NIB1+8
FP_ACCC EQU FP_NIB1+9
FP_ACC1 EQU FP_NIB1+10
FP_ACC2 EQU FP_NIB1+11
FP_ACC3 EQU FP_NIB1+12
FP_ACC4 EQU FP_NIB1+13
FP_ACC5 EQU FP_NIB1+14
FP_ACC6 EQU FP_NIB1+15
FP_ACC7 EQU FP_NIB1+16
FP_ACC8 EQU FP_NIB1+17
FP_ACCS EQU FP_NIB1+18
;
$EJECT
ORG 1993H
;
;**************************************************************
;
; The floating point entry points and jump table
;
;**************************************************************
;
FP_BASE: AJMP FLOATING_ADD
FP_BASE1: AJMP FLOATING_SUB
FP_BASE2: AJMP FLOATING_COMP
FP_BASE3: AJMP FLOATING_MUL
FP_BASE4: AJMP FLOATING_DIV
FP_BASE5: AJMP HEXSCAN
FP_BASE6: AJMP FLOATING_POINT_INPUT
FP_BASE7: AJMP FLOATING_POINT_OUTPUT
FP_BASE8: AJMP CONVERT_BINARY_TO_ASCII_STRING
FP_BASE9: AJMP CONVERT_ASCII_STRING_TO_BINARY
FP_BASE10: AJMP MULNUM10
FP_BASE11: AJMP HEXOUT
FP_BASE12: AJMP PUSHR2R0
;
$EJECT
;
FLOATING_SUB:
;
MOV P2,#ARG_STACK_PAGE
MOV R0,ARG_STACK
DEC R0 ;POINT TO SIGN
MOVX A,@R0 ;READ SIGN
CPL ACC.0
MOVX @R0,A
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;
FLOATING_ADD:
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;
;
ACALL MDES1 ;R7=TOS EXP, R6=TOS-1 EXP, R4=TOS SIGN
;R3=TOS-1 SIGN, OPERATION IS R1 # R0
;
MOV A,R7 ;GET TOS EXPONENT
JZ POP_AND_EXIT ;IF TOS=0 THEN POP AND EXIT
CJNE R6,#0,LOAD1 ;CLEAR CARRY EXIT IF ZERO
;
;**************************************************************
;
SWAP_AND_EXIT: ; Swap external args and return
;
;**************************************************************
;
ACALL LOAD_POINTERS
MOV R7,#FP_NUMBER_SIZE
;
SE1: MOVX A,@R0 ;SWAP THE ARGUMENTS
MOVX @R1,A
DEC R0
DEC R1
DJNZ R7,SE1
;
POP_AND_EXIT:
;
MOV A,ARG_STACK ;POP THE STACK
ADD A,#FP_NUMBER_SIZE
MOV ARG_STACK,A
CLR A
RET
;
;
LOAD1: SUBB A,R6 ;A = ARG 1 EXP - ARG 2 EXP
MOV FP_EXP,R7 ;SAVE EXPONENT AND SIGN
MOV FP_SIGN,R4
JNC LOAD2 ;ARG1 EXPONENT IS LARGER OR SAME
MOV FP_EXP,R6
MOV FP_SIGN,R3
CPL A
INC A ;COMPENSATE FOR EXP DELTA
XCH A,R0 ;FORCE R0 TO POINT AT THE LARGEST
XCH A,R1 ;EXPONENT
XCH A,R0
;
LOAD2: MOV R7,A ;SAVE THE EXPONENT DELTA IN R7
CLR ADD_IN
CJNE R5,#0,LOAD21
SETB ADD_IN
;
$EJECT
; Load the R1 mantissa
;
LOAD21: ACALL LOADR1_MANTISSA ;LOAD THE SMALLEST NUMBER
;
; Now align the number to the delta exponent
; R4 points to the string of the last digits lost
;
CJNE R7,#DIGIT+DIGIT+3,LOAD22
LOAD22: JC LOAD23
MOV R7,#DIGIT+DIGIT+2
;
LOAD23: MOV FP_CARRY,#00 ;CLEAR THE CARRY
ACALL RIGHT ;SHIFT THE NUMBER
;
; Set up for addition and subtraction
;
MOV R7,#DIGIT ;LOOP COUNT
MOV R1,#FP_DIG78
MOV A,#9EH
CLR C
SUBB A,R4
DA A
XCH A,R4
JNZ LOAD24
MOV R4,A
LOAD24: CJNE A,#50H,LOAD25 ;TEST FOR SUBTRACTION
LOAD25: JNB ADD_IN,SUBLP ;DO SUBTRACTION IF NO ADD_IN
CPL C ;FLIP CARRY FOR ADDITION
ACALL ADDLP ;DO ADDITION
;
JNC ADD_R
INC FP_CARRY
MOV R7,#1
ACALL RIGHT
ACALL INC_FP_EXP ;SHIFT AND BUMP EXPONENT
;
ADD_R: AJMP STORE_ALIGN_TEST_AND_EXIT
;
ADDLP: MOVX A,@R0
ADDC A,@R1
DA A
MOV @R1,A
DEC R0
DEC R1
DJNZ R7,ADDLP ;LOOP UNTIL DONE
RET
;
$EJECT
;
SUBLP: MOVX A,@R0 ;NOW DO SUBTRACTION
MOV R6,A
CLR A
ADDC A,#99H
SUBB A,@R1
ADD A,R6
DA A
MOV @R1,A
DEC R0
DEC R1
DJNZ R7,SUBLP
JC FSUB6
;
$EJECT
;
; Need to complement the result and sign because the floating
; point accumulator mantissa was larger than the external
; memory and their signs were equal.
;
CPL FP_SIGN.0
MOV R1,#FP_DIG78
MOV R7,#DIGIT ;LOOP COUNT
;
FSUB5: MOV A,#9AH
SUBB A,@R1
ADD A,#0
DA A
MOV @R1,A
DEC R1
CPL C
DJNZ R7,FSUB5 ;LOOP
;
; Now see how many zeros their are
;
FSUB6: MOV R0,#FP_DIG12
MOV R7,#0
;
FSUB7: MOV A,@R0
JNZ FSUB8
INC R7
INC R7
INC R0
CJNE R0,#FP_SIGN,FSUB7
AJMP ZERO_AND_EXIT
;
FSUB8: CJNE A,#10H,FSUB81
FSUB81: JNC FSUB9
INC R7
;
; Now R7 has the number of leading zeros in the FP ACC
;
FSUB9: MOV A,FP_EXP ;GET THE OLD EXPONENT
CLR C
SUBB A,R7 ;SUBTRACT FROM THE NUMBER OF ZEROS
JZ FSUB10
JC FSUB10
;
MOV FP_EXP,A ;SAVE THE NEW EXPONENT
;
ACALL LEFT1 ;SHIFT THE FP ACC
MOV FP_CARRY,#0
AJMP STORE_ALIGN_TEST_AND_EXIT
;
FSUB10: AJMP UNDERFLOW_AND_EXIT
;
$EJECT
;***************************************************************
;
FLOATING_COMP: ; Compare two floating point numbers
; used for relational operations and is faster
; than subtraction. ON RETURN, The carry is set
; if ARG1 is > ARG2, else carry is not set
; if ARG1 = ARG2, F0 gets set
;
;***************************************************************
;
ACALL MDES1 ;SET UP THE REGISTERS
MOV A,ARG_STACK
ADD A,#FP_NUMBER_SIZE+FP_NUMBER_SIZE
MOV ARG_STACK,A ;POP THE STACK TWICE, CLEAR THE CARRY
MOV A,R6 ;CHECK OUT EXPONENTS
CLR F0
SUBB A,R7
JZ EXPONENTS_EQUAL
JC ARG1_EXP_IS_LARGER
;
; Now the ARG2 EXPONENT is > ARG1 EXPONENT
;
SIGNS_DIFFERENT:
;
MOV A,R3 ;SEE IF SIGN OF ARG2 IS POSITIVE
SJMP ARG1_EXP_IS_LARGER1
;
ARG1_EXP_IS_LARGER:
;
MOV A,R4 ;GET THE SIGN OF ARG1 EXPONENT
ARG1_EXP_IS_LARGER1:
JZ ARG1_EXP_IS_LARGER2
CPL C
ARG1_EXP_IS_LARGER2:
RET
;
EXPONENTS_EQUAL:
;
; First, test the sign, then the mantissa
;
CJNE R5,#0,SIGNS_DIFFERENT
;
BOTH_PLUS:
;
MOV R7,#DIGIT ;POINT AT MS DIGIT
DEC R0
DEC R0
DEC R0
DEC R1
DEC R1
DEC R1
;
; Now do the compare
;
CLOOP: MOVX A,@R0
MOV R6,A
MOVX A,@R1
SUBB A,R6
JNZ ARG1_EXP_IS_LARGER
INC R0
INC R1
DJNZ R7,CLOOP
;
; If here, the numbers are the same, the carry is cleared
;
SETB F0
RET ;EXIT WITH EQUAL
;
$EJECT
;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
;
FLOATING_MUL: ; Floating point multiply
;
;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
;
ACALL MUL_DIV_EXP_AND_SIGN
;
; check for zero exponents
;
CJNE R6,#00,FMUL1 ;ARG 2 EXP ZERO?
FMUL0: AJMP ZERO_AND_EXIT
;
; calculate the exponent
;
FMUL1: MOV FP_SIGN,R5 ;SAVE THE SIGN, IN CASE OF FAILURE
;
MOV A,R7
JZ FMUL0
ADD A,R6 ;ADD THE EXPONENTS
JB ACC.7,FMUL_OVER
JBC CY,FMUL2 ;SEE IF CARRY IS SET
;
AJMP UNDERFLOW_AND_EXIT
;
FMUL_OVER:
;
JNC FMUL2 ;OK IF SET
;
FOV: AJMP OVERFLOW_AND_EXIT
;
FMUL2: SUBB A,#129 ;SUBTRACT THE EXPONENT BIAS
MOV R6,A ;SAVE IT FOR LATER
;
; Unpack and load R0
;
ACALL UNPACK_R0
;
; Now set up for loop multiply
;
MOV R3,#DIGIT
MOV R4,R1B0
;
$EJECT
;
; Now, do the multiply and accumulate the product
;
FMUL3: MOV R1B0,R4
MOVX A,@R1
MOV R2,A
ACALL MUL_NIBBLE
;
MOV A,R2
SWAP A
ACALL MUL_NIBBLE
DEC R4
DJNZ R3,FMUL3
;
; Now, pack and restore the sign
;
MOV FP_EXP,R6
MOV FP_SIGN,R5
AJMP PACK ;FINISH IT OFF
;
$EJECT
;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
;
FLOATING_DIV:
;
;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
;
ACALL MDES1
;
; Check the exponents
;
MOV FP_SIGN,R5 ;SAVE THE SIGN
CJNE R7,#0,DIV0 ;CLEARS THE CARRY
ACALL OVERFLOW_AND_EXIT
CLR A
SETB ACC.ZERO_DIVIDE
RET
;
DIV0: MOV A,R6 ;GET EXPONENT
JZ FMUL0 ;EXIT IF ZERO
SUBB A,R7 ;DELTA EXPONENT
JB ACC.7,D_UNDER
JNC DIV3
AJMP UNDERFLOW_AND_EXIT
;
D_UNDER:JNC FOV
;
DIV3: ADD A,#129 ;CORRECTLY BIAS THE EXPONENT
MOV FP_EXP,A ;SAVE THE EXPONENT
ACALL LOADR1_MANTISSA ;LOAD THE DIVIDED
;
MOV R2,#FP_ACCC ;SAVE LOCATION
MOV R3,R0B0 ;SAVE POINTER IN R3
MOV FP_CARRY,#0 ;ZERO CARRY BYTE
;
DIV4: MOV R5,#0FFH ;LOOP COUNT
SETB C
;
DIV5: MOV R0B0,R3 ;RESTORE THE EXTERNAL POINTER
MOV R1,#FP_DIG78 ;SET UP INTERNAL POINTER
MOV R7,#DIGIT ;LOOP COUNT
JNC DIV7 ;EXIT IF NO CARRY
;
DIV6: MOVX A,@R0 ;DO ACCUMLATION
MOV R6,A
CLR A
ADDC A,#99H
SUBB A,R6
ADD A,@R1
DA A
MOV @R1,A
DEC R0
DEC R1
DJNZ R7,DIV6 ;LOOP
;
INC R5 ;SUBTRACT COUNTER
JC DIV5 ;KEEP LOOPING IF CARRY
MOV A,@R1 ;GET CARRY
SUBB A,#1 ;CARRY IS CLEARED
MOV @R1,A ;SAVE CARRY DIGIT
CPL C
SJMP DIV5 ;LOOP
;
; Restore the result if carry was found
;
DIV7: ACALL ADDLP ;ADD NUMBER BACK
MOV @R1,#0 ;CLEAR CARRY
MOV R0B0,R2 ;GET SAVE COUNTER
MOV @R0,5 ;SAVE COUNT BYTE
;
INC R2 ;ADJUST SAVE COUNTER
MOV R7,#1 ;BUMP DIVIDEND
ACALL LEFT
CJNE R2,#FP_ACC8+2,DIV4
;
DJNZ FP_EXP,DIV8
AJMP UNDERFLOW_AND_EXIT
;
DIV8: MOV FP_CARRY,#0
;
$EJECT
;***************************************************************
;
PACK: ; Pack the mantissa
;
;***************************************************************
;
; First, set up the pointers
;
MOV R0,#FP_ACCC
MOV A,@R0 ;GET FP_ACCC
MOV R6,A ;SAVE FOR ZERO COUNT
JZ PACK0 ;JUMP OVER IF ZERO
ACALL INC_FP_EXP ;BUMP THE EXPONENT
DEC R0
;
PACK0: INC R0 ;POINT AT FP_ACC1
;
PACK1: MOV A,#8 ;ADJUST NIBBLE POINTER
MOV R1,A
ADD A,R0
MOV R0,A
CJNE @R0,#5,PACK11 ;SEE IF ADJUSTING NEEDED
PACK11: JC PACK31
;
PACK2: SETB C
CLR A
DEC R0
ADDC A,@R0
DA A
XCHD A,@R0 ;SAVE THE VALUE
JNB ACC.4,PACK3
DJNZ R1,PACK2
;
DEC R0
MOV @R0,#1
ACALL INC_FP_EXP
SJMP PACK4
;
PACK3: DEC R1
PACK31: MOV A,R1
CLR C
XCH A,R0
SUBB A,R0
MOV R0,A
;
PACK4: MOV R1,#FP_DIG12
;
; Now, pack
;
PLOOP: MOV A,@R0
SWAP A ;FLIP THE DIGITS
INC R0
XCHD A,@R0
ORL 6,A ;ACCUMULATE THE OR'ED DIGITS
MOV @R1,A
INC R0
INC R1
CJNE R1,#FP_SIGN,PLOOP
MOV A,R6
JNZ STORE_ALIGN_TEST_AND_EXIT
MOV FP_EXP,#0 ;ZERO EXPONENT
;
;**************************************************************
;
STORE_ALIGN_TEST_AND_EXIT: ;Save the number align carry and exit
;
;**************************************************************
;
ACALL LOAD_POINTERS
MOV ARG_STACK,R1 ;SET UP THE NEW STACK
MOV R0,#FP_EXP
;
; Now load the numbers
;
STORE2: MOV A,@R0
MOVX @R1,A ;SAVE THE NUMBER
DEC R0
DEC R1
CJNE R0,#FP_CARRY,STORE2
;
CLR A ;NO ERRORS
;
PRET: RET ;EXIT
;
$EJECT
INC_FP_EXP:
;
INC FP_EXP
MOV A,FP_EXP
JNZ PRET ;EXIT IF NOT ZERO
POP ACC ;WASTE THE CALLING STACK
POP ACC
AJMP OVERFLOW_AND_EXIT
;
;***********************************************************************
;
UNPACK_R0: ; Unpack BCD digits and load into nibble locations
;
;***********************************************************************
;
PUSH R1B0
MOV R1,#FP_NIB8
;
ULOOP: MOVX A,@R0
ANL A,#0FH
MOV @R1,A ;SAVE THE NIBBLE
MOVX A,@R0
SWAP A
ANL A,#0FH
DEC R1
MOV @R1,A ;SAVE THE NIBBLE AGAIN
DEC R0
DEC R1
CJNE R1,#FP_NIB1-1,ULOOP
;
POP R1B0
;
LOAD7: RET
;
$EJECT
;**************************************************************
;
OVERFLOW_AND_EXIT: ;LOAD 99999999 E+127, SET OV BIT, AND EXIT
;
;**************************************************************
;
MOV R0,#FP_DIG78
MOV A,#99H
;
OVE1: MOV @R0,A
DEC R0
CJNE R0,#FP_CARRY,OVE1
;
MOV FP_EXP,#0FFH
ACALL STORE_ALIGN_TEST_AND_EXIT
;
SETB ACC.OVERFLOW
RET
;
$EJECT
;**************************************************************
;
UNDERFLOW_AND_EXIT: ;LOAD 0, SET UF BIT, AND EXIT
;
;**************************************************************
;
ACALL ZERO_AND_EXIT
CLR A
SETB ACC.UNDERFLOW
RET
;
;**************************************************************
;
ZERO_AND_EXIT: ;LOAD 0, SET ZERO BIT, AND EXIT
;
;**************************************************************
;
ACALL FP_CLEAR
ACALL STORE_ALIGN_TEST_AND_EXIT
SETB ACC.ZERO
RET ;EXIT
;
;**************************************************************
;
FP_CLEAR:
;
; Clear internal storage
;
;**************************************************************
;
CLR A
MOV R0,#FP_ACC8+1
;
FPC1: MOV @R0,A
DEC R0
CJNE R0,#FP_TEMP,FPC1
RET
;
$EJECT
;**************************************************************
;
RIGHT: ; Shift ACCUMULATOR RIGHT the number of nibbles in R7
; Save the shifted values in R4 if SAVE_ROUND is set
;
;**************************************************************
;
MOV R4,#0 ;IN CASE OF NO SHIFT
;
RIGHT1: CLR C
RIGHT2: MOV A,R7 ;GET THE DIGITS TO SHIFT
JZ RIGHTL1 ;EXIT IF ZERO
SUBB A,#2 ;TWO TO DO?
JNC RIGHT5 ;SHIFT TWO NIBBLES
;
; Swap one nibble then exit
;
RIGHT3: PUSH R0B0 ;SAVE POINTER REGISTER
PUSH R1B0
;
MOV R1,#FP_DIG78 ;LOAD THE POINTERS
MOV R0,#FP_DIG56
MOV A,R4 ;GET THE OVERFLOW REGISTER
XCHD A,@R1 ;GET DIGIT 8
SWAP A ;FLIP FOR LOAD
MOV R4,A
;
RIGHTL: MOV A,@R1 ;GET THE LOW ORDER BYTE
XCHD A,@R0 ;SWAP NIBBLES
SWAP A ;FLIP FOR STORE
MOV @R1,A ;SAVE THE DIGITS
DEC R0 ;BUMP THE POINTERS
DEC R1
CJNE R1,#FP_DIG12-1,RIGHTL ;LOOP
;
MOV A,@R1 ;ACC = CH8
SWAP A ;ACC = 8CH
ANL A,#0FH ;ACC = 0CH
MOV @R1,A ;CARRY DONE
POP R1B0 ;EXIT
POP R0B0 ;RESTORE REGISTER
RIGHTL1:RET
;
RIGHT5: MOV R7,A ;SAVE THE NEW SHIFT NUMBER
CLR A
XCH A,FP_CARRY ;SWAP THE NIBBLES
XCH A,FP_DIG12
XCH A,FP_DIG34
XCH A,FP_DIG56
XCH A,FP_DIG78
MOV R4,A ;SAVE THE LAST DIGIT SHIFTED
SJMP RIGHT2
;
$EJECT
;***************************************************************
;
LEFT: ; Shift ACCUMULATOR LEFT the number of nibbles in R7
;
;***************************************************************
;
MOV R4,#00H ;CLEAR FOR SOME ENTRYS
;
LEFT1: CLR C
LEFT2: MOV A,R7 ;GET SHIFT VALUE
JZ LEFTL1 ;EXIT IF ZERO
SUBB A,#2 ;SEE HOW MANY BYTES TO SHIFT
JNC LEFT5
;
LEFT3: PUSH R0B0 ;SAVE POINTER
PUSH R1B0
MOV R0,#FP_CARRY
MOV R1,#FP_DIG12
;
MOV A,@R0 ;ACC=CHCL
SWAP A ;ACC = CLCH
MOV @R0,A ;ACC = CLCH, @R0 = CLCH
;
LEFTL: MOV A,@R1 ;DIG 12
SWAP A ;DIG 21
XCHD A,@R0
MOV @R1,A ;SAVE IT
INC R0 ;BUMP POINTERS
INC R1
CJNE R0,#FP_DIG78,LEFTL
;
MOV A,R4
SWAP A
XCHD A,@R0
ANL A,#0F0H
MOV R4,A
;
POP R1B0
POP R0B0 ;RESTORE
LEFTL1: RET ;DONE
;
LEFT5: MOV R7,A ;RESTORE COUNT
CLR A
XCH A,R4 ;GET THE RESTORATION BYTE
XCH A,FP_DIG78 ;DO THE SWAP
XCH A,FP_DIG56
XCH A,FP_DIG34
XCH A,FP_DIG12
XCH A,FP_CARRY
SJMP LEFT2
;
$EJECT
MUL_NIBBLE:
;
; Multiply the nibble in R7 by the FP_NIB locations
; accumulate the product in FP_ACC
;
; Set up the pointers for multiplication
;
ANL A,#0FH ;STRIP OFF MS NIBBLE
MOV R7,A
MOV R0,#FP_ACC8
MOV R1,#FP_NIB8
CLR A
MOV FP_ACCX,A
;
MNLOOP: DEC R0 ;BUMP POINTER TO PROPAGATE CARRY
ADD A,@R0 ;ATTEMPT TO FORCE CARRY
DA A ;BCD ADJUST
JNB ACC.4,MNL0 ;DON'T ADJUST IF NO NEED
DEC R0 ;PROPAGATE CARRY TO THE NEXT DIGIT
INC @R0 ;DO THE ADJUSTING
INC R0 ;RESTORE R0
;
MNL0: XCHD A,@R0 ;RESTORE INITIAL NUMBER
MOV B,R7 ;GET THE NUBBLE TO MULTIPLY
MOV A,@R1 ;GET THE OTHER NIBBLE
MUL AB ;DO THE MULTIPLY
MOV B,#10 ;NOW BCD ADJUST
DIV AB
XCH A,B ;GET THE REMAINDER
ADD A,@R0 ;PROPAGATE THE PARTIAL PRODUCTS
DA A ;BCD ADJUST
JNB ACC.4,MNL1 ;PROPAGATE PARTIAL PRODUCT CARRY
INC B
;
MNL1: INC R0
XCHD A,@R0 ;SAVE THE NEW PRODUCT
DEC R0
MOV A,B ;GET BACK THE QUOTIENT
DEC R1
CJNE R1,#FP_NIB1-1,MNLOOP
;
ADD A,FP_ACCX ;GET THE OVERFLOW
DA A ;ADJUST
MOV @R0,A ;SAVE IT
RET ;EXIT
;
$EJECT
;***************************************************************
;
LOAD_POINTERS: ; Load the ARG_STACK into R0 and bump R1
;
;***************************************************************
;
MOV P2,#ARG_STACK_PAGE
MOV R0,ARG_STACK
MOV A,#FP_NUMBER_SIZE
ADD A,R0
MOV R1,A
RET
;
;***************************************************************
;
MUL_DIV_EXP_AND_SIGN:
;
; Load the sign into R7, R6. R5 gets the sign for
; multiply and divide.
;
;***************************************************************
;
ACALL FP_CLEAR ;CLEAR INTERNAL MEMORY
;
MDES1: ACALL LOAD_POINTERS ;LOAD REGISTERS
MOVX A,@R0 ;ARG 1 EXP
MOV R7,A ;SAVED IN R7
MOVX A,@R1 ;ARG 2 EXP
MOV R6,A ;SAVED IN R6
DEC R0 ;BUMP POINTERS TO SIGN
DEC R1
MOVX A,@R0 ;GET THE SIGN
MOV R4,A ;SIGN OF ARG1
MOVX A,@R1 ;GET SIGN OF NEXT ARG
MOV R3,A ;SIGN OF ARG2
XRL A,R4 ;ACC GETS THE NEW SIGN
MOV R5,A ;R5 GETS THE NEW SIGN
;
; Bump the pointers to point at the LS digit
;
DEC R0
DEC R1
;
RET
;
$EJECT
;***************************************************************
;
LOADR1_MANTISSA:
;
; Load the mantissa of R0 into FP_Digits
;
;***************************************************************
;
PUSH R0B0 ;SAVE REGISTER 1
MOV R0,#FP_DIG78 ;SET UP THE POINTER
;
LOADR1: MOVX A,@R1
MOV @R0,A
DEC R1
DEC R0
CJNE R0,#FP_CARRY,LOADR1
;
POP R0B0
RET
;
$EJECT
;***************************************************************
;
HEXSCAN: ; Scan a string to determine if it is a hex number
; set carry if hex, else carry = 0
;
;***************************************************************
;
ACALL GET_DPTR_CHARACTER
PUSH DPH
PUSH DPL ;SAVE THE POINTER
;
HEXSC1: MOVX A,@DPTR ;GET THE CHARACTER
ACALL DIGIT_CHECK ;SEE IF A DIGIT
JC HS1 ;CONTINUE IF A DIGIT
ACALL HEX_CHECK ;SEE IF HEX
JC HS1
;
CLR ACC.5 ;NO LOWER CASE
CJNE A,#'H',HEXDON
SETB C
SJMP HEXDO1 ;NUMBER IS VALID HEX, MAYBE
;
HEXDON: CLR C
;
HEXDO1: POP DPL ;RESTORE POINTER
POP DPH
RET
;
HS1: INC DPTR ;BUMP TO NEXT CHARACTER
SJMP HEXSC1 ;LOOP
;
HEX_CHECK: ;CHECK FOR A VALID ASCII HEX, SET CARRY IF FOUND
;
CLR ACC.5 ;WASTE LOWER CASE
CJNE A,#'F'+1,HEX_CHECK1 ;SEE IF F OR LESS
HEX_CHECK1:
JC HC1
RET
;
HC1: CJNE A,#'A',HC11 ;SEE IF A OR GREATER
HC11: CPL C
RET
;
$EJECT
;
PUSHR2R0:
;
MOV R3,#HIGH CONVERT;CONVERSION LOCATION
MOV R1,#LOW CONVERT
ACALL CONVERT_BINARY_TO_ASCII_STRING
MOV A,#0DH ;A CR TO TERMINATE
MOVX @R1,A ;SAVE THE CR
MOV DPTR,#CONVERT
;
; Falls thru to FLOATING INPUT
;
$EJECT
;***************************************************************
;
FLOATING_POINT_INPUT: ; Input a floating point number pointed to by
; the DPTR
;
;***************************************************************
;
ACALL FP_CLEAR ;CLEAR EVERYTHING
ACALL GET_DPTR_CHARACTER
ACALL PLUS_MINUS_TEST
MOV MSIGN,C ;SAVE THE MANTISSA SIGN
;
; Now, set up for input loop
;
MOV R0,#FP_ACCC
MOV R6,#7FH ;BASE EXPONENT
SETB F0 ;SET INITIAL FLAG
;
INLOOP: ACALL GET_DIGIT_CHECK
JNC GTEST ;IF NOT A CHARACTER, WHAT IS IT?
ANL A,#0FH ;STRIP ASCII
ACALL STDIG ;STORE THE DIGITS
;
INLPIK: INC DPTR ;BUMP POINTER FOR LOOP
SJMP INLOOP ;LOOP FOR INPUT
;
GTEST: CJNE A,#'.',GT1 ;SEE IF A RADIX
JB FOUND_RADIX,INERR
SETB FOUND_RADIX
CJNE R0,#FP_ACCC,INLPIK
SETB FIRST_RADIX ;SET IF FIRST RADIX
SJMP INLPIK ;GET ADDITIONAL DIGITS
;
GT1: JB F0,INERR ;ERROR IF NOT CLEARED
CJNE A,#'e',GT11 ;CHECK FOR LOWER CASE
SJMP GT12
GT11: CJNE A,#'E',FINISH_UP
GT12: ACALL INC_AND_GET_DPTR_CHARACTER
ACALL PLUS_MINUS_TEST
MOV XSIGN,C ;SAVE SIGN STATUS
ACALL GET_DIGIT_CHECK
JNC INERR
;
ANL A,#0FH ;STRIP ASCII BIAS OFF THE CHARACTER
MOV R5,A ;SAVE THE CHARACTER IN R5
;
GT2: INC DPTR
ACALL GET_DIGIT_CHECK
JNC FINISH1
ANL A,#0FH ;STRIP OFF BIAS
XCH A,R5 ;GET THE LAST DIGIT
MOV B,#10 ;MULTIPLY BY TEN
MUL AB
ADD A,R5 ;ADD TO ORIGINAL VALUE
MOV R5,A ;SAVE IN R5
JNC GT2 ;LOOP IF NO CARRY
MOV R5,#0FFH ;FORCE AN ERROR
;
FINISH1:MOV A,R5 ;GET THE SIGN
JNB XSIGN,POSNUM ;SEE IF EXPONENT IS POS OR NEG
CLR C
SUBB A,R6
CPL A
INC A
JC FINISH2
MOV A,#01H
RET
;
POSNUM: ADD A,R6 ;ADD TO EXPONENT
JNC FINISH2
;
POSNM1: MOV A,#02H
RET
;
FINISH2:XCH A,R6 ;SAVE THE EXPONENT
;
FINISH_UP:
;
MOV FP_EXP,R6 ;SAVE EXPONENT
CJNE R0,#FP_ACCC,FINISH_UP1
ACALL FP_CLEAR ;CLEAR THE MEMORY IF 0
FINISH_UP1:
MOV A,ARG_STACK ;GET THE ARG STACK
CLR C
SUBB A,#FP_NUMBER_SIZE+FP_NUMBER_SIZE
MOV ARG_STACK,A ;ADJUST FOR STORE
AJMP PACK
;
STDIG: CLR F0 ;CLEAR INITIAL DESIGNATOR
JNZ STDIG1 ;CONTINUE IF NOT ZERO
CJNE R0,#FP_ACCC,STDIG1
JNB FIRST_RADIX,RET_X
;
DECX: DJNZ R6,RET_X
;
INERR: MOV A,#0FFH
;
RET_X: RET
;
STDIG1: JB DONE_LOAD,FRTEST
CLR FIRST_RADIX
;
FRTEST: JB FIRST_RADIX,DECX
;
FDTEST: JB FOUND_RADIX,FDT1
INC R6
;
FDT1: JB DONE_LOAD,RET_X
CJNE R0,#FP_ACC8+1,FDT2
SETB DONE_LOAD
;
FDT2: MOV @R0,A ;SAVE THE STRIPPED ACCUMULATOR
INC R0 ;BUMP THE POINTER
RET ;EXIT
;
$EJECT
;***************************************************************
;
; I/O utilities
;
;***************************************************************
;
INC_AND_GET_DPTR_CHARACTER:
;
INC DPTR
;
GET_DPTR_CHARACTER:
;
MOVX A,@DPTR ;GET THE CHARACTER
CJNE A,#' ',PMT1 ;SEE IF A SPACE
;
; Kill spaces
;
SJMP INC_AND_GET_DPTR_CHARACTER
;
PLUS_MINUS_TEST:
;
CJNE A,#0E3H,PMT11 ;SEE IF A PLUS, PLUS TOKEN FROM BASIC
SJMP PMT3
PMT11: CJNE A,#'+',PMT12
SJMP PMT3
PMT12: CJNE A,#0E5H,PMT13 ;SEE IF MINUS, MINUS TOKEN FROM BASIC
SJMP PMT2
PMT13: CJNE A,#'-',PMT1
;
PMT2: SETB C
;
PMT3: INC DPTR
;
PMT1: RET
;
$EJECT
;***************************************************************
;
FLOATING_POINT_OUTPUT: ; Output the number, format is in location 23
;
; IF FORMAT = 00 - FREE FLOATING
; = FX - EXPONENTIAL (X IS THE NUMBER OF SIG DIGITS)
; = NX - N = NUM BEFORE RADIX, X = NUM AFTER RADIX
; N + X = 8 MAX
;
;***************************************************************
;
ACALL MDES1 ;GET THE NUMBER TO OUTPUT, R0 IS POINTER
ACALL POP_AND_EXIT ;OUTPUT POPS THE STACK
MOV A,R7
MOV R6,A ;PUT THE EXPONENT IN R6
ACALL UNPACK_R0 ;UNPACK THE NUMBER
MOV R0,#FP_NIB1 ;POINT AT THE NUMBER
MOV A,FORMAT ;GET THE FORMAT
MOV R3,A ;SAVE IN CASE OF EXP FORMAT
JZ FREE ;FREE FLOATING?
CJNE A,#0F0H,FPO1 ;SEE IF EXPONENTIAL
FPO1: JNC EXPOUT
;
; If here, must be integer USING format
;
MOV A,R6 ;GET THE EXPONENT
JNZ FPO2
MOV R6,#80H
FPO2: MOV A,R3 ;GET THE FORMAT
SWAP A ;SPLIT INTEGER AND FRACTION
ANL A,#0FH
MOV R2,A ;SAVE INTEGER
ACALL NUM_LT ;GET THE NUMBER OF INTEGERS
XCH A,R2 ;FLIP FOR SUBB
CLR C
SUBB A,R2
MOV R7,A
JNC FPO3
MOV R5,#'?' ;OUTPUT A QUESTION MARK
ACALL SOUT1 ;NUMBER IS TOO LARGE FOR FORMAT
AJMP FREE
FPO3: CJNE R2,#00,USING0 ;SEE IF ZERO
DEC R7
ACALL SS7
ACALL ZOUT ;OUTPUT A ZERO
SJMP USING1
;
USING0: ACALL SS7 ;OUTPUT SPACES, IF NEED TO
MOV A,R2 ;OUTPUT DIGITS
MOV R7,A
ACALL OUTR0
;
USING1: MOV A,R3
ANL A,#0FH ;GET THE NUMBER RIGHT OF DP
MOV R2,A ;SAVE IT
JZ PMT1 ;EXIT IF ZERO
ACALL ROUT ;OUTPUT DP
ACALL NUM_RT
CJNE A,2,USINGX ;COMPARE A TO R2
;
USINGY: MOV A,R2
AJMP Z7R7
;
USINGX: JNC USINGY
;
USING2: XCH A,R2
CLR C
SUBB A,R2
XCH A,R2
ACALL Z7R7 ;OUTPUT ZEROS IF NEED TO
MOV A,R2
MOV R7,A
AJMP OUTR0
;
; First, force exponential output, if need to
;
FREE: MOV A,R6 ;GET THE EXPONENT
JNZ FREE1 ;IF ZERO, PRINT IT
ACALL SOUT
AJMP ZOUT
;
FREE1: MOV R3,#0F0H ;IN CASE EXP NEEDED
MOV A,#80H-DIGIT-DIGIT-1
ADD A,R6
JC EXPOUT
SUBB A,#0F7H
JC EXPOUT
;
; Now, just print the number
;
ACALL SINOUT ;PRINT THE SIGN OF THE NUMBER
ACALL NUM_LT ;GET THE NUMBER LEFT OF DP
CJNE A,#8,FREE4
AJMP OUTR0
;
FREE4: ACALL OUTR0
ACALL ZTEST ;TEST FOR TRAILING ZEROS
JZ U_RET ;DONE IF ALL TRAILING ZEROS
ACALL ROUT ;OUTPUT RADIX
;
FREE2: MOV R7,#1 ;OUTPUT ONE DIGIT
ACALL OUTR0
JNZ U_RET
ACALL ZTEST
JZ U_RET
SJMP FREE2 ;LOOP
;
EXPOUT: ACALL SINOUT ;PRINT THE SIGN
MOV R7,#1 ;OUTPUT ONE CHARACTER
ACALL OUTR0
ACALL ROUT ;OUTPUT RADIX
MOV A,R3 ;GET FORMAT
ANL A,#0FH ;STRIP INDICATOR
JZ EXPOTX
;
MOV R7,A ;OUTPUT THE NUMBER OF DIGITS
DEC R7 ;ADJUST BECAUSE ONE CHAR ALREADY OUT
ACALL OUTR0
SJMP EXPOT4
;
EXPOTX: ACALL FREE2 ;OUTPUT UNTIL TRAILING ZEROS
;
EXPOT4: ACALL SOUT ;OUTPUT A SPACE
MOV R5,#'E'
ACALL SOUT1 ;OUTPUT AN E
MOV A,R6 ;GET THE EXPONENT
JZ XOUT0 ;EXIT IF ZERO
DEC A ;ADJUST FOR THE DIGIT ALREADY OUTPUT
CJNE A,#80H,XOUT2 ;SEE WHAT IT IS
;
XOUT0: ACALL SOUT
CLR A
SJMP XOUT4
;
XOUT2: JC XOUT3 ;NEGATIVE EXPONENT
MOV R5,#'+' ;OUTPUT A PLUS SIGN
ACALL SOUT1
SJMP XOUT4
;
XOUT3: ACALL MOUT
CPL A ;FLIP BITS
INC A ;BUMP
;
XOUT4: CLR ACC.7
MOV R0,A
MOV R2,#0
MOV R1,#LOW CONVERT ;CONVERSION LOCATION
MOV R3,#HIGH CONVERT
ACALL CONVERT_BINARY_TO_ASCII_STRING
MOV R0,#LOW CONVERT ;NOW, OUTPUT EXPONENT
;
EXPOT5: MOVX A,@R0 ;GET THE CHARACTER
MOV R5,A ;OUTPUT IT
ACALL SOUT1
INC R0 ;BUMP THE POINTER
MOV A,R0 ;GET THE POINTER
CJNE A,R1B0,EXPOT5 ;LOOP
;
U_RET: RET ;EXIT
;
OUTR0: ; Output the characters pointed to by R0, also bias ascii
;
MOV A,R7 ;GET THE COUNTER
JZ OUTR ;EXIT IF DONE
MOV A,@R0 ;GET THE NUMBER
ORL A,#30H ;ASCII BIAS
INC R0 ;BUMP POINTER AND COUNTER
DEC R7
MOV R5,A ;PUT CHARACTER IN OUTPUT REGISTER
ACALL SOUT1 ;OUTPUT THE CHARACTER
CLR A ;JUST FOR TEST
CJNE R0,#FP_NIB8+1,OUTR0
MOV A,#55H ;KNOW WHERE EXIT OCCURED
;
OUTR: RET
;
ZTEST: MOV R1,R0B0 ;GET POINTER REGISTER
;
ZT0: MOV A,@R1 ;GET THE VALUE
JNZ ZT1
INC R1 ;BUMP POINTER
CJNE R1,#FP_NIB8+1,ZT0
;
ZT1: RET
;
NUM_LT: MOV A,R6 ;GET EXPONENT
CLR C ;GET READY FOR SUBB
SUBB A,#80H ;SUB EXPONENT BIAS
JNC NL1 ;OK IF NO CARRY
CLR A ;NO DIGITS LEFT
;
NL1: MOV R7,A ;SAVE THE COUNT
RET
;
NUM_RT: CLR C ;SUBB AGAIN
MOV A,#80H ;EXPONENT BIAS
SUBB A,R6 ;GET THE BIASED EXPONENT
JNC NR1
CLR A
;
NR1: RET ;EXIT
;
SPACE7: MOV A,R7 ;GET THE NUMBER OF SPACES
JZ NR1 ;EXIT IF ZERO
ACALL SOUT ;OUTPUT A SPACE
DEC R7 ;BUMP COUNTER
SJMP SPACE7 ;LOOP
;
Z7R7: MOV R7,A
;
ZERO7: MOV A,R7 ;GET COUNTER
JZ NR1 ;EXIT IF ZERO
ACALL ZOUT ;OUTPUT A ZERO
DEC R7 ;BUMP COUNTER
SJMP ZERO7 ;LOOP
;
SS7: ACALL SPACE7
;
SINOUT: MOV A,R4 ;GET THE SIGN
JZ SOUT ;OUTPUT A SPACE IF ZERO
;
MOUT: MOV R5,#'-'
SJMP SOUT1 ;OUTPUT A MINUS IF NOT
;
ROUT: MOV R5,#'.' ;OUTPUT A RADIX
SJMP SOUT1
;
ZOUT: MOV R5,#'0' ;OUTPUT A ZERO
SJMP SOUT1
;
SOUT: MOV R5,#' ' ;OUTPUT A SPACE
;
SOUT1: AJMP OUTPUT
;
$EJECT
;***************************************************************
;
CONVERT_ASCII_STRING_TO_BINARY:
;
;DPTR POINTS TO ASCII STRING
;PUT THE BINARY NUMBER IN R2:R0, ERROR IF >64K
;
;***************************************************************
;
CASB: ACALL HEXSCAN ;SEE IF HEX NUMBER
MOV ADD_IN,C ;IF ADD_IN IS SET, THE NUMBER IS HEX
ACALL GET_DIGIT_CHECK
CPL C ;FLIP FOR EXIT
JC RCASB
MOV R3,#00H ;ZERO R3:R1 FOR LOOP
MOV R1,#00H
SJMP CASB5
;
CASB2: INC DPTR
MOV R0B0,R1 ;SAVE THE PRESENT CONVERTED VALUE
MOV R2B0,R3 ;IN R2:R0
ACALL GET_DIGIT_CHECK
JC CASB5
JNB ADD_IN,RCASB ;CONVERSION COMPLETE
ACALL HEX_CHECK ;SEE IF HEX NUMBER
JC CASB4 ;PROCEED IF GOOD
INC DPTR ;BUMP PAST H
SJMP RCASB
;
CASB4: ADD A,#9 ;ADJUST HEX ASCII BIAS
;
CASB5: MOV B,#10
JNB ADD_IN,CASB6
MOV B,#16 ;HEX MODE
;
CASB6: ACALL MULNUM ;ACCUMULATE THE DIGITS
JNC CASB2 ;LOOP IF NO CARRY
;
RCASB: CLR A ;RESET ACC
MOV ACC.OVERFLOW,C ;IF OVERFLOW, SAY SO
RET ;EXIT
;
$EJECT
;
MULNUM10:MOV B,#10
;
;***************************************************************
;
MULNUM: ; Take the next digit in the acc (masked to 0FH)
; accumulate in R3:R1
;
;***************************************************************
;
PUSH ACC ;SAVE ACC
PUSH B ;SAVE MULTIPLIER
MOV A,R1 ;PUT LOW ORDER BITS IN ACC
MUL AB ;DO THE MULTIPLY
MOV R1,A ;PUT THE RESULT BACK
MOV A,R3 ;GET THE HIGH ORDER BYTE
MOV R3,B ;SAVE THE OVERFLOW
POP B ;GET THE MULTIPLIER
MUL AB ;DO IT
MOV C,OV ;SAVE OVERFLOW IN F0
MOV F0,C
ADD A,R3 ;ADD OVERFLOW TO HIGH RESULT
MOV R3,A ;PUT IT BACK
POP ACC ;GET THE ORIGINAL ACC BACK
ORL C,F0 ;OR CARRY AND OVERFLOW
JC MULX ;NO GOOD IF THE CARRY IS SET
;
MUL11: ANL A,#0FH ;MASK OFF HIGH ORDER BITS
ADD A,R1 ;NOW ADD THE ACC
MOV R1,A ;PUT IT BACK
CLR A ;PROPAGATE THE CARRY
ADDC A,R3
MOV R3,A ;PUT IT BACK
;
MULX: RET ;EXIT WITH OR WITHOUT CARRY
;
;***************************************************************
;
CONVERT_BINARY_TO_ASCII_STRING:
;
;R3:R1 contains the address of the string
;R2:R0 contains the value to convert
;DPTR, R7, R6, and ACC gets clobbered
;
;***************************************************************
;
CLR A ;NO LEADING ZEROS
MOV DPTR,#10000 ;SUBTRACT 10000
ACALL RSUB ;DO THE SUBTRACTION
MOV DPTR,#1000 ;NOW 1000
ACALL RSUB
MOV DPTR,#100 ;NOW 100
ACALL RSUB
MOV DPTR,#10 ;NOW 10
ACALL RSUB
MOV DPTR,#1 ;NOW 1
ACALL RSUB
JZ RSUB2 ;JUMP OVER RET
;
RSUB_R: RET
;
RSUB: MOV R6,#-1 ;SET UP THE COUNTER
;
RSUB1: INC R6 ;BUMP THE COUNTER
XCH A,R2 ;DO A FAST COMPARE
CJNE A,DPH,RSUB11
RSUB11: XCH A,R2
JC FAST_DONE
XCH A,R0 ;GET LOW BYTE
SUBB A,DPL ;SUBTRACT, CARRY IS CLEARED
XCH A,R0 ;PUT IT BACK
XCH A,R2 ;GET THE HIGH BYTE
SUBB A,DPH ;ADD THE HIGH BYTE
XCH A,R2 ;PUT IT BACK
JNC RSUB1 ;LOOP UNTIL CARRY
;
XCH A,R0
ADD A,DPL ;RESTORE R2:R0
XCH A,R0
XCH A,R2
ADDC A,DPH
XCH A,R2
;
FAST_DONE:
;
ORL A,R6 ;OR THE COUNT VALUE
JZ RSUB_R ;RETURN IF ZERO
;
RSUB2: MOV A,#'0' ;GET THE ASCII BIAS
ADD A,R6 ;ADD THE COUNT
;
RSUB4: MOV P2,R3 ;SET UP P2
MOVX @R1,A ;PLACE THE VALUE IN MEMORY
INC R1
CJNE R1,#00H,RSUB3 ;SEE IF RAPPED AROUND
INC R3 ;BUMP HIGH BYTE
;
RSUB3: RET ;EXIT
;
$EJECT
;***************************************************************
;
HEXOUT: ; Output the hex number in R3:R1, supress leading zeros, if set
;
;***************************************************************
;
ACALL SOUT ;OUTPUT A SPACE
MOV C,ZSURP ;GET ZERO SUPPRESSION BIT
MOV ADD_IN,C
MOV A,R3 ;GET HIGH NIBBLE AND PRINT IT
ACALL HOUTHI
MOV A,R3
ACALL HOUTLO
;
HEX2X: CLR ADD_IN ;DON'T SUPPRESS ZEROS
MOV A,R1 ;GET LOW NIBBLE AND PRINT IT
ACALL HOUTHI
MOV A,R1
ACALL HOUTLO
MOV R5,#'H' ;OUTPUT H TO INDICATE HEX MODE
;
SOUT_1: AJMP SOUT1
;
HOUT1: CLR ADD_IN ;PRINTED SOMETHING, SO CLEAR ADD_IN
ADD A,#90H ;CONVERT TO ASCII
DA A
ADDC A,#40H
DA A ;GOT IT HERE
MOV R5,A ;OUTPUT THE BYTE
SJMP SOUT_1
;
HOUTHI: SWAP A ;SWAP TO OUTPUT HIGH NIBBLE
;
HOUTLO: ANL A,#0FH ;STRIP
JNZ HOUT1 ;PRINT IF NOT ZERO
JNB ADD_IN,HOUT1 ;OUTPUT A ZERO IF NOT SUPRESSED
RET
;
$EJECT
ORG 1FEBH ;FOR LINK COMPATABILITY
;
;
GET_DIGIT_CHECK: ; Get a character, then check for digit
;
ACALL GET_DPTR_CHARACTER
;
DIGIT_CHECK: ;CHECK FOR A VALID ASCII DIGIT, SET CARRY IF FOUND
;
CJNE A,#'9'+1,DC10 ;SEE IF ASCII 9 OR LESS
DC10: JC DC1
RET
;
DC1: CJNE A,#'0',DC11 ;SEE IF ASCII 0 OR GREATER
DC11: CPL C
RET
;
;***************************************************************
;
XSEG ;External Ram
;
;***************************************************************
;
DS 4
IBCNT: DS 1 ;LENGTH OF A LINE
IBLN: DS 2 ;THE LINE NUMBER
IBUF: DS LINLEN ;THE INPUT BUFFER
CONVT: DS 15 ;CONVERSION LOCATION FOR FPIN
;
ORG 100H
;
GTB: DS 1 ;GET LOCATION
ERRLOC: DS 1 ;ERROR TYPE
ERRNUM: DS 2 ;WHERE TO GO ON AN ERROR
VARTOP: DS 2 ;TOP OF VARIABLE STORAGE
ST_ALL: DS 2 ;STORAGE ALLOCATION
MT_ALL: DS 2 ;MATRIX ALLOCATION
MEMTOP: DS 2 ;TOP OF MEMORY
RCELL: DS 2 ;RANDOM NUMBER CELL
DS FPSIZ-1
CXTAL: DS 1 ;CRYSTAL
DS FPSIZ-1
FPT1: DS 1 ;FLOATINP POINT TEMP 1
DS FPSIZ-1
FPT2: DS 1 ;FLOATING POINT TEMP 2
INTLOC: DS 2 ;LOCATION TO GO TO ON INTERRUPT
STR_AL: DS 2 ;STRING ALLOCATION
SPV: DS 2 ;SERIAL PORT BAUD RATE
TIV: DS 2 ;TIMER INTERRUPT NUM AND LOC
PROGS: DS 2 ;PROGRAM A PROM TIME OUT
IPROGS: DS 2 ;INTELLIGENT PROM PROGRAMMER TIMEOUT
TM_TOP: DS 1
END
Go to most recent revision | Compare with Previous | Blame | View Log