-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathforth.dasm16
400 lines (325 loc) · 5.64 KB
/
forth.dasm16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
jmp start
; some kind of configuration
:dictionary_end
dat 0x0000
:return_stack_top
dat 0x0000
:return
dat return_stack_top
:screen
dat 0x8000
; data section here
:initial_stack
dat 0x0000
:prompt
dat "FORTH> ",0
:result
dat "0000000",0
:ok_msg
dat "Ok",0
:program
dat "8 dup * 256 swap / 1 1 7 print",0x20,0
:test1
dat "65534",0
:start
mov [return_stack_top], 0xb000 ; init return sp
mov [current_word], 0x9000 ; init memory buffer for string placement
mov [dictionary_end], [last_word] ; last word on boot
push program
callword(parse)
pop a
jmp exit
defword(parse, 0, parse)
jmp parse_begin
:string_to_parse
dat 0x0000
:current_pos
dat 0x0000
:current_word
dat 0x0000
:memory
dat 0x0000 ; buffer
:parse_begin
pop [string_to_parse]
mov [memory], 0x1800 ; buffer
mov x, [string_to_parse]
mov a, [current_word]
jmp parse_add_symbol
:parse_next_token ; init buffer
mov a, [current_word]
mov x, [string_to_parse]
mov x, [current_pos]
:parse_add_symbol
mov [a], [x]
add x, 1
add a, 1
ife [x],0 ; TEH END
jmp parse_exit
ifn [x],0x20 ; IF NOT SPACE
jmp parse_add_symbol
add x, 1
mov [current_pos], x ; WORKOUT
mov [a], 0
push [current_word]
callword(isnumber)
ife 1, pop ; that's NUMBER
jmp parse_num
:parse_word
push [current_word]
callword(searchForWord)
mov a, pop
call(a)
jmp parse_next_token
:parse_num
push [current_word]
callword(strtoint) ; digit is on stack
jmp parse_next_token
:parse_exit
next
defword(searchForWord, 0, searchForWord) ; ( n -- addr ) searches word in dictionary by name
jmp sfw_begin
:sfw_local_current_addr
dat 0x0000
:sfw_local_name_str
dat 0x0000
:sfw_local_name_len
dat 0x0000
:sfw_begin
mov j, 0xf000
mov [dictionary_end], [last_word]
mov [sfw_local_current_addr], [dictionary_end]
mov [sfw_local_name_str], pop
mov push, [sfw_local_name_str]
callword(upstr)
callword(strlen)
mov [sfw_local_name_len], pop ; name_length
:sfw_mainloop
mov b, [sfw_local_current_addr]
add b, 3
push b
callword(strlen)
mov a, pop
ifn [sfw_local_name_len], a
jmp nextword
push [sfw_local_name_str]
push b
callword(strcmp)
ife [sfw_local_name_len],pop
jmp sfw_found
:nextword
mov b, [sfw_local_current_addr] ; Load current name
add b, 3
ife [b], 0 ; 0 - dictionary start
jmp sfw_not_found ; exit
sub b, 1 ; switch to link
mov [sfw_local_current_addr], [b] ; load previous link
jmp sfw_mainloop
:sfw_found
mov a, [sfw_local_current_addr]
push a
jmp sfw_exit
:sfw_not_found
push 0
:sfw_exit
next
defword(dup, 0, dup)
set a, pop
set push, a
set push, a
next
defword(rot, 0, rot)
set a, pop
set b, pop
set c, pop
set push, b
set push, a
set push, c
next
defword(strcmp, 0, strcmp)
mov a, pop
mov b, pop
mov i, 0
:strcmp_loop
ifn [a],[b]
jmp strcmp_exit
add a, 1
add b, 1
add i, 1
ifn [a], 0
jmp strcmp_loop
:strcmp_exit
push i
next
defword(writeline, 0, writeline)
mov a, pop
mov i, 0
:__writeline_loop1
mov [0x8000+i], [a]
add i, 1
add a, 1
ifn [a], 0
jmp __writeline_loop1
next
defword(strlen, 0, strlen)
mov a, pop
mov i, 0
:__strlen_loop
ife [a], 0
jmp __strlen_exit
add i, 1
add a,1
jmp __strlen_loop
:__strlen_exit
set push, i
next
defword(inttostr, 0, inttostr) ; ( num str -- str )
mov a, pop
mov b, pop
mov z, b
mov x, a
mov y, 10000
jmp __next_digit_start
:__digit
add x, 48
mov [b],x
add b, 1
ret
:__next_digit
mov x, a
mod x, y
div y, 10
:__next_digit_start
div x, y
jsr __digit
ifg y, 1
jmp __next_digit
set push, z
next
defword(strtoint, 0, strtoint) ; ( num str -- str )
jmp strtoint_start
:strtoint_string
dat 0
:strtoint_digit
dat 0
:strtoint_result
dat 0
:strtoint_start
mov [strtoint_string], pop
push [strtoint_string]
callword(strlen)
mov z, pop
sub z, 1
mov a, [strtoint_string]
add a, z
mov b, [a]
sub b, 0x30
mov [strtoint_result], b
mov y, 1
:strtoint_next_digit
mul y, 10
sub z, 1
ife z, 0xffff
jmp strtoint_finished
mov a, [strtoint_string]
add a, z
mov b, [a]
sub b, 0x30
mul b, y
add [strtoint_result], b
jmp strtoint_next_digit
:strtoint_finished
push [strtoint_result]
next
defword(isnumber, 0, isnumber)
mov a, pop
mov i, 0
:isnumber_mainloop
ife [a], 0
jmp isnumber_success
ifg 0x30, [a]
jmp isnumber_fail
ifg [a], 0x39
jmp isnumber_fail
add a, 1
jmp isnumber_mainloop
:isnumber_fail
push 0xffff
jmp isnumber_finish
:isnumber_success
push 1
:isnumber_finish
next
defword(upstr, 0, upstr)
mov a, pop
mov z, a
jmp __upstr_begin
:__upstr_loop
add a, 1
:__upstr_begin
ife [a], 0
jmp __upstr_exit
ifg 0x60, [a]
jmp __upstr_loop
ifg [a], 0x7a
jmp __upstr_loop
sub [a], 0x20
jmp __upstr_loop
:__upstr_exit
set push, z
next
defword(+, 0, plus)
pop a
pop b
add a,b
push a
next
defword(-, 0, minus)
pop b
pop a
sub a,b
push a
next
defword(*, 0, multiply)
pop b
pop a
mul a,b
push a
next
defword(/, 0, divide)
pop b
pop a
div a,b
push a
next
defword(swap, 0, swap)
pop b
pop a
push b
push a
next
defword(print, 0, print)
set a, 0
set b, 0x8000
hwi 0
pop z
pop y
pop x
mul y, 32
add x, y
add x, 0x8000 ;0x800 is start of video RAM
:print_ploop
ife [z], 0 ;end of string?
set PC, print_finish ;then return
set [x], 0x2 ; Green
shl [x], 0x4
bor [x], 0x8 ; Gray
shl [x], 0x8
bor [x], [z]
add z, 1
add x, 1
set PC, print_ploop
:print_finish
next
:last_word
dat prev_word
:exit