blob: b9381373cbc64e792aa40e2380742c5999126935 [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
73 CMP AL, ASCII_RETURN
74 JNE .COMMENT
75 JE .START
76
77.DONE:
78 SUB DI, WORD_BUFFER ; Length
79 PUSH WORD_BUFFER
80 PUSH DI
81
82 NEXT
83
84
swissChili7c626b92022-01-01 23:35:39 -080085 DEFWORD_RAW_IMMEDIATE LPAREN, '('
86.LOOP:
87 CALL READ_KEY
88 CMP AL, ')'
89 JNE .LOOP
90 NEXT
91
92
swissChilif7f1e2b2021-12-31 14:42:43 -080093 ;; ( string len -- num unparsed )
94 DEFWORD_RAW NUMBER, 'NUMBER'
95 POP DX ; Length
96 POP BX ; Index
97 ADD DX, BX ; End pointer
98 XOR AX, AX ; The number
99
100 XOR CX, CX ; CL - used for char
101
102.LOOP:
103 MOV CL, BYTE [BX]
104 CMP CL, '0'
105 JL .DONE
106 CMP CL, '9'
107 JG .DONE
108
109 SUB CL, '0'
110 MOV CH, 10 ; This needs to be reset each time
111 ; which is annoying
112 IMUL CH ; 8-bit IMUL operand means that the
113 ; result is just in AX, not extended
114 ; by DX. Perfect
115 XOR CH, CH
116 ADD AX, CX
117 INC BX
118 CMP BX, DX
119 JL .LOOP
120
121.DONE:
122 SUB DX, BX ; Number of chars unread
123 PUSH AX
124 PUSH DX
125 NEXT
126
127
128 ;; Emit a char from the stack
129 DEFWORD_RAW EMIT, 'EMIT'
130 POP DX
131 WRITECOUT
132 NEXT
133
134
135 DEFWORD_RAW CR, 'CR'
136 MOV DX, CRLF_MSG
137 WRITESOUT
138 NEXT
139
140
swissChilif8849dc2021-12-31 23:15:57 -0800141 DEFWORD_THREADED SPACE, 'SPACE'
142 DW LITERAL, ' ', EMIT, EXIT
143
144
swissChilif7f1e2b2021-12-31 14:42:43 -0800145 DEFWORD_RAW TYPE, 'TYPE'
146TYPE_STRING:
147 POP CX ; Length
148 POP BX ; Index
149 ADD CX, BX ; End pointer
150
151.LOOP:
152 MOV DL, BYTE [BX]
153 WRITECOUT
154
155 INC BX
156 CMP BX, CX
157 JNE .LOOP
158
159.DONE:
160 NEXT
161
162
163 ;; ( n -- )
164 DEFWORD_RAW DOT, '.'
165 POP AX ; The number
swissChili7c626b92022-01-01 23:35:39 -0800166 CALL DOT_INT
167 NEXT
swissChilif7f1e2b2021-12-31 14:42:43 -0800168
169DOT_INT:
170 TEST AX, AX
171 JNZ .START
172
173 MOV DX, '0'
174 WRITECOUT
swissChili7c626b92022-01-01 23:35:39 -0800175 RET
swissChilif7f1e2b2021-12-31 14:42:43 -0800176
177.START:
178 MOV BX, 10 ; The base
179
180 ;; TODO: BUG: Depending on this value there is a maximum number
181 ;; that this routine will format, which is weird. For the value of
182 ;; 7 it is 1280.
183 MOV CX, 7
184.LOOP:
185 XOR DX, DX
186 DIV BX ; AX = quotient; DX = remainder
187 PUSH DX
188
189 LOOP .LOOP
190
191 MOV CX, 7
192 XOR BX, BX ; At start
193.REVERSE:
194 POP DX
195 OR BL, DL
196 JZ .END
197
198 ADD DL, '0'
199 WRITECOUT
200
201.END:
202 LOOP .REVERSE
203
swissChili7c626b92022-01-01 23:35:39 -0800204 RET
205
206
207 ;; ( flags *start len )
208 DEFWORD_RAW OPEN_FILE_NAMED, 'OPEN-FILE-NAMED'
209 POP CX ; Length
210 POP BX ; Start
211 MOV DX, BX
212 ADD BX, CX
213 MOV BYTE [BX], 0
214 POP CX ; Flags
215 CREATF
216
217 MOV AX, CX ; Flags
218 OPENF
219
220 JC FILE_WRITE_ERROR
221 PUSH AX
222 NEXT
223
224FILE_WRITE_ERROR:
225 MOV DX, MSG_OPENF_FAILED
226 WRITESOUT
227 PUSH AX
228 NEXT
229
230
231 ;; ( flags -- handle )
232 DEFWORD_THREADED OPEN_FILE, 'OPEN-FILE'
233 DW _WORD ; ( flags *str len )
234 DW OPEN_FILE_NAMED
235 DW EXIT
236
237
238 DEFWORD_RAW CLOSE_FILE, 'CLOSE-FILE'
239 POP BX
240 CLOSEF
241 NEXT
242
243
244 ;; Write word to file
245 ;; ( cell handle -- )
246 DEFWORD_RAW FILE_COMMA, 'F,'
247 POP BX ; Handle
248 POP DX ; Data
249 MOV WORD [FILE_WRITE_BUFFER], DX
250 MOV DX, FILE_WRITE_BUFFER ; Address
251 MOV CX, 2 ; Length
252 WRITEF
253 JC FILE_WRITE_ERROR
254 NEXT
255
256
257 ;; ( byte handle -- )
258 DEFWORD_RAW FILE_CHAR_COMMA, 'FC,'
259 POP BX
260 POP DX
261 MOV BYTE [FILE_WRITE_BUFFER], DL
262 MOV DX, FILE_WRITE_BUFFER
263 MOV CX, 1
264 WRITEF
265 JC FILE_WRITE_ERROR
266 NEXT
267
268
269 ;; ( *start *end handle -- )
270 DEFWORD_RAW FILE_WRITE_RANGE, 'FWRITE-RANGE'
271 POP BX
272 POP CX ; End
273 POP DX
274 SUB CX, DX ; Get difference
275 WRITEF
swissChilif7f1e2b2021-12-31 14:42:43 -0800276 NEXT
277
278
279;;; DATA ;;;
280 CRLF_MSG DB ASCII_RETURN, ASCII_NEWLINE, '$'
swissChili7c626b92022-01-01 23:35:39 -0800281 MSG_OPENF_FAILED DB 'File error', ASCII_RETURN, ASCII_NEWLINE, '$'
swissChilif7f1e2b2021-12-31 14:42:43 -0800282
swissChili7c626b92022-01-01 23:35:39 -0800283 WORD_BUFFER TIMES 33 DB 0
284 FILE_WRITE_BUFFER DW 0
swissChilif7f1e2b2021-12-31 14:42:43 -0800285WORD_BUFFER_END: