?? rexpres.asm
字號:
* 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 + -