-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathinterpreter_sub.asm
381 lines (381 loc) · 8.98 KB
/
interpreter_sub.asm
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
%ifndef _INTERPRETER_SUB_ASM_
%define _INTERPRETER_SUB_ASM_
; --- modules ---
%include "list32_sub.asm"
%include "list8_sub.asm"
%include "list16_sub.asm"
%include "str_sub.asm"
%include "print_sub.asm"
%include "console_sub.asm"
%include "commands/meta/var.asm"
%include "commands/meta/stack.asm"
%include "commands/meta/err.asm"
%include "commands/meta/compare.asm"
%include "commands/meta/command.asm"
%include "commands/meta/buffer.asm"
%include "commands/say.asm"
%include "commands/bye.asm"
%include "commands/set.asm"
%include "commands/push.asm"
%include "commands/pop.asm"
%include "commands/rst.asm"
%include "commands/lsb.asm"
%include "commands/=.asm"
%include "commands/stb.asm"
%include "commands/clb.asm"
%include "commands/run.asm"
%include "commands/jump.asm"
%include "commands/cmp.asm"
%include "commands/jse.asm"
%include "commands/jsne.asm"
%include "commands/jue.asm"
%include "commands/june.asm"
%include "commands/jug.asm"
%include "commands/juge.asm"
%include "commands/jul.asm"
%include "commands/jule.asm"
%include "commands/add.asm"
%include "commands/sub.asm"
%include "commands/mul.asm"
%include "commands/div.asm"
%include "commands/load.asm"
%include "commands/save.asm"
%include "commands/read.asm"
%include "commands/cls.asm"
; --- macros ---
%define NORMAL_COLOR (YELLOW)
%define STRING_COLOR (GREEN)
%define SYMBOL_COLOR (WHITE)
%macro INTERPRETER_INIT 0
BUFFER_INIT
%endmacro
; --- data ---
interpreter_data :
.marks :
; a list 32. each slot stores address to the begining of sub-string and the length
times 1 dw 0
times LIST32_MAX dd 0
.splitting_chars : ; characters that splits string into sub-strings (separator)
db " ", 0
.standalone_chars : ; character that is always alone
db "=", 0
.string_literal_chars : ; character that initiate or terminate strings
db 0x22, 0x27, 0x60, 0
.command_table :
; address to the command name and its corresponding function
dw @sayCommand_name, @sayCommand
dw @readCommand_name, @readCommand
dw @setCommand_name, @setCommand
dw @addCommand_name, @addCommand
dw @subCommand_name, @subCommand
dw @mulCommand_name, @mulCommand
dw @divCommand_name, @divCommand
dw @clearConsoleCommand_name, @clearConsoleCommand
dw @pushStackCommand_name, @pushStackCommand
dw @popStackCommand_name, @popStackCommand
dw @resetStackCommand_name, @resetStackCommand
dw @compareCommand_name, @compareCommand
dw @jumpStringEqualCommand_name, @jumpStringEqualCommand
dw @jumpStringNotEqualCommand_name, @jumpStringNotEqualCommand
dw @jumpUintEqualCommand_name, @jumpUintEqualCommand
dw @jumpUintNotEqualCommand_name, @jumpUintNotEqualCommand
dw @jumpUintLessCommand_name, @jumpUintLessCommand
dw @jumpUintLessEqualCommand_name, @jumpUintLessEqualCommand
dw @jumpUintGreaterCommand_name, @jumpUintGreaterCommand
dw @jumpUintGreaterEqualCommand_name, @jumpUintGreaterEqualCommand
dw @jumpCommand_name, @jumpCommand
dw @listBufferCommand_name, @listBufferCommand
dw @setRowCommand_name, @setRowCommand
dw @clearBufferCommand_name, @clearBufferCommand
dw @setActiveBufferCommand_name, @setActiveBufferCommand
dw @runBufferCommand_name, @runBufferCommand
dw @saveCommand_name, @saveCommand
dw @loadCommand_name, @loadCommand
dw @byeCommand_name, @byeCommand
dw 0
.invalid_command_error_c_string :
db "Invalid command.", 0
; --- subroutines ---
; print marks
interpreterPrintMarks :
pusha
mov si, interpreter_data.marks
LIST32_GET_COUNT ; cx = count of marks
add si, 2 ; si = begining of marks
PRINT_CHAR '['
.loop :
cmp cx, 0
je .loop_end
push cx
mov word cx, [si] ; cx = length of string
add si, 2
mov word bx, [si] ; bx = string
add si, 2
call printCStringing
pop cx
PRINT_CHAR ','
dec cx
jmp .loop
.loop_end :
PRINT_CHAR ']'
popa
ret
; execute command string
; si <- list 8
interpreterExecute :
call interpreterMark
call interpreterExecuteMark
ret
; execute command string
; si <- string
; cx <- length of string
interpreterExecuteString :
call interpreterMarkString
call interpreterExecuteMark
ret
; execute command from interpreter_data.marks
interpreterExecuteMark :
pusha
mov si, interpreter_data.marks
LIST32_GET_COUNT
cmp cx, 0
je .end ; No argument, just end it.
add si, 2
mov word cx, [si] ; cx = length of first argument
add si, 2
mov word bx, [si]
call varReadString ; accept variable referencing
mov si, bx ; si = address of first argument
mov bx, interpreter_data.command_table
.loop_command_table :
mov word di, [bx] ; di = command name from command table
cmp di, 0
je .invalid_command_err
; compare first token with command name
; si <- address of first argument [retained]
; cx <- length of first argument [retained]
; di <- command name
push si
push cx
.loop_cmp_command_char :
mov byte al, [di] ; al = current character of command name
cmp al, 0
je .cmp_command_length
cmp cx, 0
je .loop_end
mov byte ah, [si] ; ah = current character of first argument
cmp al, ah
jne .loop_end
inc di
inc si
dec cx
jmp .loop_cmp_command_char
.cmp_command_length :
cmp cx, 0
jne .loop_end
; First argument have the same length and same character sequence
; execute command function and end.
pop cx
pop si
add bx, 2
mov si, interpreter_data.marks
mov di, [bx]
pusha
call di ; call command
popa
jmp .end
.loop_end :
pop cx
pop si
add bx, 4
jmp .loop_command_table
.invalid_command_err :
; print error
mov bx, interpreter_data.invalid_command_error_c_string
call err.print ; jmping to label from other files : 0
.end :
popa
ret
; mark the subs-strings in the string given, output into interpreter_data.marks
; si <- string
; cx <- length of string
interpreterMarkString :
pusha
mov di, interpreter_data.marks
LIST32_INIT
mov bx, si ; bx = address of sub-string
xor dx, dx ; dx = length of sub-string
xor ah, ah ; ah = current string literal char
.loop :
cmp cx, 0
je .loop_end
mov al, [si] ; al = current character
cmp ah, 0
je .not_processing_string_literal
cmp ah, al
je .str_end
inc dx
jmp .skip_switch
.str_end :
push si
mov si, interpreter_data.marks
mov ax, bx
LIST32_APPEND dx, ax
pop si
add bx, dx
inc bx
xor ax, ax
xor dx, dx
jmp .skip_switch
.not_processing_string_literal :
push si ; >> BEGIN SWITCH <<
mov si, interpreter_data.splitting_chars
call cStringHasChar
jc .is_splitting_char
mov si, interpreter_data.standalone_chars
call cStringHasChar
jc .is_standalone_char
mov si, interpreter_data.string_literal_chars
call cStringHasChar
jc .is_string_literal_char
inc dx
jmp .switch_end
.is_splitting_char :
mov si, interpreter_data.marks
; write into marks
cmp dx, 0
je .empty_mark
push ax
mov ax, bx
LIST32_APPEND dx, ax
pop ax
; update state
.empty_mark :
add bx, dx
inc bx
xor dx, dx
jmp .switch_end
.is_standalone_char :
mov si, interpreter_data.marks
; write sub-string before standalone char into marks
cmp dx, 0
je .mark_standalone_char
push ax
mov ax, bx
LIST32_APPEND dx, ax
pop ax
; write the standalone char into marks
.mark_standalone_char :
add bx, dx
push ax
mov ax, bx
mov dx, 1
LIST32_APPEND dx, ax
pop ax
; update states
inc bx
xor dx, dx
jmp .switch_end
.is_string_literal_char :
mov si, interpreter_data.marks
; write sub-string before string literal char into marks
cmp dx, 0
je .start_string_literal
push ax
mov ax, bx
LIST32_APPEND dx, ax
pop ax
; set current string literal char
.start_string_literal :
push bx
mov bh, al
mov ah, bh
pop bx
; update states
add bx, dx
inc bx
xor dx, dx
jmp .switch_end
.switch_end :
clc ; clear flag set by cStringHasChar
pop si ; >> END SWITCH <<
.skip_switch :
dec cx
inc si
jmp .loop
.loop_end :
cmp ah, 0
jne .uncleaned_buffer
cmp dx, 0
je .cleaned_buffer
.uncleaned_buffer :
mov si, interpreter_data.marks
mov ax, bx
LIST32_APPEND dx, bx
.cleaned_buffer :
popa
ret
; mark the sub-strings in the list 8 given, output into interpreter_data.marks
; si <- list 8
interpreterMark :
pusha
LIST8_GET_COUNT ; cx = count of chars
add si, 2 ; si = begining of string
call interpreterMarkString
popa
ret
; paint the list 16 buffer
; si <- address of list 16 buffer
interpreterPaint :
pusha
LIST16_GET_COUNT ; cx = count
mov di, si
add di, 2 ; di = begining of buffer
xor bl, bl ; bl = current string literal char
.loop :
cmp cx, 0
je .loop_end
mov byte al, [di] ; al = current character
cmp bl, 0
je .not_processing_string_literal
cmp bl, al
jne .not_string_literal_end
xor bl, bl
.not_string_literal_end :
push di
inc di ; move to attribute
mov byte [di], STRING_COLOR
pop di
jmp .continue
.not_processing_string_literal :
push di ; >> BEGIN SWITCH <<
mov si, interpreter_data.standalone_chars
call cStringHasChar
jc .is_standalone_char
mov si, interpreter_data.string_literal_chars
call cStringHasChar
jc .is_string_literal_char
jmp .is_normal_char
.is_standalone_char :
inc di ; move to attribute
mov byte [di], SYMBOL_COLOR
jmp .switch_end
.is_string_literal_char :
mov bl, al
inc di ; move to attribute
mov byte [di], STRING_COLOR
jmp .switch_end
.is_normal_char :
inc di
mov byte [di], NORMAL_COLOR
.switch_end :
clc
pop di ; >> END SWITCH <<
.continue :
add di, 2
dec cx
jmp .loop
.loop_end :
popa
ret
%endif ; _INTERPRETER_SUB_ASM_