blob: 26576b5a29daa1fb0c821b8b4374b5e4b317eb0e [file] [log] [blame]
swissChilif7f1e2b2021-12-31 14:42:43 -08001 ;; FORTH.ASM -- Forth system for Microsoft (R) DOS
2
3 BITS 16
4
5 ;; DOS loads .COM executables here
6 ORG 100h
7
8 %INCLUDE "DOS.ASM"
9
10;;; MACROS ;;;
11
12 ;; Step indirect threaded code to next word. Call this in a raw
13 ;; word to effectively return. In an interpreted word SI first
14 ;; needs to be reset to the calling value.
15 %MACRO NEXT 0
16 LODSW
17 MOV BX, AX ; [ax] is invalid in 16 bits
18 JMP [BX]
19 %ENDMACRO
20
21
22 ;; Push register operand to return stack
23 %MACRO RSPUSH 1
24 SUB BP, WORDSZ
25 MOV [BP], %1
26 %ENDMACRO
27
28
29 ;; Pop from return stack to register operand
30 %MACRO RSPOP 1
31 MOV %1, [BP]
32 ADD BP, WORDSZ
33 %ENDMACRO
34
35
36 ;; Used for the compile-time dictionary linked list. Not used at
37 ;; runtime.
38 %DEFINE LINK 0
39
40
41 IMMEDIATE_BIT EQU 1 << 6
42 HIDDEN_BIT EQU 1 << 5
43 LENGTH_MASK EQU 0b11111
44
45
46 ;; Define a threaded word. The arguments should be the symbol for
47 ;; the word, followed by the string version. e.g.:
48 ;;
49 ;; DEFWORD DUP, 'DUP', IMMEDIATE_BIT
50 %MACRO DEFWORD 3
51 ALIGN 2
52
53WORD_%1:
54 DW LINK
55 %DEFINE LINK WORD_%1
56 DB WORDLEN_%1 | %3 ; Length | Flags
57
58NAME_%1:
59 DB %2,
60 WORDLEN_%1 EQU $ - NAME_%1
61
62 ALIGN 2
63
64%1:
65 %ENDMACRO
66
67
68 %MACRO DEFWORD_THREADED 2
69 DEFWORD %1, %2, 0
70 DW DOCOL
71 %ENDMACRO
72
73
74 %MACRO DEFWORD_THREADED_IMMED 2
75 DEFWORD %1, %2, IMMEDIATE_BIT
76 DW DOCOL
77 %ENDMACRO
78
79
80 ;; Same as DEFWORD_THREADED but this time with raw code
81 %MACRO DEFWORD_RAW 2
82 DEFWORD %1, %2, 0
83 DW INTRAW ; Raw interpreter codeword
84
85 ;; Callable from assembly
86CODE_%1:
87 %ENDMACRO
88
89
90 %MACRO DEFWORD_RAW_IMMEDIATE 2
91 DEFWORD %1, %2, IMMEDIATE_BIT
92 DW INTRAW
93
94 ;; Callable from assembly
95CODE_%1:
96 %ENDMACRO
97
98
99 ;; DEFVAR name, 'name'
100 ;; dw 0
101 %MACRO DEFVAR 2
102 DEFWORD_RAW %1, %2
103 PUSH VAR_%1
104 NEXT
105
106VAR_%1:
107 %ENDMACRO
108
109 %MACRO DEFCONST 3
110 DEFWORD_RAW %1, %2
111 PUSH CONST_%1
112 NEXT
113 CONST_%1 EQU %3
114 %ENDMACRO
115
116
117 %MACRO INCLUDE_STRING 2
118 DW LITSTRING
119 DW STRINGLEN_%1
120.BEFORE_STRING_%1:
121 DB %2
122 STRINGLEN_%1 EQU $ - .BEFORE_STRING_%1
123 ALIGN WORDSZ
124 %ENDMACRO
125
126
127 ;; TODO: This doesn't work for some reason
128 %MACRO RELATIVE_ADDRESS 1
129 DW (%1 - $)
130 %ENDMACRO
131
132
133;;; PROGRAM CODE ;;;
134
135_START:
136 ;; Progran begins
137 MOV BP, SP
138 SUB BP, 1024 ; why can't I use SP as a base for
139 ; load effective address?
140 MOV SI, INDIRECT_START
141 NEXT
142
143 ALIGN 2
144
145
146 ;; DO COLon definition -- Codeword for indirect threaded code
147 ;; ax: indirect execution address
148DOCOL:
149 RSPUSH si
150 ADD AX, WORDSZ ; Point to the first word address
151 MOV SI, AX ; Enter the function body (set si)
152 NEXT
153
154
155 ;; Interpret raw code (plain machine code)
156INTRAW:
157 ADD AX, WORDSZ
158 JMP AX
159
160
161INDIRECT_START:
162 DW SETUP
163 DW QUIT
164 DW BYE
165
166
167SETUP:
168 DW INTRAW
169
170 MOV DX, MSG
171 WRITESOUT
172
173 NEXT
174
175LITERAL:
176 DW INTRAW
177
178 LODSW ; Load the next word
179 PUSH AX
180
181 NEXT
182
183
184EXIT:
185 DW INTRAW
186 RSPOP SI
187 NEXT
188
189TEST_PRINTING:
190 DW INTRAW
191 MOV AX, 5723
192 JMP DOT_INT
193
194
195 DEFWORD_RAW BYE, 'BYE'
196 FLUSH
197 QUIT_PROC
198
199
200 DEFWORD_RAW LIT, 'LIT'
201 LODSW ; Read next word from input to AX
202 PUSH AX
203 NEXT
204
205
206 DEFWORD_RAW DROP, 'DROP'
207 ADD SP, WORDSZ
208 NEXT
209
210
211 DEFWORD_RAW SWAP, 'SWAP'
212 POP AX
213 POP BX
214 PUSH AX
215 PUSH BX
216 NEXT
217
218
219 DEFWORD_RAW DUP, 'DUP'
220 ;; This is stupid, [SP] is invalid
221 POP AX
222 PUSH AX
223 PUSH AX
224 NEXT
225
226
227 DEFWORD_RAW PLUS, '+'
228 POP AX
229 POP BX
230 ADD AX, BX
231 PUSH AX
232 NEXT
233
234
235 DEFWORD_RAW MINUS, '-' ; ( DX AX -- DX-AX )
236 POP AX
237 POP DX
238 SUB DX, AX
239 PUSH DX
240 NEXT
241
242
243 DEFWORD_RAW ADD1, '1+'
244 POP AX
245 ADD AX, 1
246 PUSH AX
247 NEXT
248
249
250 DEFWORD_RAW ADD2, '2+'
251 POP AX
252 ADD AX, 2
253 PUSH AX
254 NEXT
255
256
257 ;; This kind of sucks
258 DEFWORD_RAW _2DUP, '2DUP' ; ( a b -- a b a b )
259 POP AX
260 POP BX
261 PUSH BX
262 PUSH AX
263 PUSH BX
264 PUSH AX
265 NEXT
266
267
268 %INCLUDE "IOWORDS.ASM"
269 %INCLUDE "DICTNRY.ASM"
270
271;;; LATE-INIT VARIABLES ;;;
272 DEFVAR STATE, 'STATE'
273 DW 0 ; Interpret
274
275 DEFVAR HERE, 'HERE'
276 DW HERE_START
277
278 ;; LATEST must be the last word defined in FORTH.ASM!
279 DEFVAR LATEST, 'LATEST'
280 DW LINK
281
282
283;;; PROGRAM DATA ;;;
284 MSG DB 'DOS FORTH', 0Dh, 0Ah, '$'
285
286
287;;; FREE DATA ;;;
288HERE_START: