blob: cf3a726a60018180dbfab37b7cc3bb5bbc13229c [file] [log] [blame]
swissChilif7f1e2b2021-12-31 14:42:43 -08001;;; Assembly definitions of built-in Forth words
2;;; Assume this is included after all the relevant macros
3
4
5;;; INPUT & OUTPUT ROUTINES ;;;
6 ;; Read a key from the input. If STDIN is blank wait for a key
7 ;; press.
8 ;;
9 ;; TODO: Keep an internal buffer until RETURN is pressed, allow
10 ;; some line editing.
11 ;;
12 ;; Actually, that could be implemented in Forth for simplicity.
13 DEFWORD_RAW KEY, 'KEY'
14 CALL READ_KEY
15 PUSH AX
16 NEXT
17
18 ;; This routine returns the key in AL, but Forth wants it on the
19 ;; stack, so we have a helper function.
20READ_KEY:
swissChilif7f1e2b2021-12-31 14:42:43 -080021 ;; Check if line buffer is empty
22 READCIN
23 XOR AH, AH ; We don't care about the scan code
24 RET
25
26
27 %MACRO WHITESPACE 2
28 CMP %1, ' '
29 JE %2
30
31 CMP %1, 09h ; \t
32 JE %2
33
34 CMP %1, 0Ah ; \n
35 JE %2
36
37 CMP %1, 0Dh ; \r
38 JE %2
39 %ENDMACRO
40
41
42 ;; Read a word from the input, max 32 bytes. WORD is reserved in
43 ;; NASM sadly.
44 DEFWORD_RAW _WORD, 'WORD'
45READ_WORD:
46 MOV DI, WORD_BUFFER
47
48.START:
49 ;; First skip whitespace
50 CALL READ_KEY ; Char in AL
51
52 WHITESPACE AL, .START
53 CMP AL, '\'
54 JE .COMMENT
55
56.LOOP:
57 CMP AL, 'a'
58 JL .STORE
59 CMP AL, 'z'
60 JG .STORE
61
62 SUB AL, ('a' - 'A') ; To upper case
63
64.STORE:
65 STOSB ; Buffer char
66
67 CALL READ_KEY
68 WHITESPACE AL, .DONE
69 JMP .LOOP
70
71.COMMENT:
72 CALL READ_KEY
swissChilie4d2e282022-01-04 22:22:27 -080073 CMP AL, ASCII_NEWLINE
swissChilif7f1e2b2021-12-31 14:42:43 -080074 JE .START
swissChilie4d2e282022-01-04 22:22:27 -080075 CMP AL, ASCII_RETURN
76 JE .START
77
78 JMP .COMMENT
swissChilif7f1e2b2021-12-31 14:42:43 -080079
80.DONE:
81 SUB DI, WORD_BUFFER ; Length
82 PUSH WORD_BUFFER
83 PUSH DI
84
85 NEXT
86
87
swissChili7c626b92022-01-01 23:35:39 -080088 DEFWORD_RAW_IMMEDIATE LPAREN, '('
89.LOOP:
90 CALL READ_KEY
91 CMP AL, ')'
92 JNE .LOOP
93 NEXT
94
95
swissChilif7f1e2b2021-12-31 14:42:43 -080096 ;; ( string len -- num unparsed )
97 DEFWORD_RAW NUMBER, 'NUMBER'
98 POP DX ; Length
99 POP BX ; Index
100 ADD DX, BX ; End pointer
101 XOR AX, AX ; The number
102
103 XOR CX, CX ; CL - used for char
104
105.LOOP:
106 MOV CL, BYTE [BX]
107 CMP CL, '0'
108 JL .DONE
109 CMP CL, '9'
110 JG .DONE
111
112 SUB CL, '0'
113 MOV CH, 10 ; This needs to be reset each time
114 ; which is annoying
115 IMUL CH ; 8-bit IMUL operand means that the
116 ; result is just in AX, not extended
117 ; by DX. Perfect
118 XOR CH, CH
119 ADD AX, CX
120 INC BX
121 CMP BX, DX
122 JL .LOOP
123
124.DONE:
125 SUB DX, BX ; Number of chars unread
126 PUSH AX
127 PUSH DX
128 NEXT
129
130
131 ;; Emit a char from the stack
132 DEFWORD_RAW EMIT, 'EMIT'
133 POP DX
134 WRITECOUT
135 NEXT
136
137
138 DEFWORD_RAW CR, 'CR'
139 MOV DX, CRLF_MSG
140 WRITESOUT
141 NEXT
142
143
swissChilif8849dc2021-12-31 23:15:57 -0800144 DEFWORD_THREADED SPACE, 'SPACE'
145 DW LITERAL, ' ', EMIT, EXIT
146
147
swissChilif7f1e2b2021-12-31 14:42:43 -0800148 DEFWORD_RAW TYPE, 'TYPE'
149TYPE_STRING:
150 POP CX ; Length
151 POP BX ; Index
152 ADD CX, BX ; End pointer
153
154.LOOP:
155 MOV DL, BYTE [BX]
156 WRITECOUT
157
158 INC BX
159 CMP BX, CX
160 JNE .LOOP
161
162.DONE:
163 NEXT
164
165
166 ;; ( n -- )
167 DEFWORD_RAW DOT, '.'
168 POP AX ; The number
swissChili7c626b92022-01-01 23:35:39 -0800169 CALL DOT_INT
170 NEXT
swissChilif7f1e2b2021-12-31 14:42:43 -0800171
172DOT_INT:
173 TEST AX, AX
174 JNZ .START
175
176 MOV DX, '0'
177 WRITECOUT
swissChili7c626b92022-01-01 23:35:39 -0800178 RET
swissChilif7f1e2b2021-12-31 14:42:43 -0800179
180.START:
181 MOV BX, 10 ; The base
182
183 ;; TODO: BUG: Depending on this value there is a maximum number
184 ;; that this routine will format, which is weird. For the value of
185 ;; 7 it is 1280.
186 MOV CX, 7
187.LOOP:
188 XOR DX, DX
189 DIV BX ; AX = quotient; DX = remainder
190 PUSH DX
191
192 LOOP .LOOP
193
194 MOV CX, 7
195 XOR BX, BX ; At start
196.REVERSE:
197 POP DX
198 OR BL, DL
199 JZ .END
200
201 ADD DL, '0'
202 WRITECOUT
203
204.END:
205 LOOP .REVERSE
206
swissChili7c626b92022-01-01 23:35:39 -0800207 RET
208
209
swissChili94f1e762022-01-29 21:55:45 -0800210 ;; ( flags *start len -- handle )
swissChili7c626b92022-01-01 23:35:39 -0800211 DEFWORD_RAW OPEN_FILE_NAMED, 'OPEN-FILE-NAMED'
212 POP CX ; Length
213 POP BX ; Start
214 MOV DX, BX
215 ADD BX, CX
216 MOV BYTE [BX], 0
217 POP CX ; Flags
218 CREATF
219
220 MOV AX, CX ; Flags
221 OPENF
222
223 JC FILE_WRITE_ERROR
224 PUSH AX
225 NEXT
226
227FILE_WRITE_ERROR:
228 MOV DX, MSG_OPENF_FAILED
229 WRITESOUT
230 PUSH AX
231 NEXT
232
233
234 ;; ( flags -- handle )
235 DEFWORD_THREADED OPEN_FILE, 'OPEN-FILE'
236 DW _WORD ; ( flags *str len )
237 DW OPEN_FILE_NAMED
238 DW EXIT
239
240
241 DEFWORD_RAW CLOSE_FILE, 'CLOSE-FILE'
242 POP BX
243 CLOSEF
244 NEXT
245
246
247 ;; Write word to file
248 ;; ( cell handle -- )
249 DEFWORD_RAW FILE_COMMA, 'F,'
250 POP BX ; Handle
251 POP DX ; Data
252 MOV WORD [FILE_WRITE_BUFFER], DX
253 MOV DX, FILE_WRITE_BUFFER ; Address
254 MOV CX, 2 ; Length
255 WRITEF
256 JC FILE_WRITE_ERROR
257 NEXT
258
259
260 ;; ( byte handle -- )
261 DEFWORD_RAW FILE_CHAR_COMMA, 'FC,'
262 POP BX
263 POP DX
264 MOV BYTE [FILE_WRITE_BUFFER], DL
265 MOV DX, FILE_WRITE_BUFFER
266 MOV CX, 1
267 WRITEF
268 JC FILE_WRITE_ERROR
269 NEXT
270
271
272 ;; ( *start *end handle -- )
273 DEFWORD_RAW FILE_WRITE_RANGE, 'FWRITE-RANGE'
274 POP BX
275 POP CX ; End
276 POP DX
277 SUB CX, DX ; Get difference
278 WRITEF
swissChilif7f1e2b2021-12-31 14:42:43 -0800279 NEXT
280
281
282;;; DATA ;;;
283 CRLF_MSG DB ASCII_RETURN, ASCII_NEWLINE, '$'
swissChili7c626b92022-01-01 23:35:39 -0800284 MSG_OPENF_FAILED DB 'File error', ASCII_RETURN, ASCII_NEWLINE, '$'
swissChilif7f1e2b2021-12-31 14:42:43 -0800285
swissChili7c626b92022-01-01 23:35:39 -0800286 WORD_BUFFER TIMES 33 DB 0
287 FILE_WRITE_BUFFER DW 0
swissChilif7f1e2b2021-12-31 14:42:43 -0800288WORD_BUFFER_END: