4
4
; by Oscar Toledo G.
5
5
; http://nanochess.org/
6
6
;
7
- ; (c) Copyright 2019 Oscar Toledo G.
7
+ ; (c) Copyright 2019-2020 Oscar Toledo G.
8
8
;
9
9
; Creation date: Jul/19/2019. 10pm to 12am.
10
10
; Revision date: Jul/20/2019. 10am to 2pm.
33
33
; Numbers (0-65535) can be entered and display as unsigned.
34
34
;
35
35
; To enter new program lines:
36
- ; 10 print "Hello, world !"
36
+ ; 10 print "Hello all !"
37
37
;
38
38
; To erase program lines:
39
39
; 10
40
40
;
41
41
; To test statements directly (interactive syntax):
42
- ; print "Hello, world !"
42
+ ; print "Hello all !"
43
43
;
44
44
; To erase the current program:
45
45
; new
76
76
; Expressions:
77
77
;
78
78
; The operators +, -, / and * are available with
79
- ; common precedence rules and signed operation.
79
+ ; common precedence rules and signed operation.
80
+ ; Integer-only arithmetic.
80
81
;
81
82
; You can also use parentheses:
82
83
;
83
84
; 5+6*(10/2)
84
85
;
85
- ; Variables and numbers can be used in expressions.
86
+ ; Variables and numbers can be used in expressions.
87
+ ;
88
+ ; The rnd function (without arguments) returns a
89
+ ; value between 0 and 255.
86
90
;
87
91
; Sample program (counting 1 to 10):
88
92
;
114
118
; 180 goto 120
115
119
; 190 print
116
120
; 200 i=i+1
117
- ; 210 if i-n-1 goto 30
121
+ ; 210 if i-n-1 goto 30
122
+ ;
123
+ ; Sample program of guessing the dice:
124
+ ;
125
+ ; 10 print "choose ";
126
+ ; 20 print "a number ";
127
+ ; 30 print "(1-6)"
128
+ ; 40 input a
129
+ ; 50 b=rnd
130
+ ; 60 b=b-b/6*6
131
+ ; 70 b=b+1
132
+ ; 80 if a-b goto 110
133
+ ; 90 print "good"
134
+ ; 100 goto 120
135
+ ; 110 print "miss"
136
+ ; 120 print b
118
137
;
119
138
120
139
cpu 8086
@@ -130,9 +149,11 @@ com_file: equ 0
130
149
%endif
131
150
132
151
vars: equ 0x7e00 ; Variables (multiple of 256)
133
- running: equ 0x7e7e ; Running status
134
- line: equ 0x7e80 ; Line input
135
- program: equ 0x7f00 ; Program address
152
+ line: equ 0x7e80 ; Line input
153
+
154
+ program: equ 0x8000 ; Program address
155
+ ; (notice optimizations dependent on this address)
156
+
136
157
stack: equ 0xff00 ; Stack address
137
158
max_line: equ 1000 ; First unavailable line number
138
159
max_length: equ 20 ; Maximum length of line
@@ -149,10 +170,10 @@ start:
149
170
pop ss
150
171
%endif
151
172
cld ; Clear Direction flag
152
- mov di , program ; Point to program
153
- mov al , 0x0d ; Fill with CR
154
- mov cx , max_size ; Max. program size
155
- rep stosb ; Initialize
173
+ mov di , program ; Point to program
174
+ f14: mov byte [ di ] ,0x0d ; Fill with Carriage Return (CR) character
175
+ inc di ; Until reaching maximum 64K (DI becomes zero)
176
+ jne f14
156
177
157
178
;
158
179
; Main loop
@@ -161,8 +182,6 @@ main_loop:
161
182
mov sp , stack ; Reinitialize stack pointer
162
183
mov ax , main_loop
163
184
push ax
164
- xor ax , ax ; Mark as interactive
165
- mov [ running ], ax
166
185
mov al , '>' ; Show prompt
167
186
call input_line ; Accept line
168
187
call input_number ; Get number
@@ -188,7 +207,8 @@ statement:
188
207
mov di , statements ; Point to statements list
189
208
f5: mov al ,[ di ] ; Read length of the string
190
209
inc di ; Avoid length byte
191
- and ax , 0x00ff ; Is it zero?
210
+ cbw ; Make AH zero
211
+ dec ax ; Is it zero?
192
212
je f4 ; Yes, jump
193
213
xchg ax , cx
194
214
push si ; Save current position
@@ -331,34 +351,46 @@ f24: cmp al,0x40 ; Variable?
331
351
jnc f25 ; Yes, jump
332
352
dec si ; Back one letter...
333
353
call input_number ; ...to read number
334
- jmp spaces ; Avoid spaces
335
-
336
- f25: call get_variable_2 ; Get variable address
354
+ jmp short spaces
355
+
356
+ f25: cmp al , 0x72
357
+ jne f22
358
+ cmp byte [ si ], 0x6e
359
+ jne f22
360
+ lodsw ; Advance SI by 2
361
+ in al , 0x40 ; Read timer counter 0
362
+ mov ah , 0
363
+ ret
364
+
365
+ f22: call get_variable_2 ; Get variable address
337
366
xchg ax , bx
338
367
mov ax ,[ bx ] ; Read
339
368
ret ; Return
340
369
341
370
;
342
- ; Get variable address
371
+ ; Get variable address.
372
+ ; Also avoid spaces.
343
373
;
344
374
get_variable:
345
375
lodsb ; Read source
346
376
get_variable_2:
347
377
and al , 0x1f ; 0x61-0x7a -> 0x01-0x1a
348
378
add al , al ; x 2 (each variable = word)
349
- mov ah , vars>> 8 ; Setup high-byte of address
379
+ mov ah , vars>> 8 ; Setup high-byte of address
380
+ dec si
350
381
;
351
- ; Avoid spaces
382
+ ; Avoid spaces after current character
352
383
;
353
- spaces:
354
- cmp byte [ si ], ' ' ; Space found?
355
- jne f22 ; No, return
384
+ spaces_2:
385
+ inc si
356
386
;
357
- ; Avoid spaces after current character
387
+ ; Avoid spaces
388
+ ; The interpreter depends on this routine not modifying AX
358
389
;
359
- spaces_2:
360
- inc si ; Advance to next character
361
- jmp spaces
390
+ spaces:
391
+ cmp byte [ si ], ' ' ; Space found?
392
+ je spaces_2 ; Yes, move one character ahead.
393
+ ret ; No, return.
362
394
363
395
;
364
396
; Output unsigned number
@@ -375,10 +407,11 @@ f26:
375
407
call f26 ; Yes, output left side
376
408
f8: pop ax
377
409
add al , '0' ; Output remainder as...
378
- jmp output ; ...ASCII digit
410
+ jmp short output ; ...ASCII digit
379
411
380
412
;
381
- ; Read number in input
413
+ ; Read number in input
414
+ ; Also avoid spaces afterwards.
382
415
; AX = result
383
416
;
384
417
input_number:
@@ -395,7 +428,6 @@ f11: lodsb ; Read source
395
428
jmp f11 ; Continue
396
429
397
430
f12: dec si ; SI points to first non-digit
398
- f22:
399
431
ret
400
432
401
433
;
@@ -419,33 +451,21 @@ run_statement:
419
451
xor ax , ax
420
452
f10:
421
453
call find_line ; Find line in program
422
- f27: cmp word [ running ], 0 ; Already running ?
423
- je f31
424
- mov [ running ], ax ; Yes, target is new line
454
+ f27: cmp sp , stack - 2 ; In interactive mode ?
455
+ je f31 ; Yes, jump.
456
+ mov [ stack - 4 ], ax ; No, replace the saved address of next line
425
457
ret
426
458
f31:
427
459
push ax
428
460
pop si
429
- add ax , max_length ; Point to next line
430
- mov [ running ], ax ; Save for next time
461
+ add ax , max_length ; Point to next line
462
+ push ax ; Save for next time (this goes into address stack-4)
431
463
call statement ; Process current statement
432
- mov ax ,[ running ]
464
+ pop ax ; Restore address of next line (could have changed)
433
465
cmp ax , program + max_size ; Reached the end?
434
466
jne f31 ; No, continue
435
467
ret ; Yes, return
436
468
437
- ;
438
- ; Find line in program
439
- ; Entry:
440
- ; ax = line number
441
- ; Result:
442
- ; ax = pointer to program
443
- find_line:
444
- mov cx , max_length
445
- mul cx
446
- add ax , program
447
- ret
448
-
449
469
;
450
470
; Input line from keyboard
451
471
; Entry:
484
504
cmp al , '" ' ; Double quotes?
485
505
je f18 ; Yes, jump
486
506
call output ; Output character
507
+ cmp al , 0x0d ;
487
508
jne f9 ; Jump if not finished with 0x0d (CR)
488
509
ret ; Return
489
510
@@ -520,7 +541,19 @@ f17:
520
541
mov ah , 0x0e
521
542
mov bx , 0x0007
522
543
int 0x10
523
- cmp al , 0x0d
544
+ ret
545
+
546
+ ;
547
+ ; Find line in program
548
+ ; Entry:
549
+ ; ax = line number
550
+ ; Result:
551
+ ; ax = pointer to program.
552
+ ; cx = max. length allowed for line.
553
+ find_line:
554
+ mov cx , max_length
555
+ mul cx
556
+ add ax , program
524
557
ret
525
558
526
559
;
@@ -530,31 +563,31 @@ f17:
530
563
; Then a word with the address of the code
531
564
;
532
565
statements:
533
- db 3 , "new"
566
+ db 4 , "new"
534
567
dw start
535
568
536
- db 4 , "list"
569
+ db 5 , "list"
537
570
dw list_statement
538
571
539
- db 3 , "run"
572
+ db 4 , "run"
540
573
dw run_statement
541
574
542
- db 5 , "print"
575
+ db 6 , "print"
543
576
dw print_statement
544
577
545
- db 5 , "input"
578
+ db 6 , "input"
546
579
dw input_statement
547
580
548
- db 2 , "if"
581
+ db 3 , "if"
549
582
dw if_statement
550
583
551
- db 4 , "goto"
584
+ db 5 , "goto"
552
585
dw goto_statement
553
586
554
- db 6 , "system"
587
+ db 7 , "system"
555
588
dw system_statement
556
-
557
- db 0
589
+
590
+ db 1
558
591
559
592
;
560
593
; Boot sector filler
0 commit comments