-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathBAS2BC.ASM
More file actions
1266 lines (1052 loc) · 37.7 KB
/
BAS2BC.ASM
File metadata and controls
1266 lines (1052 loc) · 37.7 KB
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
page
page 60,132
title BAS2BC - Basic naar Basicode converter
;--------------------------------------------:
; BAS2BC :
; Een programma van Jac Goudsmit :
; :
; JG 250288 / :
;--------------------------------------------:
; Dit programma vertaalt een BASIC ASCII file naar Basicode.
; Met "BASICODE file" bedoel ik een programma in BASICODE-
; formaat, dat als DOS-file is opgeslagen.
; VERSPREIDING
; Dit programma mag vrij gekopieerd worden, onder de volgende
; voorwaarden:
; - Kopieen moeten gratis zijn (m.a.w. een kopie mag niet meer
; kosten dan de lege diskette)
; - Wijzigingen die door anderen dan de schrijver zijn aange-
; bracht, moeten duidelijk aangegeven worden;
; bijvoorbeeld kan dan de tekst in de .COM file
; gewijzigd worden in 'Door Jac Goudsmit. datum ... wijzigingen
; door Mr. X dd. ...'
; - De naam van de schrijver moet vermeld worden in de
; geassembleerde file (.COM file) (eventueel met toevoeging
; van schrijvers van wijzigingen)
;--------------------------------------------:
; Algemene voorbereiding MASM :
;--------------------------------------------:
.radix 16
Code segment
assume cs:Code,ds:Code,es:Code
;--------------------------------------------:
; Programma-begin :
;--------------------------------------------:
org 6C
Drive2 label byte ; drive wordt gebruikt voor 2e parm
org 80
ParmLen label byte
org 81
Parms label byte
;--------------------------------------------:
; Buffers e.d. :
;--------------------------------------------:
org 101 ; org 101 omdat [Buffer-1] geen CR mag zijn.
; (ivm leesroutine)
Buffer label byte
org 100
Begin: jmp Main ; Entry point van COM file.
; De volgende tekst wordt afgedrukt als je een TYPE op BAS2BC.COM
; probeert. Een goede gewoonte! Vergeet het EOF karakter (1A) niet.
db 0Dh,'IBM PC BASIC naar Basicode converter.',0Dh,0A
db 'Door Jac Goudsmit. V1.00. Datum 25 feb 1988.',0Dh,0A,1A
; De volgende foutmeldingen worden alleen gegeven als de eigenlijke
; verwerking nog niet begonnen is. Daarom kunnen ze in het buffer-
; gebied liggen.
ParmMsg db 'Fout in parameters. Syntax is:',0Dh,0A,0A
db ' BAS2BC source [dest] [/R|/N]',0Dh,0A,0A
db 'Als de doelfile dezelfde naam heeft als de bronfile, geef dan'
db ' geen DEST op.',0Dh,0A
db 'Geef /R om de regels tot 1000 NIET te verwijderen;',0Dh,0A
db 'Geef /N om geen regelnummers op het scherm te zetten.',0Dh,0A,24
DOSMsg db 'Foute DOS versie. (Moet 3.00 of hoger zijn.)',0Dh,0A,24
; Deze tabel bevat de mogelijke slash-parameters
; Om het makkelijk te maken zijn er voor elke parameter twee
; mogelijkheden in de tabel: upper case en lower case.
ParmTbl db 'RrNn'
AantPmM equ $-ParmTbl ; aantal Parameter-mogelijkheden
; Constanten
BufLen equ 256d ; I/O buffer lengte. Van invloed op snelheid
IntLen equ 65d ; max. lengte van een BC regel in de int.buffer
OutLen equ 65d ; max. lengte van een BC regel in de uit.buffer
; De volgende berekening wordt gedaan omdat de assembler (V1.00)
; de term BUFFER+BUFLEN-$ DUP (?) niet blijkt te pikken.
BufEnd equ Buffer+BufLen
; Buffer opvullen.
if BufEnd GT $
db BufEnd-$ dup (?)
endif
; Intermediate buffer - houdt BC regel vast nadat spaties verwijderd
; zijn.
IntBuf db IntLen dup (?)
; Output buffer - houdt BC regel vast waar spaties weer ingevoegd
; zijn. Wordt initieel gevuld met '1000 ' omdat deze tekst weggelezen
; wordt als SParm niet 0 is
OutBuf db '1000 '
InitOLen equ $-OutBuf
db (OutLen-InitOLen) dup(?)
; De volgende buffers bevatten filenamen als het programma draait.
; Ze worden met 0 opgevuld omdat een ASCIIZ filenaam ook altijd
; eindigt met 0
TMPNaam db 15d dup (0) ; Bevat ASCIIZ naam van Temp. file (geen path)
DestNaam db 40 dup (0) ; Bevat ASCIIZ naam van Destination file
;--------------------------------------------:
; Data :
;--------------------------------------------:
; Enige foutmeldingen die ook tijdens of na het programma kunnen op-
; treden. Deze kunnen dus niet naar het buffer-gebied verplaatst
; worden.
; Deze wordt afgedrukt als DOS na een INT 21 File I/O funktie
; een foutmelding geeft. Om het niet te ingewikkeld te maken
; heb ik maar een foutmelding voor het hele scala van DOS fouten.
IOMsg db 'File I/O fout. Programma afgebroken.'
; De hierna volgende Carriage Return, Line Feed wordt na bovenstaande
; foutmelding afgedrukt, maar kan ook los afgedrukt worden.
CRLF db 0Dh,0A,24
; Deze foutmelding wordt afgedrukt als er bijvoorbeeld een te lange
; regel wordt gedetecteerd.
FileMsg db 'WAARSCHUWING:',0Dh,0A
db 'Source-file waarschijnlijk geen BASICODE programma.',0Dh,0A,24
; Deze foutmelding wordt afgedrukt als de source file niet als ASCII
; file opgeslagen is
BinMsg db 'Programma is niet opgeslagen als ASCII bestand. BAS2BC '
db 'afgebroken.',0Dh,0A,24
; Zolang BAS2BC naar regel 1000 zoekt, staat de volgende tekst op
; het scherm:
Msg1000 db '----',0Dh,24
SourceF dw 0 ; File handle van source file (0=ongeopend)
DestF dw 0 ; File handle van Temporary file (0=ongeopend)
EOFFlag db 0 ; End of file flag; wordt 1 als laatste regel
; is ingelezen.
BCFlag db 1 ; wordt gereset als regel te lang is o.i.d.
EOFOfs dw BufLen ; Offset van file-einde in Buffer
InOfs dw BufLen ; Offset van eerste ongebruikte byte in Buffer
OutWLen dw InitOLen ; Aantal bytes in Output Buffer (schrijven)
; initiele waarde geldt voor de CHAIN regel
IntWLen dw 0 ; Aantal bytes in Intermediate Buffer (BC)
IntOfs dw 0 ; Lees-offset in intermediate buffer
Qmode db 0 ; Quote gevonden - geen spaties verwijderen en
; geen keywords detecteren.
Dmode db 0 ; DATA of REM gevonden - rest van regel negeren
; In pass 1:
; 1=gevonden - geen spaties verwijderen
; 3=zojuist gevonden, eventueel eerste spatie
; verwijderen.
ParmSet label byte ; tabel met flags van slash-parameters.
SParm db 0 ; /R = Source ook weergeven op scherm
NParm db 0 ; /N = Niets weergeven (tenzij /R gegeven)
;--------------------------------------------:
; tabellen :
;--------------------------------------------:
; we beginnen met keywords waar andere keywords in zitten:
Keywords db 4,'GOTO',3,'FOR',7,'RESTORE',4,'STOP',3
; vervolgens de keywords REM en DATA (buitenbeentjes)
REM db 'REM',4
DATA db 'DATA',2
; dit zijn de significante keywords:
Sign_KW db 'TO',4,'THEN',4,'STEP',3,'AND',2,'OR',3,'NOT',0
; test-tekst: wordt gebruikt bij weghalen van regels t/m 999
R1000 db 0,'1000 ' ; 0 wordt vervangen door 0Dh
R1000L equ $-R1000
;--------------------------------------------:
; Lage-niveau routines :
; (Oftewel Sub-subroutines) :
;--------------------------------------------:
;
; In deze routines worden alle registers bewaard, tenzij anders
; aangegeven.
;
ClosAl proc near
;
; Sluit eventueel files.
;
push ax
push bx
push dx
; Source file geopend? dan sluiten
cmp SourceF,0
je OK8
mov bx,SourceF
mov ah,3E
int 21 ; close file
; Temporary file geopend? dan eerst sluiten, daarna verwijderen
OK8: cmp DestF,0
je OK9
mov bx,DestF
mov ah,3E
int 21
mov dx,offset TMPNaam
mov ah,41 ; delete (temporary) file
int 21
pop dx
pop bx
pop ax
ret
ClosAl endp
Error proc near
;
; Sluit eventueel files, drukt tekst vanaf [DX] af en stopt programma
;
; Deze routine aanroepen met een JMP instructie.
;
push dx
call ClosAl
; Boodschap afdrukken
OK9: mov dx,offset CRLF ; Eerst Cr,Lf printen
mov ah,9
int 21
pop dx
mov ah,9
int 21
; einde programma
int 20
Error endp
Break proc far
;
; Deze routine handelt Ctrl-Break af. Als deze combinatie wordt ge-
; drukt tijdens het programma, worden de files gesloten en het pro-
; gramma afgebroken.
;
push ds
push cs
pop ds
call ClosAl
pop ds
stc ; Breek programma af - zie DOS tech ref
ret
Break endp
ParmErr proc near
;
; Fout in parameters. Aanroepen met JMP
;
mov dx,offset ParmMsg
jmp Error
ParmErr endp
IOErr proc near
;
; DOS fout. Aanroepen met JMP
;
mov dx,offset IOMsg
jmp Error
IOErr endp
FileErr proc near
;
; Wordt gegenereerd als de Source-file geen Basicode programma
; blijkt te zijn. Aanroepen met JMP
;
mov dx,offset FileMsg
jmp Error
FileErr endp
DosErr proc near
;
; Foute DOS versie. Aanroepen met JMP
;
mov dx,offset DosMsg
jmp Error
DosErr endp
ReadBlok proc near
;
; Leest een blok in de Buffer vanuit de Source file.
; Het niet gebruikte gedeelte van de buffer wordt naar het begin
; van de buffer geschoven. De offset van het eerste ongebruikte byte
; staat in InOfs.
; Als het einde van de file (de staart) zich al in de buffer bevindt,
; dan zal EOFOfs de eerste positie na het einde bevatten.
; Met andere woorden: als EOFOfs=0, dan is de file helemaal verwerkt
; en kan EOFFlag op 1 gezet worden.
; Na afloop wordt InOfs bijgewerkt.
; Gaat er iets mis, dan gebeurt er een I/O error.
;
push ax
push bx
push cx
push dx
push si
push di
; Verplaats eventueel ongebruikte deel van de buffer
mov cx,BufLen ; bereken aantal te verplaatsen bytes
sub cx,InOfs
jcxz OK12 ; is nul? dan niets verplaatsen.
mov di,offset Buffer ; verplaats naar begin van buffer
mov si,di
add si,InOfs ; van [Buffer+InOfs]
mov ax,si
sub ax,di
push ax
push cx
rep movsb ; Doe verplaatsing
pop cx ; recover aantal verplaatste bytes
pop ax
; bereken offset voor en lengte van het in te lezen stuk file.
; Op de plaats van het eerste in te lezen byte wordt van tevoren
; een Carriage Return gezet. Als het einde van de file nog niet
; is bereikt, dan wordt deze dus overgeschreven, maar anders
; wordt de actie onmiddellijk afgebroken door die CR,
; aangezien het halve programma daar steeds op controleert.
OK12: mov InOfs,cx ; Sla aantal verplaatste bytes even op.
mov dx,cx
add dx,offset Buffer
mov bx,dx
mov byte ptr [bx],0Dh
mov cx,BufLen
sub cx,InOfs ; aantal bytes inlezen=BufLen-InOfs
; Moeten we eigenlijk wel inlezen uit de file? of hoeven we alleen
; EOFOfs te veranderen?
cmp EOFOfs,Buflen
je OK12A
sub EOFOfs,ax
mov ax,cx ; zodat hieronder altijd naar OK14 wordt ge-
jmp short OK13 ; sprongen
; Inlezen uit file
OK12A: push dx
mov bx,Sourcef
mov ah,3F
int 21 ; read file
pop dx
jnc OK13
jmp IOErr
; Als de staart de buffer inloopt, wordt EOFOfs goed gezet
OK13: mov InOfs,0
cmp ax,cx
je OK14 ; springt altijd als staart al in de Buffer zit
add dx,ax ; Dit wordt dus alleen uitgevoerd als de staart
sub dx,offset Buffer ; de EERSTE KEER in de buffer zit.
mov EOFOfs,dx
; Eventueel EOFFlag setten.
OK14: cmp EOFOfs,0
jne OK14A
mov EOFFlag,1
; Einde.
OK14A: pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
ReadBlok endp
WritBlok proc near
;
; Schrijf Output Buffer weg naar Destination file.
; Uitgegaan wordt van de lengte aangegeven in OutWLen.
; Na afloop wordt deze op 0 gezet. Gaat er iets mis, dan gebeurt er
; een I/O fout.
;
push ax
push bx
push cx
push dx
; Zet registers goed en schrijf weg
mov bx,DestF
mov dx,offset OutBuf
mov cx,OutWLen
xor ax,ax ; voor controle als cx=0
cmp cx,0
je OK15
mov ah,40 ; write file
int 21
jnc OK15
OK16: jmp IOErr
OK15: cmp ax,cx ; aantal weggeschreven bytes OK?
jne OK16
mov OutWLen,0
; Einde.
pop dx
pop cx
pop bx
pop ax
ret
WritBlok endp
ReadByte proc near
;
; Leest een byte uit de source file. Eerst wordt geprobeerd een byte
; uit de buffer te lezen. Als het vorige karakter een CR was,
; dan wordt een nieuw blok ingelezen.
; Als er geen CR werd gevonden, dan wordt CY op 1 gezet, en wordt
; BCFlag op 0 gezet.
;
push bx
; Zitten er nog bytes in de buffer? Als de buffer leeggelezen is,
; dan is dit blijkbaar geen geldig programma en wordt dus BCFlag
; gereset. Ook wordt dan de CF geset, om aan te geven dat er iets
; niet klopt. De aanroeper moet de rest dan maar zelf uitzoeken.
mov bx,InOfs
cmp bx,BufLen
jb OK17
stc
and BCFlag,0 ; reset validity flag
jmp short OK18
; Einde van de file (zonder EOF karakter)?
OK17: cmp bx,EofOfs
jb OK17A
mov al,26d
jmp OK20
; Er zitten nog bytes in de buffer - inlezen.
OK17A: mov al,[bx+Buffer]
and al,7F
; De teller die aangeeft waar het volgende byte moet worden gelezen,
; wordt opgehoogd.
inc bx
mov InOfs,bx
; Lees een nieuw blok in aan het einde van een regel
cmp al,13d ; CR? dan blok inlezen
jne OK20
call ReadBlok
jmp short OK22
; Als het ingelezen byte een EOF karakter is, dan was dit het laatste
; karakter van de file. Dat MOET wel een CR zijn (zie ook ReadBlok)
; en wordt dus vervangen.
OK20: cmp al,26d ; EOF? dan vervangen door CR
jne OK22
mov al,13d
mov EofFlag,1
OK22: clc
; Einde.
OK18: pop bx
jc OK18A
cmp al,10d ; negeer LF
je Readbyte
OK18A: ret
ReadByte endp
WriteScr proc near
;
; Schrijft een karakter naar het scherm
;
cmp al,1A ; EOF-karakter wordt een pijltje
je GeenScr ; en dat wil ik niet
push dx
push ax
mov dl,al
mov ah,2
int 21
pop ax
pop dx
GeenScr: ret
WriteScr endp
WritByte proc near
;
; Schrijft het byte in AL weg in de Output buffer.
; Was het een CR of is de buffer vol, dan wordt de inhoud
; weggeschreven.
;
push ax
; Buffer vol? zo ja, dan wegschrijven.
cmp OutWLen,OutLen
jb OK24
call WritBlok
; zet byte in buffer
OK24: push bx
mov bx,OutWLen
mov [bx+OutBuf],al
OK24A: pop bx
inc OutWLen
; Ook wegschrijven na een CR
cmp al,0Dh
jne OK30
call WritBlok
; Einde.
OK30: pop ax
ret
WritByte endp
WriteInt proc near
;
; Schrijft een byte naar de Intermediate Buffer. Als de buffer vol is,
; wordt BCFlag gereset.
;
; Is de buffer vol? Dan is de regel te lang en het programma is
; blijkbaar niet in Basicode. Reset dus BCFlag en negeer de aanroep.
cmp IntWLen,IntLen
jb NietVol
and BCFlag,0
jmp short BufVol
; Is de buffer nog niet vol, dan kan het byte gewoon weggezet worden.
NietVol: push bx
mov bx,IntWLen
mov [bx+IntBuf],al
inc IntWLen
; Einde.
pop bx
BufVol: ret
WriteInt endp
ReadInt proc near
;
; Leest een byte uit de Intermediate Buffer.
; Als er geprobeerd wordt te lezen na het einde van de buffer, dan
; wordt er CR geretourneerd
;
push bx
; Is de buffer leeggelezen? geef dan een Carriage Return als
; resultaat.
mov bx,IntOfs
cmp bx,IntWLen
mov al,0Dh
je EindInt
; Schrijf het byte in de buffer en verhoog de teller
mov al,[bx+IntBuf]
inc IntOfs
; Einde.
EindInt: pop bx
ret
ReadInt endp
Transfer proc near
;
; Schrijft Intermediate Buffer weg, met toevoeging van een LF na de CR
;
; Deze routine wordt gebruikt als er een Input Buffer Overflow
; gebeurt. De hele Intermediate Buffer wordt dan naar de file
; geschreven.
push cx
push si
; Bereken begin-offset en lengte
mov cx,IntWLen
mov si,offset IntBuf
; Schrijf weg
LP5: lodsb
call WritByte
loop LP5
cmp al,13d
je NoCR
mov al,13d ; anders ook CR
call WritByte
; Einde.
NoCR: pop si
pop cx
mov IntOfs,0
mov IntWLen,0
ret
Transfer endp
;--------------------------------------------:
; Subroutines :
;--------------------------------------------:
; In deze routines worden geen registers bewaard, tenzij anders
; aangegeven.
ZoekPrms proc near
;
; Zoekt slash-parameters
;
; Zoek naar een slash ('/')
mov di,offset parms
mov cl,ParmLen
xor ch,ch
mov al,'/'
ParmLP: repne scasb
jne GeenPrms
; Gevonden? dan controleren welke het is
mov al,[di]
push di
push cx
mov di,offset ParmTbl
mov cl,AantPmM
repne scasb
jne FoutePrm
; Is het een geldige parameter? dan opslaan
dec di
sub di,offset ParmTbl
shr di,1 ; voor Upper en Lower case
mov byte ptr [ParmSet+di],1
; Zijn er nog meer parameters?
FoutePrm:pop cx
pop di
jmp ParmLP
; Geen parameters (meer) - terug
GeenPrms:ret
ZoekPrms endp
ZoekNamn proc near
;
; Zoekt naar de namen van Source en Destination file in de parameters
;
; De naam van de Destination file wordt gekopieerd in DestNaam.
; Dat moet, omdat het Parameter-gebied overgeschreven wordt. (Dat
; is immers ook het Disk Transfer Area.)
; De offset van de Sourcefilenaam wordt doorgegeven in DX. Die wordt
; maar 1 keer gebruikt, dus die hoeft niet naar het programma door-
; gegeven te worden.
;
; Zoek naam van Source file
mov di,offset Parms
mov cl,ParmLen
xor ch,ch
mov al,' '
repe scasb ; zoek eerste teken van SourceNaam
pushf ; corrigeer DI en CX
dec di
inc cx
popf
jne OK2
OK3: jmp ParmErr
OK2: mov dx,di
OK2A: repne scasb ; zoek laatste teken van SourceNaam
jne OK3A
pushf ; corrigeer
dec di ; cx wordt niet gecorrigeerd; dat zou meteen
popf ; weer ongedaan moeten worden gemaakt hieronder
OK3A: mov byte ptr [di],0 ; is een ASCIIZ string, dus voeg 0 toe.
inc di ; 1 plaats verder. (geen DEC CX - zie boven)
jcxz EenParm ; 1 parameter - dan sourcenaam kopieren
; Zoek naam voor destination file
repe scasb ; zoek eerste teken van DestinationNaam
pushf
dec di
inc cx
popf
je OK3
cmp byte ptr [di],'/' ; slash-parameter is geen filenaam
je OK2A ; dus zoek einde van parameter en dan filenaam
push di ; sla begin-offset op
repne scasb ; zoek laatste teken DestinationNaam
jcxz OK28
dec di
OK28: pop si
jmp short OK28A
; Als er maar 1 parameter gegeven werd, betekent dat, dat
; DestNaam hetzelfde wordt als SourceNaam
; DI bevat nog steeds het einde van de sourcenaam
EenParm: mov si,dx ; begin-offset in si
; Op dit punt geldt: SI=begin van destnaam, DI=einde van destnaam
; Destination-naam gevonden? dan kopieren naar programma
; Let erop dat de naam 2 bytes verder moet komen als er een drive
; voor de destination is opgegeven. Dit laatste wordt in het
; hoofdprogramma uitgezocht, want DOS geeft dat keurig netjes door
; als het programma begint.
OK28A: mov cx,di ; lengte bepalen
sub cx,si
cmp cx,40
jb OK4
mov cx,3F
OK4: mov di,offset DestNaam ; verplaatsen naar programma
cmp byte ptr [di],0
je OK4A ; is er een drive ingevuld?
add di,2
OK4A: rep movsb ; doe verplaatsing
; Einde
ret
ZoekNamn endp
OpenSrc proc near
;
; Open Source file en lees lengte
;
; DX moet het adres bevatten van de naam van de file.
; Open file
mov ax,3D00 ; Open file for read
int 21
jnc OK5
jmp IOErr
; Sla File-handle op
OK5: mov SourceF,ax
; Einde
ret
OpenSrc endp
OpenDest proc near
;
; De Destination file wordt geopend om te controleren of de naam
; geldig is. Wordt hij niet gevonden, dan wordt hij gemaakt en
; uitgewist, om dezelfde reden.
;
; Er wordt een Temporary file geopend op de drive die
; aangegeven wordt door de naam van de Destination file.
; Aan het einde van het programma krijgt de Temporary file de naam
; van de destination file.
;
mov dx,offset DestNaam
xor cx,cx
mov ax,3D01 ; openen voor schrijven
int 21
jc OK25 ; openen niet gelukt? probeer dan te maken
; close file
mov bx,ax
mov ah,3E
int 21
jnc OK27
jmp IOErr
; Openen niet gelukt; probeer file te creeeren
OK25: mov dx,offset DestNaam
mov ah,3C
int 21
jnc OK25A
jmp ParmErr
; wis de zojuist gemaakte file uit
OK25A: mov bx,ax
mov ah,3Eh ; close file
int 21
jnc OK26
jmp IOErr
OK26: mov dx,offset DestNaam ; Delete file
mov ah,41
int 21
jnc OK27
jmp IOErr
; Maak nu een Temporary file (dit kan alleen vanaf DOS 3.00)
OK27: mov dx,offset TMPNaam
xor cx,cx
mov ah,5A ; Create temporary file
int 21
jnc OK7
jmp IOErr
; File-handle opslaan
OK7: mov DestF,ax
; Einde.
ret
OpenDest endp
Vertaal proc near
;
; Deze routine verricht het zware werk.
; Er wordt 1 regel van de source file vertaald, en wel als volgt:
; - Het regelnummer wordt direct weggeschreven.
; - De rest van de regel wordt ingelezen tot een CR gevonden wordt.
; Alle tekens in opdrachten worden vertaald naar Upper Case,
; alle foute Control-karakters worden vertaald naar Lower Case.
; - Dan wordt de regel teken voor teken afgescand naar Keywords.
; Wordt er een gevonden dan worden er spaties in de output-buf-
; fer gezet.
; - Als een CR wordt gevonden, dan wordt er een CR,LF aan de Output-
; buffer toegevoegd.
; De routine keert terug als dit gebeurd is.
;
; ==== PASS 1 ====
; In Pass 1 wordt de regel overgezet in de Intermediate Buffer.
; Daarbij worden spaties verwijderd (waar dat nodig en mogelijk is)
; Ook worden (waar nodig en mogelijk) de tekens naar Upper Case
; vertaald.
mov Qmode,0
mov Dmode,0
call ReadByte
cmp EofFlag,0
je BeginVrt
jmp VertEind
; Lees regelnummer+spatie. Deze worden rechtstreeks weggeschreven
LP3: call ReadByte ; lees byte
BeginVrt:cmp al,'0'
jb OK102AA
cmp al,'9'
ja OK102AA
call WritByte
cmp NParm,0 ; Als NParm
jne LP3 ; 1 is, hoeft er niets te worden afgedrukt
call WriteScr
jmp LP3
; We hebben het regelnummer gehad. Er moet nu hoe dan ook een spatie
; weggeschreven worden.
OK102AA: push ax
mov al,' '
call WritByte
pop ax
; stond er een spatie achter het regelnummer?
; lees dan het volgende byte in
cmp al,' '
jne OK102A
call ReadByte
; nieuwe regel op scherm (indien nodig)
OK102A: cmp NParm,0
jne OK101
push ax
mov al,13d
call WriteScr
pop ax
jmp short OK101
; Lees rest van regel; strip spaties en maak hoofdletters
LP4: call ReadByte
jnc OK101 ; Geen overflow? dan verder
; In geval van Buffer Overflow wordt volgende code uitgevoerd:
call Transfer
call ReadBlok
and BCFlag,0 ; reset validity flag
cmp EOFFlag,0
je LP6
jmp VertEind
LP6: call ReadByte ; lees rest van regel in en gooi weg
jnc OK102
call ReadBlok
cmp EOFFlag,0
je OK102
jmp VertEind
OK102: cmp al,13d
jne LP6
jmp VertEind
; Einde van instrukties voor buffer-overflow
; Controle op spatie.
OK101: cmp al,' ' ; geen spatie? Dan hoeft-ie niet te worden
jne GeenSPC ; weggehaald
; spatie-controle wordt alleen in bepaalde gevallen uitgevoerd
cmp Qmode,0
jne GeenSPC
cmp Dmode,1 ; alleen verwijderen als Dmode<>1
; (Dmode wordt van 3 op 1 gezet bij de eerste
; non-spatie achter de REM of DATA)
je GeenSPC
jmp Next1A ; Dmode niet op 1 zetten
; Eventueel vertalen naar Upper Case
GeenSPC: cmp Qmode,0 ; Vertalen naar Upper Case nodig?
jne OverUpC
cmp Dmode,0
jne OverUpC
cmp al,'a'
jb OverUpC
cmp al,'z'
ja OverUpC
sub al,20
; Het zo bewerkte teken tenslotte wegschrijven
OverUpC: call WriteInt ; Schrijf teken in Intermediate buffer
; Nu nog controleren of een van de modes aan of uit gezet moeten
; worden.
; Eerst de Quote mode.
cmp al,'"' ; Quote? dan Qmode omschakelen
jne OK103
xor Qmode,1
; Data mode
OK103: cmp Dmode,0
jne Next1 ; Geen controle als REM of DATA al gevonden
cmp IntWLen,3 ; was dit REM of DATA? dan Dmode aan
jb Next1
mov si,IntWLen
add si,offset IntBuf-3 ; si=offset laatste 3 tekens
push si
mov di,offset REM
mov cx,3
repe cmpsb
pop si
jne OK104
mov Dmode,3
jmp short Next1A
OK104: dec si
mov di,offset DATA
mov cx,4
repe cmpsb
jne Next1
mov Dmode,3
jmp short Next1A
Next1: and Dmode,1 ; als Dmode 3 was, wordt die nu 1, zodat
; alleen de eventuele direct volgende
; spaties worden verwijderd
Next1A: cmp al,13d
je Pass2
jmp LP4
; ==== Pass 2 ====
; In Pass 2 worden (waar nodig) spaties ingevoegd, lettend op de
; sleutelwoorden in de Keywords-tabel.
; De bytes worden een voor een ingelezen en er wordt per byte ge-
; controleerd op het begin van een Keyword.
; Er zijn ook andere zoek-algoritmen mogelijk, maar die zijn een
; stuk ingewikkelder. Ik vond hier de snelheid van het programmeren
; belangrijker dan de snelheid van het programma. Mocht je er anders
; over denken, ga dan gerust je gang.