Repository navigation
Expand file tree
/
Copy pathOEM.ASM
More file actions
4138 lines (3661 loc) · 78.9 KB
/
Copy pathOEM.ASM
File metadata and controls
4138 lines (3661 loc) · 78.9 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
;
; Reversed-engineered OEM.ASM, courtesy of Michal Necasek 2020-07-13
;
DSEG SEGMENT PUBLIC 'DATASG'
; Defined elsewhere
EXTRN CSAVEA:WORD,CSAVEM:WORD
; Data defined by the OEM module
OVMODE db 0 ; Old video mode
CBKINT dw offset CTLBRK
CBRKSG dw 0
dw offset TIMISR
TIMRSG dw 0
CVPAGE db 0 ; Currently selected video page
var_63a db 0
var_63b db 80 ; Screen width in columns (40/80)
var_63c db 0
VISVPG db 0 ; Currently visible video page
var_63e db 0 ; Initial/saved number of columns
CVMODE db 0 ; Currently set video mode
var_640 db 0
var_641 db 0
var_642 db 0
var_643 dw 0707h ; Cursor shape
var_645 db 7 ; Saved text attributes
var_646 db 7 ; Current text attributes
var_647 dw 0 ; Current video memory offset
var_649 dw 0 ; Screen width in pixels?
var_64b db 0 ; Current character column?
var_64c db 0
var_64d db 0
var_64e dw 0
var_650 db 0
db 0
var_652 db 6
db 5
db 1
var_655 db 6
db 10
db 1
db 0 ; Likely unused
db 0
db 0
db 0
db 0
db 0
db 0
db 0
var_660 db 3
var_661 dw 0 ; Current offset into screen?
var_663 dw 0 ; Some other offset?
var_665 db 0
var_666 db 0
var_667 dw 0 ; Function pointer
var_669 db 0
DSEG ENDS
CSEG SEGMENT PUBLIC 'CODESG'
ASSUME CS:CSEG
; GW-BASIC routines that OEM code calls into.
EXTRN KYBCLR:NEAR
EXTRN SCNCLR:NEAR
EXTRN SCNSWI:NEAR
EXTRN GRPINI:NEAR
EXTRN SPCTAB:NEAR
EXTRN SNERR:NEAR
PUBLIC SEGINI, GETHED, PRTMAP, GETFBC, SETFBC, GRPSIZ, POKFLT, PEKFLT
; =============== S U B R O U T I N E =======================================
SEGINI proc near
push ds
xor ax, ax
mov ds, ax
assume ds:nothing
mov ax, cs
mov ds:6Eh, ax ; Adjust segment for vector 1Bh
mov ds:72h, ax ; Adjust segment for vector 1Ch
mov ds:92h, ax ; Adjust segment for vector 24h
mov ax, es
mov ds:510h, ax ; Stash away BASIC data segment
pop ds
assume ds:nothing
ret
SEGINI endp
; ---------------------------------------------------------------------------
OEMHED db 0Dh,0Ah
db 'Microsoft BASIC',0Dh,0Ah
; db 'OEM.ASM by OS/2 Museum, July 2020',0Dh,0Ah
db 'https://github.com/microsoft/GW-BASIC'
db 0
; =============== S U B R O U T I N E =======================================
GETHED proc near
cmp al, al
mov bx, offset OEMHED
ret
GETHED endp
; =============== S U B R O U T I N E =======================================
; Map print function/output character codes
PRTMAP proc near
cmp al, 0FFh
jnz short loc_5044
cmp byte ptr ds:var_63a, 0
jz short BADMAP
mov al, ' '
loc_5044:
cmp al, 7 ; BEL
jz short BADMAP
cmp al, ' '
jnb short loc_506E
cmp al, 9
jb short loc_506E
jz short loc_5073
cmp al, 0Eh
jb short BADMAP
cmp al, 1Ch
jb short loc_506E
BADMAP:
mov ah, 0FFh
or al, al
stc
ret
; ---------------------------------------------------------------------------
loc_5060:
mov al, ' '
cmp byte ptr ds:var_63a, 0
jnz short loc_506E
or al, al
mov al, 0
ret
; ---------------------------------------------------------------------------
loc_506E:
or al, al
jz short loc_5060
ret
; ---------------------------------------------------------------------------
loc_5073:
mov al, 0Fh
jmp short BADMAP
PRTMAP endp
; =============== S U B R O U T I N E =======================================
; Get foreground/background colors
; On entry:
; CF set : Graphics
; CF clear: Text mode
GETFBC proc near
jb short TXTATR
mov al, ds:var_646
mov bl, al
shr bl, 1
shr bl, 1
shr bl, 1
shr bl, 1
and ax, 8Fh
and bx, 7
ret
; ---------------------------------------------------------------------------
TXTATR:
xor ax, ax
mov bx, ax
mov al, 3
ret
GETFBC endp
; ---------------------------------------------------------------------------
byte_5095 db 0
; =============== S U B R O U T I N E =======================================
; Set foreground/background colors
SETFBC proc near
push ax
push bx
cmp byte ptr ds:var_63a, 0
jnz short loc_50CE
shl bl, 1
shl bl, 1
shl bl, 1
shl bl, 1
or al, bl
cmp cs:byte_5095, 0
mov cs:byte_5095, 0
mov al, ds:var_645
jnz short loc_50CB
mov cs:byte_5095, 1
mov al, 70h ; 'p'
cmp byte ptr ds:var_645, 7
jz short loc_50CB
mov al, 7
loc_50CB:
mov ds:var_646, al
loc_50CE:
pop bx
pop ax
ret
SETFBC endp
; ---------------------------------------------------------------------------
mov cl, ds:var_63b
mov ch, 0
mov dx, 25
ret
; =============== S U B R O U T I N E =======================================
; Get screen pixel dimensions
GRPSIZ proc near
mov cx, ds:var_649
or cx, cx
jz short HEIGHT
dec cx ; Decrement unless zero
HEIGHT:
mov dx, 199
ret
GRPSIZ endp
; ---------------------------------------------------------------------------
PEKPOK db 0 ; Is it a PEEK (0) or POKE (255)?
word_50E9 dw 2Eh
dw 2Fh
dw 347h
dw 348h
dw 30h
dw 31h
dw 358h
dw 359h
dw 4Eh
dw 2Ch
dw 2Dh
dw 6Ah
off_5101 dw offset loc_5192
dw 153h
dw 152h
dw 646h ; var_646 ???
dw 48Fh
dw 48Eh
dw 157h
dw 156h
dw 47Eh
dw 47Dh
dw 155h
dw 154h
; =============== S U B R O U T I N E =======================================
; Filter PEEKs for "special" addresses
PEKFLT proc near
push ax
push cx
push bx
push dx
mov dx, bx
mov cs:PEKPOK, 0 ; It's a peek
jmp short DOPFLT
PEKFLT endp
; =============== S U B R O U T I N E =======================================
; Filter POKEs for "special" addresses
; On entry: Address in ES:DX
; On exit : ZF clear if poke should be done
POKFLT proc near
push ax
push cx
push bx
push dx
mov cs:PEKPOK, -1 ; It's a poke
DOPFLT:
push di
push es
cld
mov ax, ds
mov cx, es
cmp cx, ax ; Is it the BASIC data segment?
jz short BASDAT
cmp cx, 0 ; Zero segment?
jnz short PFLTX
cmp dx, 41Ah ; Is it the pointer into the keyboard buffer?
jnz short PFLTX
cmp cs:PEKPOK, -1 ; Is it a POKE?
jnz short PFLTX
call KYBCLR
jmp short PFLTX
; ---------------------------------------------------------------------------
BASDAT:
mov di, offset word_50E9
mov ax, dx
mov cx, 18h
shr cx, 1
push cs
pop es
assume es:CSEG
repne scasw
jnz short PFLTX
shl cx, 1
mov bx, offset off_5101
add bx, cx
mov ax, cs:[bx]
pop es
assume es:nothing
pop di
pop dx
pop bx
cmp cx, 2
jb short loc_518F
cmp cs:PEKPOK, 0 ; Is it a PEEK?
jz short loc_5187
mov dx, ax
or ax, 0FFFFh
pop cx
pop ax
ret
; ---------------------------------------------------------------------------
loc_5187:
mov bx, ax
or ax, 0FFFFh
pop cx
pop ax
ret
; ---------------------------------------------------------------------------
loc_518F:
pop cx
jmp ax
; ---------------------------------------------------------------------------
loc_5192:
xor ax, ax
pop ax
ret
; ---------------------------------------------------------------------------
PFLTX:
pop es
pop di
pop dx
pop bx
pop cx
pop ax
ret
POKFLT endp
; ---------------------------------------------------------------------------
; Start of another module?
; align 4
PUBLIC SETCBF, INICOM, RECCOM, SNDCOM, STACOM, TRMCOM, SNDLPT
BAUDTB dw 9600
dw 4800
dw 2400
dw 1800
dw 1200
dw 600
dw 300
dw 150
dw 110
dw 75
dw 12
dw 24
dw 48
dw 64
dw 96
dw 192
dw 384
dw 768
dw 1047
dw 1536
masks? db 8
db 18h
db 28h
db 38h
COMTBL dw offset CM1CTL
dw offset CM2CTL
CM1CTL db 0 ; Control structure for first COM port
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
dw offset CM1ISR
CM2CTL db 0 ; Control structure for second COM port
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
dw offset CM2ISR
CBFSEG dw 0
CBFSIZ dw 0
ISRDSP dw offset ISRFN0
dw offset ISRFN1
dw offset ISRFN2
dw offset ISRFN3
; ---------------------------------------------------------------------------
CM1ISR:
push bx
mov bx, offset CM1CTL
jmp short COMISR
; =============== S U B R O U T I N E =======================================
CM2ISR proc far
push bx
mov bx, offset CM2CTL
COMISR:
push cx
push dx
push si
push di
push ds
push cs
pop ds
assume ds:CSEG
push ax
mov byte ptr [bx+1Dh], 0
mov dx, [bx]
inc dx
inc dx
in al, dx
loc_523B:
and al, 6
inc byte ptr [bx+1Dh]
mov ah, 0
mov si, ax
jmp ISRDSP[si]
ISRFN2:
dec dx
dec dx
in al, dx
mov si, [bx+0Ah]
inc si
cmp si, CBFSIZ
jbe short loc_5257
xor si, si
loc_5257:
cmp si, [bx+8]
jnz short loc_5262
or byte ptr [bx+18h], 1
jmp short COMEOI
; ---------------------------------------------------------------------------
loc_5262:
mov BYTE PTR ISREVT, 1
mov [bx+0Ah], si
push ds
push bx
mov bx, [bx+14h]
mov di, CBFSEG
mov ds, di
assume ds:nothing
mov [bx+si], al
pop bx
pop ds
COMEOI:
mov al, 20h ; Send EOI
out 20h, al ; Interrupt controller, 8259A.
mov dx, [bx]
inc dx
inc dx
in al, dx
test al, 1
jnz short ISRX
cmp byte ptr [bx+1Dh], 8
jb short loc_523B
or byte ptr [bx+19h], 1
push ds
xor ax, ax
mov ds, ax
assume ds:nothing
mov si, cs:[bx+1Eh] ; Messing with the IVT!
mov ax, cs:[bx+10h]
mov [si], ax
mov ax, cs:[bx+12h]
mov [si+2], ax
xor ax, ax
mov cs:[bx+10h], ax
mov cs:[bx+12h], ax
pop ds
assume ds:nothing
inc dx
inc dx
mov al, 0 ; Read interrupt mask
out dx, al
in al, 21h ; Interrupt controller, 8259A.
or al, [bx+1Ch] ; Mask this port's IRQ again
out 21h, al ; Interrupt controller, 8259A.
mov al, 20h ; One more EOI for good measure?
out 20h, al ; Interrupt controller, 8259A.
ISRX:
pop ax
pop ds
pop di
pop si
pop dx
pop cx
pop bx
sti
iret
; ---------------------------------------------------------------------------
ISRFN1:
dec dx
mov si, [bx+0Ch]
cmp si, [bx+0Eh]
jz short loc_52F2
inc si
cmp si, 80h ; '�'
jbe short loc_52DC
xor si, si
loc_52DC:
mov [bx+0Ch], si
push bx
push ds
mov bx, [bx+16h]
mov di, ds:CBFSEG
mov ds, di
mov al, [bx+si]
pop ds
pop bx
dec dx
out dx, al
jmp short COMEOI
; ---------------------------------------------------------------------------
loc_52F2:
mov al, 0Dh
out dx, al
jmp short COMEOI
; ---------------------------------------------------------------------------
ISRFN3:
add dx, 3
in al, dx
and al, 0Ah
or [bx+18h], al
jmp COMEOI
; ---------------------------------------------------------------------------
ISRFN0:
add dx, 4
in al, dx
sub dx, 5
mov cl, [bx+1Ah]
not al
and al, cl
mov ah, [bx+19h]
mov ch, ah
and ah, 0F0h
cmp ah, al
jz short loc_5330
and ch, 0Fh
or al, ch
mov [bx+19h], al
and al, cl
jz short loc_5333
or byte ptr [bx+19h], 2
mov al, 0Dh
out dx, al
loc_5330:
jmp COMEOI
; ---------------------------------------------------------------------------
loc_5333:
and byte ptr [bx+19h], 0FDh
mov al, 0Fh
out dx, al
jmp COMEOI
CM2ISR endp
; =============== S U B R O U T I N E =======================================
; Set OEM COM Buffer (size & location)
; On entry: CX = COM buffer segment
; DX = COM buffer size if ZF set
; ZF set = use buffer size in DX
; ZF clear = use default buffer size
;
; On return: DX = COM buffer size
; CF set on error
SETCBF proc near
push bx
push ax
push ds
push si
mov cs:CBFSEG, cx
jnz short HAVBSZ ; ZF set if COM buffer size was
; given on the command line (/C:xxx)
mov dx, 256 ; Default COM buffer size
HAVBSZ:
xor si, si
or dx, dx
jz short SCBFX ; Bail if zero buffer size
cmp dx, 7F70h ; Buffer size too big?
jbe short CKCOM1
mov dx, 7F70h ; Maximum COM buffer size
CKCOM1:
mov cs:CBFSIZ, dx
inc dx
mov ds, si
assume ds:nothing
mov bx, offset CM1CTL
mov ax, ds:400h ; Read COM1 base from BDA
cmp ax, 3F8h ; Does it match the first UART?
jnz short CKCOM2
mov word ptr cs:[bx+1Eh], 30h ; Address of IRQ4 vector
mov byte ptr cs:[bx+1Bh], 0EFh ; IRQ4 mask
mov byte ptr cs:[bx+1Ch], 10h ; IRQ4 bit
mov cs:[bx], ax
mov cs:[bx+16h], si
add si, 81h ; '�'
mov cs:[bx+14h], si
add si, dx
mov bx, offset CM2CTL
mov ax, ds:402h ; Read COM2 base from BDA
CKCOM2:
cmp ax, 2F8h ; Is it the second UART?
jnz short SCBFX
mov word ptr cs:[bx+1Eh], 2Ch ; Address of IRQ3 vector
mov byte ptr cs:[bx+1Bh], 0F7h ; IRQ3 mask
mov byte ptr cs:[bx+1Ch], 8 ; IRQ3 bit
mov cs:[bx], ax
mov cs:[bx+16h], si
add si, 81h ; '�'
mov cs:[bx+14h], si
add si, dx
SCBFX:
mov dx, si
add dx, 0Fh ; Round up to next para
and dx, 0FFF0h
pop si
pop ds
assume ds:nothing
pop ax
pop bx
clc
ret
SETCBF endp
; ---------------------------------------------------------------------------
; START OF FUNCTION CHUNK FOR INICOM
BADFNM:
mov ah, -1 ; Bad file name
jmp INICMX
; ---------------------------------------------------------------------------
COMERR:
mov ah, -2
jmp INICMX
; END OF FUNCTION CHUNK FOR INICOM
; =============== S U B R O U T I N E =======================================
; Machine dependent COM OPEN routine
INICOM proc near
push si
push di
push ds
push cs
pop ds
assume ds:CSEG
mov si, bx
cld
lods byte ptr es:[si]
mov ah, al
call CMPREP
or dx, dx
jz short COMERR
lods word ptr es:[si]
mov di, offset BAUDTB
mov cx, 0Ah
push es
push cs
pop es
assume es:CSEG
repne scasw
pop es
assume es:nothing
jnz short BADFNM
add di, 12h
add dx, 3
mov al, 80h ; '�'
out dx, al
sub dx, 3
mov ax, [di]
out dx, al
inc dx
mov al, ah
out dx, al
add dx, 2
lods byte ptr es:[si]
sub al, 4
mov ah, al
jb short BADFNM
jz short loc_5418
dec al
loc_5418:
cmp al, 3
ja short BADFNM
mov cl, al
lods byte ptr es:[si]
jnz short loc_542A
cmp al, 2
jz short loc_542A
or al, al
jnz short BADFNM
loc_542A:
or ah, al
jz short BADFNM
dec al
js short loc_543D
mov ah, 0
push bx
mov bx, offset masks?
add bx, ax
or cl, [bx]
pop bx
loc_543D:
lods byte ptr es:[si]
or al, al
jz short loc_5446
or cl, 4
loc_5446:
mov al, cl
out dx, al
lods word ptr es:[si]
mov cl, 0
mov [bx+2], ax
or ax, ax
jz short loc_5457
or cl, 80h
loc_5457:
lods word ptr es:[si]
mov [bx+4], ax
or ax, ax
jz short loc_5463
or cl, 10h
loc_5463:
lods word ptr es:[si]
mov [bx+6], ax
or ax, ax
jz short loc_546F
or cl, 20h
loc_546F:
lods byte ptr es:[si]
test al, 2
mov al, 3
jz short loc_5479
mov al, 1
loc_5479:
inc dx
out dx, al
xor al, al
mov [bx+1Ah], cl
mov [bx+18h], al
mov word ptr [bx+8], 0
mov word ptr [bx+0Ah], 0
mov word ptr [bx+0Ch], 0
mov word ptr [bx+0Eh], 0
cmp word ptr [bx+10h], 0
jnz short loc_54DC
sub dx, 4
push ds
xor ax, ax
mov ds, ax
mov si, cs:[bx+1Eh] ; IVT manipulation!
mov ax, [si]
mov cs:[bx+10h], ax
mov ax, [si+2]
mov cs:[bx+12h], ax
mov ax, cs:[bx+20h]
mov [si], ax
mov ax, cs
mov [si+2], ax
pop ds
assume ds:nothing
inc dx
inc dx
in al, dx
dec dx
dec dx
in al, dx
add dx, 5
in al, dx
sub dx, 4
mov al, 0Dh
out dx, al
in al, 21h ; Interrupt controller, 8259A.
and al, [bx+1Bh] ; Unmask IRQ
out 21h, al ; Interrupt controller, 8259A.
add dx, 3
loc_54DC:
in al, dx
or al, 8
out dx, al
inc dx
inc dx
cli
in al, dx
not al
and al, cl
mov [bx+19h], al
sti
call sub_5665
INICMX:
pop ds
pop di
pop si
ret
INICOM endp
; =============== S U B R O U T I N E =======================================
; Read Char from COM to [AL] if ready
RECCOM proc near
push bx
push cx
push dx
push si
push di
push ds
push cs
pop ds
assume ds:CSEG
push ax
call CMPREP
mov cl, 0
call sub_5643
pop cx
mov al, cl
jnz short loc_552C
cli
mov si, [bx+8]
cmp si, [bx+0Ah]
jz short loc_552C
inc si
cmp si, CBFSIZ
jbe short loc_551B
xor si, si
loc_551B:
mov [bx+8], si
mov bx, [bx+14h]
mov di, CBFSEG
mov ds, di
assume ds:nothing
mov al, [bx+si]
sti
or dx, dx
loc_552C:
pop ds
pop di
pop si
pop dx
pop cx
pop bx
ret
RECCOM endp
; =============== S U B R O U T I N E =======================================
; Send [AL] to COM
SNDCOM proc near
push bx
push cx
push dx
push si
push di
push ds
push cs
pop ds
assume ds:CSEG
push ax
call CMPREP
mov cl, [bx+1Ah]
call sub_5643
pop cx
jnz short SNDCMX
SNDLOP:
cli
mov si, [bx+0Eh]
inc si
cmp si, 80h ; '�'
jbe short loc_5555
xor si, si
loc_5555:
cmp si, [bx+0Ch]
jz short loc_557D
push ds
push bx
mov [bx+0Eh], si
mov bx, [bx+16h]