⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rexpres.asm

📁 在单片机内嵌BASIC语言解释程序的完整代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
*        title    REXPRES.TXT
*        page
******************************************************************************
*                                                                            *
*               RUNTIME EXPRESSION EVALUATION SUBROUTINE                     *
*                                                                            *
******************************************************************************
*
*
DONEXP:	LDAA   #OPARNTOK    ; USE AN OPEN PAREN AS AN END OF EXPRESSION MARKER.
	JSR    PSHOP        ; PUSH OPEN PAREN ON THE STACK.
DONEXP1:	LDAA   0,Y          ; GET THE NEXT CHARACTER IN THE EXPRESSION.
	CMPA   #OPARNTOK    ; IS IT AN OPEN PAREN?
	BNE    DONEXP4      ; NO. CONTINUE.
	INY                 ; POINT TO NEXT TOKEN.
	BSR    DONEXP       ; GO DO A SUBEXPRESSION.
	INY                 ; MOVE THE IP PAST THE CLOSING PAREN.
	BRA    DONEXP1      ; GO GET THE NEXT CHARACTER.
DONEXP4:	TSTA                ; CHECK FOR OPERATOR OR OPERAND.
	BPL    DONEXP2      ; IF NOT VARIABLE OR CONSTANT, GO CHECK FOR FUNCT.
	BSR    PSHNUM       ; GO PUSH OPERAND ONTO STACK.
	BRA    DONEXP1      ; GO GET NEXT TOKEN.
DONEXP2:	JSR    CHKNFUN      ; GO CHECK FOR FUNCTION THAT RETURNS A NUMBER.
	JSR    CHCKEE       ; GO CHECK FOR END OF EXPRESSION.
	BCC    DONEXP3      ; IF NOT END OF EXPRESSION, GO PUSH OPERATOR.
	RTS                 ; IF AT END, RETURN.
DONEXP3:	INY                 ; POINT TO THE NEXT TOKEN.
	JSR    PSHOP        ; PUSH OPERATOR ONTO STACK.
	BRA    DONEXP1      ; GO GET NEXT TOKEN.
*
*
*
*        PSHNUM SUBROUTINE
*
*        PUSHES A NUMERIC OPERAND (CONSTANT OR VARIABLE) VALUE ONTO THE
*        OPERAND STACK.
*
*
PSHNUM:	CMPA   #IVARTOK     ; IS IT AN INTEGER SCALER VARIABLE?
	BNE    PSHNUM1      ; NO. GO CHECK FOR CONSTANT.
	LDD    1,Y          ; YES. GET THE "OFFSET" ADDRESS.
	ADDD   VARBEGIN     ; ADD IN THE START ADDRESS OF THE VARIABLE TABLE.
	XGDX                ; GET THE ADDRESS INTO X.
	LDAB   #$03         ; BUMP INTERPRETER POINTER PAST "VARIABLE".
	ABY
	LDD    3,X          ; GET THE VARIABLE VALUE.
	BRA    PSHNUM4      ; GO PUT IT ON THE STACK.
PSHNUM1:	CMPA   #ICONTOK     ; IS IT AN INTEGER CONSTANT?
	BNE    PSHNUM2      ; NO. GO CHECK FOR AN INTEGER ARRAY VARIABLE.
	LDX    1,Y          ; GET THE CONSTANT VALUE INTO X.
	LDAB   #$04
	ADDB   3,Y
	ABY
	XGDX                ; PUT THE CONSTANT VALUE INTO D.
	BRA    PSHNUM4      ; GO PUT IT ON THE STACK.
PSHNUM2:	CMPA   #IAVARTOK    ; IS IT AN INTEGER ARRAY?
	BNE    PSHNUM3      ; NO. GO CHECK FOR A STRING VARIABLE.
	BSR    CALCSUB      ; GO GET BASE ADDR. & SUBSCRIPT OF ARRAY.
	PSHY                ; SAVE THE INTERPRETER POINTER.
	PSHX                ; PUT THE BASE ADDRESS OF THE ARRAY ON THE STACK.
	ASLD                ; MULTIPLY THE SUBSCRIPT BY THE # OF BYTES/ELEMENT.
	TSY                 ; POINT TO THE BASE ADDRESS.
	ADDD   0,Y          ; GET ADDRESS OF THE ELEMENT.
	PULX                ; RESTORE X.
	PULY                ; RESTORE Y
	XGDX                ; PUT ELEMENT ADDRESS INTO X.
	LDD    0,X          ; GET VALUE OF ELEMENT IN D.
	BRA    PSHNUM4 
PSHNUM3:	LDAA   #ILTOKERR
	JMP    RPTRERR
PSHNUM4:	LDX    NUMSTACK     ; GET THE OPERAND STACK POINTER.
	DEX                 ; MAKE ROOM ON THE STACK FOR NEW OPERAND.
	DEX
	CPX    ENUMSTK      ; HAS THE STACK OVERFLOWED?
	BHS    PSHNUM5      ; NO. GO STACK THE VALUE.
	LDAA   #MSTKOERR    ; YES.
	STAA   ERRCODE
	JMP    RPTRERR      ; GO REPORT THE ERROR.
PSHNUM5:	STX    NUMSTACK     ; SAVE THE STACK POINTER.
	STD    0,X          ; PUT THE VALUE ON THE STACK.
	RTS                 ; RETURN.
*
*
*        THIS SUBROUTINE CALCULATES BOTH THE BASE ADDRESS AND THE
*        SUBSCRIPT OF THE ARRAY VARIABLE THAT IS CURRENTLY POINTED TO BY
*        THE Y-REG. IT CHECKS TO SEE IF THE VARIABLE HAS BEEN DIMENTIONED
*        AND IF THE SUBSCRIPT IS IN RANGE. THE ROUTINE RETURNS WITH THE
*        ADDRESS OF THE ARRAY IN THE X-REG. & THE SUBSCRIPT IN THE D-REG.
*
CALCSUB:	LDD    1,Y          ; GET THE VARIABLE OFFSET ADDRESS.
	ADDD   VARBEGIN     ; ADD IN THE START OF THE VARIABLE AREA.
	XGDX                ; PUT ADDRESS INTO X.
	LDX    3,X          ; GET THE ACTUAL STORAGE ADDRESS.
*                             ; HAS THE ARRAY BEEN DIMENTIONED?
	BNE    CALCSUB2     ; YES. CONTINUE.
	LDAA   #UNDIMERR    ; NO. UNDIMENTIONED ARRAY REFERENCE.
CALCSUB1:	JMP    RPTRERR      ; GO REPORT THE ERROR.
CALCSUB2:	LDAB   #$4          ; SET POINTER TO START OF SUBSCRIPT EXPRESSION.
	ABY
	PSHX                ; SAVE THE POINTER TO THE ARRAY STORAGE AREA.
	JSR    DONEXP       ; GO GET THE SUBSCRIPT.
	INY                 ; BUMP IP PAST THE CLOSING PAREN OF THE SUBSCRIPT.
	PULX                ; RESTORE X.
	JSR    PULNUM       ; GET SUBSCRIPT FROM THE OPERAND STACK.
	CPD    0,X          ; IS THE SUBSCRIPT WITHIN RANGE?
	BLS    CALCSUB3     ; YES. CONTINUE.
	LDAA   #SUBORERR    ; NO. SUBSCRIPT OUT OF RANGE ERROR.
	BRA    CALCSUB1     ; GO REPORT IT.
CALCSUB3:	INX                 ; BYPASS THE SUBSCRIPT LIMIT.
	INX
	RTS
*
*
PULNUM:	PSHX                ; SAVE THE X-REG.
	LDX    NUMSTACK     ; GET THE OPERAND STACK POINTER.
	LDD    0,X          ; GET THE OPERAND.
	INX                 ; BUMP THE STACK POINTER.
	INX
	STX    NUMSTACK     ; SAVE THE STACK POINTER.
	PULX                ; RESTORE THE X-REG.
	CPD    #0           ; "TEST" THE OPERAND BEFORE WE RETURN.
	RTS                 ; RETURN.
*
*
*        /***** chcknfun() *****/
*
*        /* checks for a numeric function and performs it if present */
*
CHKNFUN:	CMPA   #FUNCTFLG    ; IS THIS A FUNCTION CALL?
	BEQ    CHKNFUN1     ; YES. GO DO THE FUNCTION.
	RTS                 ; NO. JUST RETURN.
CHKNFUN1:	LDAA   1,Y          ; GET THE FUNCTION CODE BYTE IN B.
	DECA                ; SUBTRACT 1 FOR INDEXING.
	LDAB   #3           ; BUMP THE IP.
	ABY                 ; POINT TO THE FIRST ELEMENT IN THE EXPRESSION.
	TAB                 ; PUT THE FUNCTION NUMBER INTO B.
	ASLB                ; MULT BY THE NUMBER OF BYTES/ADDRESS.
	LDX    #RNFUNCT     ; POINT TO THE FUNCTION ADDRESS TABLE.
	ABX                 ; POINT TO THE PROPER FUNCTION.
	LDX    0,X          ; GET THE ADDRESS INTO X.
	JSR    0,X          ; GO DO THE FUNCTION.
	INY                 ; PUT IP PAST THE CLOSING PAREN.
	LDAA   0,Y          ; GET NEXT CHARACTER.
	RTS                 ; RETURN.
*
*
RNFUNCT:	EQU    *
	FDB    RFDIV
	FDB    ICHRS        ; "ICHRS" BECAUSE IT'S ILLEGAL IN AN EXPRESSION.
	FDB    RADC
	FDB    RABS
	FDB    RRND
	FDB    RSGN
	FDB    ITAB         ; "ITAB" BECAUSE IT'S ILLEGAL IN AN EXPRESSION.
	FDB    RCALL
	FDB    RPEEK
	FDB    RFEEP        ; "EEP" AS A FUNCTION.
	FDB    IHEX         ; "IHEX" BECAUSE IT'S ILLEGAL IN AN EXPRESSION.
	FDB    RFPORTA
	FDB    RFPORTB
	FDB    RFPORTC
	FDB    RFPORTD
	FDB    RFPORTE
	FDB    RFTIME
	FDB    IHEX2        ; "IHEX2" BECAUSE IT'S ILLEGAL IN AN EXPRESSION.
	FDB    RFPACC
*
*
*        /***** chckee() *****/
*
*        /* if the current token is a semicolin, comma, colin, or space */
*        /* all pending operations on the math stack are performed and */
*        /* we return with the carry set */
*
CHCKEE:	EQU    *
	CMPA   #CPARNTOK    ; IS IT A CLOSED PAREN?
	BEQ    CHCKEE2      ; YES.
	CMPA   #MEOLTOK     ; IS IT ONE OF THE "EXPRESSION END" TOKENS?
	BHS    CHCKEE1      ; YES.
	CLC                 ; FLAG "NOT AT THE END OF EXPRESSION".
	RTS                 ; RETURN.
CHCKEE1:	LDAA   #CPARNTOK    ; END OF EXPRESSION FOUND. PERFORM ALL PENDING
CHCKEE2:	BSR    PSHOP        ; OPERATIONS.
	SEC                 ; FLAG END OF EXPRESSION.
	RTS
*
*
PSHOP:	LDX    OPSTACK      ; GET THE OPERATOR STACK POINTER.
	DEX                 ; DECREMENT THE STACK POINTER.
	CPX    EOPSTK       ; DID THE STACK OVERFLOW?
	BNE    PSHOP1       ; NO. CONTINUE.
	LDAA   #MSTKOERR    ; YES.
	JMP    RPTRERR      ; GO REPORT THE ERROR.
PSHOP1:	STX    OPSTACK
	STAA   0,X          ; PUT IT ON THE STACK.
PSHOP2:	LDX    OPSTACK
	LDAA   0,X          ; GET THE NEW OPERATOR OFF THE TOP OF STACK.
	CMPA   #OPARNTOK    ; IS IT AN OPEN PAREN?
	BEQ    PSHOP5       ; YES. GO PUSH IT.
	LDAB   1,X          ; GET THE PREVIOUS OPERATOR OFF THE STACK.
	ANDB   #$F0         ; MASK ALL BUT THE PRECIDENCE VALUE.
	ANDA   #$F0         ; MASK ALL BUT THE OPERATOR PRECIDENCE.
	CBA                 ; IS THE PRECIDENCE OF THE CURRENT OPERATOR >=
*                             ; THE OPERATOR ON THE TOP OF THE STACK?
	BHI    PSHOP5       ; NO. JUST GO PUSH IT ON THE STACK.
	LDAA   1,X          ; YES. GET THE PREVIOUS OPERATOR FROM THE STACK.
	LDAB   0,X          ; GET THE CURRENT OPERATOR FROM THE STACK.
	CMPB   #CPARNTOK    ; IS THE CURRENT OPERATOR A CLOSED PAREN?
	BNE    PSHOP3       ; NO. CONTINUE.
	CMPA   #OPARNTOK    ; YES. IS THE PREVIOUS OPERATOR AN OPEN PAREN?
	BNE    PSHOP3       ; NO. CONTINUE.
	INX                 ; YES. KNOCK BOTH OPERATORS OFF THE STACK.
	INX
	STX    OPSTACK      ; SAVE THE STACK POINTER.
PSHOP5:	RTS                 ; RETURN.
PSHOP3:	STAB   1,X          ; PUT IT ON THE STACK.
	INX                 ; UPDATE THE STACK POINTER.
	STX    OPSTACK
	BSR    DOOP         ; GO DO THE OPERATION.
	BRA    PSHOP2       ; GO TRY FOR ANOTHER OPERATION.
*
*
DOOP:	CMPA   #$70         ; IS IT A UINARY OPERATOR?
	BLO    DOOP1        ; NO. GO CHECK THE NEXT GROUP.
	SUBA   #$70         ; YES. SUBTRACT THE BASE VALUE OF THE GROUP.
	LDX    #HEIR7       ; POINT TO THE EXECUTION ADDRESS TABLE.
	BRA    DOOP7        ; GO DO THE OPERATION.
DOOP1:	CMPA   #$60         ; IS IT THE "^" OPERATOR?
	BLO    DOOP2        ; NO. GO CHECK THE NEXT GROUP.
	SUBA   #$60         ; YES. SUBTRACT THE BASE VALUE OF THE GROUP.
	LDX    #HEIR6       ; POINT TO THE EXECUTION ADDRESS TABLE.
	BRA    DOOP7        ; GO DO THE OPERATION.
DOOP2:	CMPA   #$50         ; IS IT MULTIPLY, DIVIDE, OR MOD?
	BLO    DOOP3        ; NO. GO CHECK THE NEXT GROUP.
	SUBA   #$50         ; YES. SUBTRACT THE BASE VALUE OF THE GROUP.
	LDX    #HEIR5       ; POINT TO THE EXECUTION ADDRESS TABLE.
	BRA    DOOP7        ; GO DO THE OPERATION.
DOOP3:	CMPA   #$40         ; IS IT ADD OR SUBTRACT?
	BLO    DOOP4        ; NO. GO CHECK THE NEXT GROUP.
	SUBA   #$40         ; YES. SUBTRACT THE BASE VALUE OF THE GROUP.
	LDX    #HEIR4       ; POINT TO THE EXECUTION ADDRESS TABLE.
	BRA    DOOP7        ; GO DO THE OPERATION.
DOOP4:	CMPA   #$30         ; IS IT A LOGICAL OPERATOR?
	BLO    DOOP5        ; NO. GO CHECK THE NEXT GROUP.
	SUBA   #$30         ; YES. SUBTRACT THE BASE VALUE OF THE GROUP.
	LDX    #HEIR3       ; POINT TO THE EXECUTION ADDRESS TABLE.
	BRA    DOOP7        ; GO DO THE OPERATION.
DOOP5:	CMPA   #$20         ; IS IT AND, OR, OR EOR?
	BLO    DOOP6        ; NO. ERROR.
	SUBA   #$20         ; YES. SUBTRACT THE BASE VALUE OF THE GROUP.
	LDX    #HEIR2       ; POINT TO THE EXECUTION ADDRESS TABLE.
	BRA    DOOP7        ; GO DO THE OPERATION.
DOOP6:	LDAA   #ILTOKERR    ; ILLEGAL OPERATOR TOKEN ENCOUNTERED.
	JMP    RPTRERR      ; GO REPORT THE ERROR.
DOOP7:	TAB                 ; PUT THE OFFSET IN B.
	ASLB                ; MULTIPLY THE OFFSET BY 2.
	ABX                 ; POINT TO THE ROUTINE ADDRESS.
	LDX    0,X          ; GET THE ADDRESS.
	JMP    0,X          ; GO DO THE OPERATION & RETURN.
*
*
HEIR7:	EQU    *
	FDB    RINDIR
	FDB    RNOT
	FDB    RNEG
HEIR6:	EQU    *
	FDB    RPWR
HEIR5:	EQU    *
	FDB    RMULT
	FDB    RDIV
	FDB    RMOD
HEIR4:	EQU    *
	FDB    RPLUS
	FDB    RMINUS
HEIR3:	EQU    *
	FDB    RLT
	FDB    RGT
	FDB    RLTEQ
	FDB    RGTEQ
	FDB    REQ
	FDB    RNOTEQ
HEIR2:	EQU    *
	FDB    RAND
	FDB    RORV
	FDB    REOR
*
*
REOR:	JSR    PULNUM
	LDX    NUMSTACK
	EORA   0,X
	EORB   1,X
REOR1:	STD    0,X
	RTS
*
*
RORV:	JSR    PULNUM
	LDX    NUMSTACK
	ORAA   0,X
	ORAB   1,X
	BRA    REOR1
*
*
RAND:	JSR    PULNUM
	LDX    NUMSTACK
	ANDA   0,X
	ANDB   1,X
	BRA    REOR1
*
*
RPLUS:	JSR    PULNUM
	LDX    NUMSTACK
	ADDD   0,X
	BRA    REOR1
*
*
RMINUS:	LDX    NUMSTACK
	LDD    2,X
	SUBD   0,X
	INX
	INX
	STD    0,X
	STX    NUMSTACK
	RTS
*
*
RDIV:	BSR    RDIVS        ; GO DO A SIGNED DIVIDE.
	JSR    PULNUM       ; GET INTEGER RESULT OFF STACK.
	LDX    NUMSTACK     ; POINT TO NUMERIC STACK.
	STD    0,X          ; OVERWRITE REMAINDER.
	RTS                 ; RETURN.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -