-
Notifications
You must be signed in to change notification settings - Fork 1
/
forth2.asm
1262 lines (994 loc) · 34.7 KB
/
forth2.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
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; A P-Code implementation of Forth
;
; Written by Chris Curl
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; In this implementation, the code starts at the beginning of the memory space, and the dictionary
; starts at the end. They grow towards each other.
;
; There are 2 stacks in this virtual machine: the data stack, and the return stack. EBP is the pointer for
; the data stack. The return stack is a counted array of DWORDs.
;
; A dictionary entry looks like this:
;
; Offset
; 00-03 dw Prev ; Address of previous entry: the current LAST.
; 04-07 dw XT ; Execution Token: the current HERE.
; 08-08 db Flags ; Flags ... see below.
; 09-09 db Count ; Name length, not including the count or the NULL delimiter
; 10-xx db(?) Name ; The word's name, NULL delimited
;
; Flags:
; Bit 0 (Flags AND 0x01) is the immediate flag. A ONE here means the word is immediate.
; Bit 1 (Flags AND 0x02) is the ready bit. A ONE here means the word is ready for use.
; Bit 2 (Flags AND 0x04) is not currently used.
; Bit 3 (Flags AND 0x08) is not currently used.
; Bit 4 (Flags AND 0x10) is the primitive bit. A ONE here means the word is machine code.
; Bit 5 (Flags AND 0x20) is not currently used.
; Bit 6 (Flags AND 0x40) is not currently used.
; Bit 7 (Flags AND 0x80) is the compile_only bit. A ONE here means the word is only for compile time (STATE=1).
;
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
include 'win32ax.inc'
; ------------------------------------------------------------------------------
; ------------------------------------------------------------------------------
; ------------------------------------------------------------------------------
section '.data' data readable writeable executable
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; Section 1 - Constants
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
oneKilo EQU 400h
oneMB EQU oneKilo * oneKilo
SIZE_DWORD EQU 4
SIZE_WORD EQU 2
SIZE_CHAR EQU 1
memorySize EQU oneKilo*16 ; The default memory size
; NB: the memory size can be changed as follows:
; This is done in the beginning of BootStrap.4th
; 1024 DUP * 32 * MEM_SIZE !
; restart!
inpBuf_SZ EQU 0100h ; the size of the input buffer
; For Dictionary entries
IMM_BIT EQU 01h
READY_BIT EQU 02h
x86_BIT EQU 10h
COMPILE_ONLY_BIT EQU 80h
NEXT_OFFSET EQU 0
XT_OFFSET EQU 4
FLAGS_OFFSET EQU 8
NAME_OFFSET EQU 9
ENTRY_OVERHEAD EQU 10
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; VM opcodes
; opcode 0 is unused
I_FETCH EQU 1
I_STORE EQU 2
I_LITERAL EQU 3
I_DUP EQU 4
I_SWAP EQU 5
I_DROP EQU 6
I_PICK EQU 7
I_ROT EQU 8
I_ONEPLUS EQU 9
I_PLUS EQU 10 ; 0Ah
I_MINUS EQU 11
I_MULT EQU 12 ; 0Ch
I_DIV EQU 13
I_EQ EQU 14 ; 0Eh
I_CALL EQU 15
I_LT EQU 16 ; 10h
I_GT EQU 17
I_TO_R EQU 18 ; 12h
I_R_FROM EQU 19
I_R_AT EQU 20 ; 14h
I_JMPZ EQU 21
I_LOOKUP EQU 22 ; 16h
I_X86 EQU 23
I_JMPNZ EQU 24 ; 18h
I_SLITERAL EQU 25
I_DEPTH EQU 26 ; 1ah
I_ONEMINUS EQU 27
I_AND EQU 28 ; 1ch
I_OR EQU 29
I_XOR EQU 30 ; 1eh
I_DIVMOD EQU 31
I_EMIT EQU 32 ; 20h
I_DICTP EQU 33
I_TWOTIMES EQU 34 ; 22h
I_TWODIV EQU 35
I_FOPEN EQU 36 ; 24h
I_FCLOSE EQU 37
I_FREAD EQU 38 ; 26h
I_FWRITE EQU 39
I_FGETC EQU 40 ; 28h
I_FETCH_8 EQU 41
I_STORE_8 EQU 42 ; 2ah
I_LITERAL_8 EQU 43
I_COMMA EQU 44 ; 2ch
I_COMMA_8 EQU 45
I_OVER EQU 46 ; 2eh
I_STRCMP EQU 47
I_STRCMPI EQU 48 ; 30h
I_CREATE EQU 49
I_WORD EQU 50 ; 32h
I_BRANCHF EQU 51
I_GOTO EQU 52 ; 34h
I_EXECUTE EQU 53
I_DOT EQU 54 ; 36h
; opcodes 55 -> 97 are unused
I_BREAK EQU 98 ; 62h
I_RETURN EQU 99 ; 63h
; opcodes 100 -> 255 are unused
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; Section 2 - Macros
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
include "./Forth-STC-Macros.inc"
; The stack pointer is EBP
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; Section 3 - Program data
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
.data
req_MEMSIZE dw memorySize
cur_MEMSIZE dw memorySize
; Each primitive is implemented as a procedure. A pointer the that routine is stored here.
primVectors dw 256 DUP (0)
welcome db "Hello, Chris.", 0
msgOK db " ", 0
msgPrompt db 13, 10, "ok. ", 0
cmdBye db 3, "bye", 0
cmdRestart db 8, "restart!", 0
resetOK db "restarted.", 0
msgBye db "Good bye.", 0
msgBad_PRE db "Sorry, I don't know '", 0
msgBad_POST db "'.", 0
msgMemOR db "Memory reference out of range.", 0
msgStackE db "Stack empty.", 0
msgRStackE db "Return stack empty.", 0
msgStackU db "Stack underflow.", 0
msgStackO db "Stack overflow.", 0
msgDivByZero db "Divide by zero.", 0
msgNoName db "Cannot create dictionary entry with no name.", 0
msgBadOP db "Invalid opcode encountered.", 0
msgNoMem db "Fatal error - memory allocation failed!", 0
msgBadMem db "Fatal error - memory addresses out of expected range!", 0
char2Num db "0123456789ABCDEF", 0
theMemory dw 0
bytesRead dw 0
hStdIn dw 0
hStdOut dw 0
SizeReadWrite dw 0
initialESPVal dw 0
var_Depth db 0
dStack dw 64 dup (0)
var_rDepth db 0
rStack dw 64 dup (0)
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; Section 4 - Variables for creating the built-in words
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; Section 5 - Code
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; .code
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; Section 6 - Primitives
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
;
; In this implementation:
;
; EBP is defined to be the stack pointer for the data stack.
; PUSH increments the pointer, and POP decrements it.
; EBX is the TOS, [EBP] is the second value on the stack.
;
; The return stack is implemented as an array of DWORDs.
;
; Both stacks have depth counters.
;
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
stackEmpty:
; mov edx, offset msgStackE
jmp doError
stackEmpty_end:
; ---------------------------------------------------------------------------------------------------------
stackUnderFlow: ; If we get here, the stack could be hosed ...
; mov edx, offset msgStackU
jmp doError
stackUnderFlow_end:
; ---------------------------------------------------------------------------------------------------------
stackOverFlow: ; If we get here, the stack could be hosed ...
; mov edx, offset msgStackO
jmp doError
stackOverFlow_end:
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
;
;
; FORTH PRIMITIVES
;
;
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
; FETCH (@) - this is the 32 bit version
fFETCH:
add ebx, the_Memory
mov ebx, [ebx]
ret
fFETCH_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
; FETCH_8 (C@)
fFETCH_8:
add ebx, the_Memory
mov ebx, [ebx]
and ebx, 0x000000FF
ret
fFETCH_8_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
; STORE (!) - this is the 32 bit version
fSTORE:
m_pop edx
m_pop eax
add edx, the_Memory
mov [edx], eax
ret
fSTORE_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
; fSTORE_8 (C!)
fSTORE_8:
m_pop edx
m_pop eax
add edx, the_Memory
mov [edx], al
ret
fSTORE_8_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fLITERAL:
mov edx, [esi]
m_push edx
add esi, SIZE_DWORD
ret
fLITERAL_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fLITERAL_8:
xor edx, edx
mov dl,[esi]
m_push edx
inc esi
ret
fLITERAL_8_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fDUP:
m_push ebx
ret
fDUP_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fSWAP:
m_get2ND eax
m_set2ND ebx
m_setTOS eax
ret
fSWAP_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fPICK:
m_pop edx
shl edx, 2
mov eax, ebp
add eax, edx
cmp eax, dStack_MAX
jg stackUnderFlow
mov eax, [eax]
m_push eax
ret
fPICK_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fROT:
m_pop eax
m_pop ecx
m_pop edx
m_push ecx
m_push eax
m_push edx
ret
fROT_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fONEPLUS:
inc ebx
ret
fONEPLUS_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fONEMINUS:
dec ebx
ret
fONEMINUS_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fPLUS:
m_pop eax
add ebx, eax
ret
fPLUS_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fMINUS:
m_pop eax
sub ebx, eax
ret
fMINUS_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fMULT:
m_pop ecx
m_getTOS eax
mul ecx
m_setTOS eax
ret
fMULT_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
; /MOD - return quotient and remainder of division
; ( dv dd -- rem quot )
f_DIVMOD:
m_pop ecx ; Dividend
m_pop eax ; Divisor
cmp ecx, 0
je divByZero
xor edx, edx ; DIV uses EDX and EAX
jns doDiv
dec edx
doDiv: div ecx ; EAX gets quotient, EDX gets remainder
m_push edx
m_push eax
ret
divByZero:
; mov edx, offset msgDivByZero
m_drop
jmp doError
f_DIV_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fEQ:
m_pop eax
cmp ebx, eax
je fEQ_T
; fall through to false
fEQ_F:
m_setTOS 0
ret
fEQ_T:
m_setTOS -1
ret
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fLT:
m_pop eax
cmp ebx, eax
jl fEQ_T
jmp fEQ_F
fLT_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fGT:
m_pop eax
cmp ebx, eax
jg fEQ_T
jmp fEQ_F
fGT_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fCALL:
mov edx, [esi]
add edx, the_Memory
add esi, SIZE_DWORD
sub esi, the_Memory
m_rpush esi
mov esi, edx ; Put the current IP (ESI) on the return stack
ret
fCALL_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fTO_R:
m_rpush ebx
m_drop
ret
fTO_R_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fR_FROM:
m_rpop eax
m_push eax
ret
fR_FROM_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fR_AT:
m_rpop eax
m_rpush eax
m_push eax
ret
fR_AT_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fJMPZ:
m_pop eax
cmp eax, 0
je jmp_T
jmp jmp_F
jmp_T:
mov esi, [esi] ; The address here is an absolute 32 bit address
add esi, the_Memory
ret
jmp_F:
add esi, 4 ; Move the IP
ret
fJMPZ_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fJMPNZ:
m_pop eax
cmp eax, 0
jne jmp_T
jmp jmp_F
fJMPNZ_end:
; ---------------------------------------------------------------------------------------------------------
fSLITERAL:
m_push esi
xor eax, eax
lodsb
add esi, eax
mov al, [esi] ; the string may be NULL terminated
if (al == 0)
inc esi
end if
ret
fSLITERAL_end:
; ---------------------------------------------------------------------------------------------------------
fX86:
mov ecx, [esi]
add esi, SIZE_DWORD
jmp ecx
fX86_end:
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
fDEPTH:
m_push var_Depth
ret
fDEPTH_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
f22:
ret
f22_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
f23:
ret
f23_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
f24:
ret
f24_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
f25:
ret
f25_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fAND:
m_pop eax
and ebx, eax
ret
fAND_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
f_OR:
m_pop eax
or ebx, eax
ret
f_OR_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fXOR:
m_pop eax
xor ebx, eax
ret
fXOR_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fEMIT:
m_pop eax
mov edx, hStdOut
call WriteChar
ret
fEMIT_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fDICTP:
add esi, SIZE_DWORD
ret
fDICTP_end:
; ---------------------------------------------------------------------------------------------------------
fTwoTimes:
shl ebx, 1
ret
fTwoTimes_end:
; ---------------------------------------------------------------------------------------------------------
fTwoDiv:
shr ebx, 1
ret
fTwoDiv_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fSPUSH: ; string push (append char) ( c addr -- )
; push edi
; call fPop ; get string offset (relative to theMemory)
; push eax ; remember it
; call fPop ; get the byte from the dataStack
; pop edx ;
; vmToAbsolute edi, edx ; resolve string actual location
; call stkPush_8 ; append the byte
; pop edi
ret
fSPUSH_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fSPOP: ; string pop (remove last char) ( addr -- c )
; push edi
; call fPop ; get string offset (relative to theMemory)
; vmToAbsolute edi, eax ; resolve string actual location
; call stkPop_8 ; get the character (decrements string length)
; call fPush ; put the char on the dataStack
; pop edi
ret
fSPOP_end:
; ---------------------------------------------------------------------------------------------------------
fFOPEN proc
m_pop eax
m_pop edx
m_pop ecx
invoke CreateFile, eax, GENERIC_READ or GENERIC_WRITE, \
FILE_SHARE_READ or FILE_SHARE_WRITE, \
NULL, 4, FILE_ATTRIBUTE_NORMAL, \
NULL
m_push eax
call GetLastError
ret
fFOPEN_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fFCLOSE:
m_pop edx
invoke CloseHandle, edx
ret
fFCLOSE_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fFREAD:
; ( addr count hFile -- numRead )
; invoke ReadFile,hFile,pMemory,MEMSIZE-1,ADDR SizeReadWrite,NULL
push ebx
m_pop eax
m_pop ecx
m_pop edx
; mov ebx, offset SizeReadWrite
invoke ReadFile, eax, edx, ecx, offset SizeReadWrite, NULL
mov eax, SizeReadWrite
m_push eax
pop ebx
ret
fFREAD_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fFWRITE:
; invoke WriteFile,hFile,pMemory,eax,ADDR SizeReadWrite,NULL
ret
fFWRITE_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fFGETC:
ret
fFGETC_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fOVER:
m_pop ebx
m_getTOS eax
m_push ebx
m_push eax
ret
fOVER_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fSTRCMP:
push esi
push ecx
push ebx
push edi
m_pop esi
m_pop edi
call strCmpC
m_push eax
pop edi
pop ebx
pop ecx
pop esi
ret
fSTRCMP_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fSTRCMPi:
push esi
push ecx
push ebx
push edi
m_pop esi
m_pop edi
call strCmpCi
m_push eax
pop edi
pop ebx
pop ecx
pop esi
ret
fSTRCMPI_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
fBREAK:
;mov edx, offset var_dStack
ret
fBREAK_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fBRANCHF: ; Branch forward relative
mov esi, [esi]
ret
fBRANCHF_end:
; ---------------------------------------------------------------------------------------------------------
; ** NOT TESTED **
fGOTO: ; Branch backward
mov esi, [esi]
ret
fGOTO_end:
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; Section 7 - Helpers
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------------------------------
; Case sensitive counted string compare - string 1 in [EDI], string 2 in [ESI]
; First db is the count
; Returns edx = 0 if not the same
strCmpC:
xor ecx, ecx
mov cl, [edi] ; max is 255 chars
inc ecx ; include the count byte
; inc ecx ; include the NULL terminator
L1:
mov dl, [esi] ; get a character from source
cmp dl, [edi] ; compare it to the target
jne notEqual
inc esi ; move to next character
inc edi
loop L1 ; repeat for entire string
mov edx, 1
ret
notEqual:
xor edx, edx
ret
strCmpC_end:
; ---------------------------------------------------------------------------------------------------------
tolower:
cmp dl, 'A'
jl allDone
cmp dl, 'Z'
jg allDone
add dl, 32
allDone: ret
tolower_end:
; ---------------------------------------------------------------------------------------------------------
; ** TESTED **
; Case insensitive counted string compare - string 1 in [EDI], string 2 in [ESI]
; First db is the count
; Returns EAX = 1 if the same, else EAX = 0
strCmpCi:
xor eax, eax
xor ecx, ecx
mov cl, [edi] ; max is 255 chars
inc ecx ; include the count byte
; inc ecx ; We are NOT including the NULL terminator
L1: mov dl, [esi] ; get a character from source
call tolower
mov al, dl
mov dl, [edi] ; compare it to the target
call toLower
cmp al, dl
jnz notEqual
inc esi ; move to next characters
inc edi
loop L1 ; repeat for entire string
mov eax, 1
ret
notEqual: xor eax, eax
ret
strCmpCi_end:
; ---------------------------------------------------------------------------------------------------------
; Copies counted strings - source string in [ESI], destination string in [EDI]
; First db is the count
strCpyC:
push ecx
xor ecx, ecx
mov cl, [esi]
add ecx, 2 ; include the count and trailing null
cld ; make sure the direction flag is correct
rep movsb
pop ecx
ret
strCpyC_end: