📄 eforth.asm
字号:
; ?STACK ( -- )
; Abort if the data stack underflows.
$COLON 6,'?STACK',QSTAC
DW DEPTH,ZLESS ;check only for underflow
D$ ABORQ,' underflow'
DW EXIT
; EVAL ( -- )
; Interpret the input stream.
$COLON 4,'EVAL',EVAL
EVAL1: DW TOKEN,DUPP,CAT ;?input stream empty
DW QBRAN,EVAL2
DW TEVAL,ATEXE,QSTAC ;evaluate input, check stack
DW BRAN,EVAL1
EVAL2: DW DROP,TPROM,ATEXE,EXIT ;prompt
;; Shell
; PRESET ( -- )
; Reset data stack pointer and the terminal input buffer.
$COLON 6,'PRESET',PRESE
DW SZERO,AT,SPSTO
DW DOLIT,TIBB,NTIB,CELLP,STORE,EXIT
; xio ( a a a -- )
; Reset the I/O vectors 'EXPECT, 'TAP, 'ECHO and 'PROMPT.
$COLON COMPO+3,'xio',XIO
DW DOLIT,ACCEP,TEXPE,DSTOR
DW TECHO,DSTOR,EXIT
; FILE ( -- )
; Select I/O vectors for file download.
$COLON 4,'FILE',FILE
DW DOLIT,PACE,DOLIT,DROP
DW DOLIT,KTAP,XIO,EXIT
; HAND ( -- )
; Select I/O vectors for terminal interface.
$COLON 4,'HAND',HAND
DW DOLIT,DOTOK,DOLIT,EMIT
DW DOLIT,KTAP,XIO,EXIT
; I/O ( -- a )
; Array to store default I/O vectors.
$COLON 3,'I/O',ISLO
DW DOVAR ;emulate CREATE
DW QRX,TXSTO ;default I/O vectors
; CONSOLE ( -- )
; Initiate terminal interface.
$COLON 7,'CONSOLE',CONSO
DW ISLO,DAT,TQKEY,DSTOR ;restore default I/O device
DW HAND,EXIT ;keyboard input
; QUIT ( -- )
; Reset return stack pointer and start text interpreter.
$COLON 4,'QUIT',QUIT
DW RZERO,AT,RPSTO ;reset return stack pointer
QUIT1: DW LBRAC ;start interpretation
QUIT2: DW QUERY ;get input
DW DOLIT,EVAL,CATCH,QDUP ;evaluate input
DW QBRAN,QUIT2 ;continue till error
DW TPROM,AT,SWAP ;save input device
DW CONSO,NULLS,OVER,XORR ;?display error message
DW QBRAN,QUIT3
DW SPACE,COUNT,TYPEE ;error message
D$ DOTQP,' ? ' ;error prompt
QUIT3: DW DOLIT,DOTOK,XORR ;?file input
DW QBRAN,QUIT4
DW DOLIT,ERR,EMIT ;file error, tell host
QUIT4: DW PRESE ;some cleanup
DW BRAN,QUIT1
;; The compiler
; ' ( -- ca )
; Search context vocabularies for the next word in input stream.
$COLON 1,"'",TICK
DW TOKEN,NAMEQ ;?defined
DW QBRAN,TICK1
DW EXIT ;yes, push code address
TICK1: DW THROW ;no, error
; ALLOT ( n -- )
; Allocate n bytes to the code dictionary.
$COLON 5,'ALLOT',ALLOT
DW CP,PSTOR,EXIT ;adjust code pointer
; , ( w -- )
; Compile an integer into the code dictionary.
$COLON 1,',',COMMA
DW HERE,DUPP,CELLP ;cell boundary
DW CP,STORE,STORE,EXIT ;adjust code pointer, compile
; [COMPILE] ( -- ; <string> )
; Compile the next immediate word into code dictionary.
$COLON IMEDD+9,'[COMPILE]',BCOMP
DW TICK,COMMA,EXIT
; COMPILE ( -- )
; Compile the next address in colon list to code dictionary.
$COLON COMPO+7,'COMPILE',COMPI
DW RFROM,DUPP,AT,COMMA ;compile address
DW CELLP,TOR,EXIT ;adjust return address
; LITERAL ( w -- )
; Compile tos to code dictionary as an integer literal.
$COLON IMEDD+7,'LITERAL',LITER
DW COMPI,DOLIT,COMMA,EXIT
; $," ( -- )
; Compile a literal string up to next " .
$COLON 3,'$,"',STRCQ
DW DOLIT,'"',WORDD ;move string to code dictionary
DW COUNT,PLUS,ALGND ;calculate aligned end of string
DW CP,STORE,EXIT ;adjust the code pointer
; RECURSE ( -- )
; Make the current word available for compilation.
$COLON IMEDD+7,'RECURSE',RECUR
DW LAST,AT,NAMET,COMMA,EXIT
;; Structures
; FOR ( -- a )
; Start a FOR-NEXT loop structure in a colon definition.
$COLON IMEDD+3,'FOR',FOR
DW COMPI,TOR,HERE,EXIT
; BEGIN ( -- a )
; Start an infinite or indefinite loop structure.
$COLON IMEDD+5,'BEGIN',BEGIN
DW HERE,EXIT
; NEXT ( a -- )
; Terminate a FOR-NEXT loop structure.
$COLON IMEDD+4,'NEXT',NEXT
DW COMPI,DONXT,COMMA,EXIT
; UNTIL ( a -- )
; Terminate a BEGIN-UNTIL indefinite loop structure.
$COLON IMEDD+5,'UNTIL',UNTIL
DW COMPI,QBRAN,COMMA,EXIT
; AGAIN ( a -- )
; Terminate a BEGIN-AGAIN infinite loop structure.
$COLON IMEDD+5,'AGAIN',AGAIN
DW COMPI,BRAN,COMMA,EXIT
; IF ( -- A )
; Begin a conditional branch structure.
$COLON IMEDD+2,'IF',IFF
DW COMPI,QBRAN,HERE
DW DOLIT,0,COMMA,EXIT
; AHEAD ( -- A )
; Compile a forward branch instruction.
$COLON IMEDD+5,'AHEAD',AHEAD
DW COMPI,BRAN,HERE,DOLIT,0,COMMA,EXIT
; REPEAT ( A a -- )
; Terminate a BEGIN-WHILE-REPEAT indefinite loop.
$COLON IMEDD+6,'REPEAT',REPEA
DW AGAIN,HERE,SWAP,STORE,EXIT
; THEN ( A -- )
; Terminate a conditional branch structure.
$COLON IMEDD+4,'THEN',THENN
DW HERE,SWAP,STORE,EXIT
; AFT ( a -- a A )
; Jump to THEN in a FOR-AFT-THEN-NEXT loop the first time through.
$COLON IMEDD+3,'AFT',AFT
DW DROP,AHEAD,BEGIN,SWAP,EXIT
; ELSE ( A -- A )
; Start the false clause in an IF-ELSE-THEN structure.
$COLON IMEDD+4,'ELSE',ELSEE
DW AHEAD,SWAP,THENN,EXIT
; WHILE ( a -- A a )
; Conditional branch out of a BEGIN-WHILE-REPEAT loop.
$COLON IMEDD+5,'WHILE',WHILE
DW IFF,SWAP,EXIT
; ABORT" ( -- ; <string> )
; Conditional abort with an error message.
$COLON IMEDD+6,'ABORT"',ABRTQ
DW COMPI,ABORQ,STRCQ,EXIT
; $" ( -- ; <string> )
; Compile an inline string literal.
$COLON IMEDD+2,'$"',STRQ
DW COMPI,STRQP,STRCQ,EXIT
; ." ( -- ; <string> )
; Compile an inline string literal to be typed out at run time.
$COLON IMEDD+2,'."',DOTQ
DW COMPI,DOTQP,STRCQ,EXIT
;; Name compiler
; ?UNIQUE ( a -- a )
; Display a warning message if the word already exists.
$COLON 7,'?UNIQUE',UNIQU
DW DUPP,NAMEQ ;?name exists
DW QBRAN,UNIQ1 ;redefinitions are OK
D$ DOTQP,' reDef ' ;but warn the user
DW OVER,COUNT,TYPEE ;just in case its not planned
UNIQ1: DW DROP,EXIT
; $,n ( na -- )
; Build a new dictionary name using the string at na.
$COLON 3,'$,n',SNAME
DW DUPP,CAT ;?null input
DW QBRAN,PNAM1
DW UNIQU ;?redefinition
DW DUPP,LAST,STORE ;save na for vocabulary link
DW HERE,ALGND,SWAP ;align code address
DW CELLM ;link address
DW CRRNT,AT,AT,OVER,STORE
DW CELLM,DUPP,NP,STORE ;adjust name pointer
DW STORE,EXIT ;save code pointer
PNAM1: D$ STRQP,' name' ;null input
DW THROW
;; FORTH compiler
; $COMPILE ( a -- )
; Compile next word to code dictionary as a token or literal.
$COLON 8,'$COMPILE',SCOMP
DW NAMEQ,QDUP ;?defined
DW QBRAN,SCOM2
DW AT,DOLIT,IMEDD,ANDD ;?immediate
DW QBRAN,SCOM1
DW EXECU,EXIT ;its immediate, execute
SCOM1: DW COMMA,EXIT ;its not immediate, compile
SCOM2: DW TNUMB,ATEXE ;try to convert to number
DW QBRAN,SCOM3
DW LITER,EXIT ;compile number as integer
SCOM3: DW THROW ;error
; OVERT ( -- )
; Link a new word into the current vocabulary.
$COLON 5,'OVERT',OVERT
DW LAST,AT,CRRNT,AT,STORE,EXIT
; ; ( -- )
; Terminate a colon definition.
$COLON IMEDD+COMPO+1,';',SEMIS
DW COMPI,EXIT,LBRAC,OVERT,EXIT
; ] ( -- )
; Start compiling the words in the input stream.
$COLON 1,']',RBRAC
DW DOLIT,SCOMP,TEVAL,STORE,EXIT
; call, ( ca -- )
; Assemble a call instruction to ca.
$COLON 5,'call,',CALLC
DW DOLIT,CALLL,COMMA,HERE ;Direct Threaded Code
DW CELLP,SUBB,COMMA,EXIT ;DTC 8086 relative call
; : ( -- ; <string> )
; Start a new colon definition using next word as its name.
$COLON 1,':',COLON
DW TOKEN,SNAME,DOLIT,DOLST
DW CALLC,RBRAC,EXIT
; IMMEDIATE ( -- )
; Make the last compiled word an immediate word.
$COLON 9,'IMMEDIATE',IMMED
DW DOLIT,IMEDD,LAST,AT,AT,ORR
DW LAST,AT,STORE,EXIT
;; Defining words
; USER ( u -- ; <string> )
; Compile a new user variable.
$COLON 4,'USER',USER
DW TOKEN,SNAME,OVERT
DW DOLIT,DOLST,CALLC
DW COMPI,DOUSE,COMMA,EXIT
; CREATE ( -- ; <string> )
; Compile a new array entry without allocating code space.
$COLON 6,'CREATE',CREAT
DW TOKEN,SNAME,OVERT
DW DOLIT,DOLST,CALLC
DW COMPI,DOVAR,EXIT
; VARIABLE ( -- ; <string> )
; Compile a new variable initialized to 0.
$COLON 8,'VARIABLE',VARIA
DW CREAT,DOLIT,0,COMMA,EXIT
;; Tools
; _TYPE ( b u -- )
; Display a string. Filter non-printing characters.
$COLON 5,'_TYPE',UTYPE
DW TOR ;start count down loop
DW BRAN,UTYP2 ;skip first pass
UTYP1: DW DUPP,CAT,TCHAR,EMIT ;display only printable
DW DOLIT,1,PLUS ;increment address
UTYP2: DW DONXT,UTYP1 ;loop till done
DW DROP,EXIT
; dm+ ( a u -- a )
; Dump u bytes from , leaving a+u on the stack.
$COLON 3,'dm+',DMP
DW OVER,DOLIT,4,UDOTR ;display address
DW SPACE,TOR ;start count down loop
DW BRAN,PDUM2 ;skip first pass
PDUM1: DW DUPP,CAT,DOLIT,3,UDOTR ;display numeric data
DW DOLIT,1,PLUS ;increment address
PDUM2: DW DONXT,PDUM1 ;loop till done
DW EXIT
; DUMP ( a u -- )
; Dump u bytes from a, in a formatted manner.
$COLON 4,'DUMP',DUMP
DW BASE,AT,TOR,HEX ;save radix, set hex
DW DOLIT,16,SLASH ;change count to lines
DW TOR ;start count down loop
DUMP1: DW CR,DOLIT,16,DDUP,DMP ;display numeric
DW ROT,ROT
DW SPACE,SPACE,UTYPE ;display printable characters
DW NUFQ,INVER ;user control
DW QBRAN,DUMP2
DW DONXT,DUMP1 ;loop till done
DW BRAN,DUMP3
DUMP2: DW RFROM,DROP ;cleanup loop stack, early exit
DUMP3: DW DROP,RFROM,BASE,STORE ;restore radix
DW EXIT
; .S ( ... -- ... )
; Display the contents of the data stack.
$COLON 2,'.S',DOTS
DW CR,DEPTH ;stack depth
DW TOR ;start count down loop
DW BRAN,DOTS2 ;skip first pass
DOTS1: DW RAT,PICK,DOT ;index stack, display contents
DOTS2: DW DONXT,DOTS1 ;loop till done
D$ DOTQP,' <sp'
DW EXIT
; !CSP ( -- )
; Save stack pointer in CSP for error checking.
$COLON 4,'!CSP',STCSP
DW SPAT,CSP,STORE,EXIT ;save pointer
; ?CSP ( -- )
; Abort if stack pointer differs from that saved in CSP.
$COLON 4,'?CSP',QCSP
DW SPAT,CSP,AT,XORR ;compare pointers
D$ ABORQ,'stacks' ;abort if different
DW EXIT
; >NAME ( ca -- na | F )
; Convert code address to a name address.
$COLON 5,'>NAME',TNAME
DW CRRNT ;vocabulary link
TNAM1: DW CELLP,AT,QDUP ;check all vocabularies
DW QBRAN,TNAM4
DW DDUP
TNAM2: DW AT,DUPP ;?last word in a vocabulary
DW QBRAN,TNAM3
DW DDUP,NAMET,XORR ;compare
DW QBRAN,TNAM3
DW CELLM ;continue with next word
DW BRAN,TNAM2
TNAM3: DW SWAP,DROP,QDUP
DW QBRAN,TNAM1
DW SWAP,DROP,SWAP,DROP,EXIT
TNAM4: DW DROP,DOLIT,0,EXIT ;false flag
; .ID ( na -- )
; Display the name at address.
$COLON 3,'.ID',DOTID
DW QDUP ;if zero no name
DW QBRAN,DOTI1
DW COUNT,DOLIT,01FH,ANDD ;mask lexicon bits
DW UTYPE,EXIT ;display name string
DOTI1: D$ DOTQP,' {noName}'
DW EXIT
; SEE ( -- ; <string> )
; A simple decompiler.
$COLON 3,'SEE',SEE
DW TICK ;starting address
DW CR,CELLP
SEE1: DW CELLP,DUPP,AT,DUPP ;?does it contain a zero
DW QBRAN,SEE2
DW TNAME ;?is it a name
SEE2: DW QDUP ;name address or zero
DW QBRAN,SEE3
DW SPACE,DOTID ;display name
DW BRAN,SEE4
SEE3: DW DUPP,AT,UDOT ;display number
SEE4: DW NUFQ ;user control
DW QBRAN,SEE1
DW DROP,EXIT
; WORDS ( -- )
; Display the names in the context vocabulary.
$COLON 5,'WORDS',WORDS
DW CR,CNTXT,AT ;only in context
WORS1: DW AT,QDUP ;?at end of list
DW QBRAN,WORS2
DW DUPP,SPACE,DOTID ;display a name
DW CELLM,NUFQ ;user control
DW QBRAN,WORS1
DW DROP
WORS2: DW EXIT
;; Hardware reset
; VER ( -- n )
; Return the version number of this implementation.
$COLON 3,'VER',VERSN
DW DOLIT,VER*256+EXT,EXIT
; hi ( -- )
; Display the sign-on message of eForth.
$COLON 2,'hi',HI
DW STOIO,CR ;initialize I/O
D$ DOTQP,'eForth v' ;model
DW BASE,AT,HEX ;save radix
DW VERSN,BDIGS,DIG,DIG
DW DOLIT,'.',HOLD
DW DIGS,EDIGS,TYPEE ;format version number
DW BASE,STORE,CR,EXIT ;restore radix
; 'BOOT ( -- a )
; The application startup vector.
$COLON 5,"'BOOT",TBOOT
DW DOVAR
DW HI ;application to boot
; COLD ( -- )
; The hilevel cold start sequence.
$COLON 4,'COLD',COLD
COLD1: DW DOLIT,UZERO,DOLIT,UPP
DW DOLIT,ULAST-UZERO,CMOVE ;initialize user area
DW PRESE ;initialize stack and TIB
DW TBOOT,ATEXE ;application boot
DW FORTH,CNTXT,AT,DUPP ;initialize search order
DW CRRNT,DSTOR,OVERT
DW QUIT ;start interpretation
DW BRAN,COLD1 ;just in case
;===============================================================
LASTN EQU _NAME+4 ;last name address
NTOP EQU _NAME-0 ;next available memory in name dictionary
CTOP EQU $+0 ;next available memory in code dictionary
MAIN ENDS
END ORIG
;===============================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -