This repository has been archived by the owner on Dec 24, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 91
/
Copy pathINT14.TXT
executable file
·1010 lines (853 loc) · 47.8 KB
/
INT14.TXT
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
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-1
title int14.asm
page ,120
; By Jeff Parsons (@jeffpar) 2018-03-06
; Installs interrupt handlers for the specified COM port
= 0001 DEBUG equ 1
0000 code segment word public 'code'
0100 org 100h
assume cs:code, ds:code, es:code, ss:code
0100 main proc near
0100 E9 093B R jmp install
main endp
assume cs:code, ds:nothing, es:nothing, ss:nothing
0103 90 even
0104 00 00 00 00 prev14 dd 0 ; previous INT 14h handler
0108 01 rtsFlg db 1 ; internal RTS flag (0=off, 1=on)
0109 00 pollFlg db 0 ; polling mode (0=off, 1=on); set by /P
010A 00 echoFlg db 0 ; set if incoming Ctrl-E has turned echo on
010B 90 even
010C FFFF comID dw -1 ; 0-based index of COM port in BIOS data area
010E 0003 comIRQ dw 3
0110 02F8 comAddr dw 2F8h
= 0020 MAXBUF equ 32
0112 0020[ inBuf db MAXBUF dup (?)
??
]
0132 0020[ outBuf db MAXBUF dup (?)
??
]
0152 0000 inTot dw 0 ; counts the total number of input bytes buffered
0154 0112 R inHead dw offset inBuf
0156 0112 R inTail dw offset inBuf
0158 0132 R outHead dw offset outBuf
015A 0132 R outTail dw offset outBuf
= 0400 MAXLOG equ 1024
015C 0400[ logBuff db MAXLOG dup (0)
00
]
055C 015C R logNext dw offset logBuff
log macro c,d
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-2
local log1
push bx
mov bx,logNext
mov byte ptr cs:[bx],c
mov byte ptr cs:[bx+1],d
add bx,2
cmp bx,offset logBuff + MAXLOG
jb log1
mov bx,offset logBuff
log1: mov byte ptr cs:[bx],'.'
mov byte ptr cs:[bx+1],'.'
mov logNext,bx
pop bx
endm
055E int14 proc far
055E 2E: 3B 16 010C R cmp dx,comID ; request for our COM port?
0563 74 03 je i14a ; yes
0565 EB 55 90 jmp i14x ; no
0568 84 E4 i14a: test ah,ah ; INIT function?
056A 75 2D jne i14b ; no
log 'N',al
056C 53 1 push bx
056D 2E: 8B 1E 055C R 1 mov bx,logNext
0572 2E: C6 07 4E 1 mov byte ptr cs:[bx],'N'
0576 2E: 88 47 01 1 mov byte ptr cs:[bx+1],al
057A 83 C3 02 1 add bx,2
057D 81 FB 055C R 1 cmp bx,offset logBuff + MAXLOG
0581 72 03 1 jb ??0000
0583 BB 015C R 1 mov bx,offset logBuff
0586 2E: C6 07 2E 1 ??0000: mov byte ptr cs:[bx],'.'
058A 2E: C6 47 01 2E 1 mov byte ptr cs:[bx+1],'.'
058F 2E: 89 1E 055C R 1 mov logNext,bx
0594 5B 1 pop bx
0595 E8 072C R call init
0598 CF iret
0599 80 FC 01 i14b: cmp ah,1 ; WRITE function?
059C 75 04 jne i14c ; no
; log 'W',al
059E E8 0773 R call write ; add the character in AL to outBuf
05A1 CF iret
05A2 80 FC 02 i14c: cmp ah,2 ; READ function?
05A5 75 04 jne i14d ; no
05A7 E8 07E5 R call read ; remove next char from inBuf into AL
; log 'R',al
; log 'r',ah
05AA CF iret
05AB 80 FC 03 i14d: cmp ah,3 ; STATUS function?
05AE 75 04 jne i14e ; no, jump to previous handler
05B0 E8 0856 R call status
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-3
; log 'S',al ; these generate too much "noise"
; log 's',ah
05B3 CF iret
05B4 80 FC AA i14e: cmp ah,0AAh ; quick-and-dirty installation check
05B7 75 03 jne i14x
05B9 F6 D4 not ah
05BB CF iret
05BC 2E: FF 2E 0104 R i14x: jmp dword ptr [prev14]
int14 endp
;
; fakeLSR
;
; Returns fake LSR in AL.
;
05C1 fakeLSR proc near
assume ds:code
05C1 53 push bx
05C2 52 push dx
05C3 83 C2 05 add dx,5 ; DX -> LSR
05C6 EC in al,dx
;
; See if inBuf contains data, and set the DR bit if it does.
;
05C7 24 FE and al,not 01h
05C9 8B 1E 0154 R mov bx,inHead
05CD 3B 1E 0156 R cmp bx,inTail
05D1 74 02 je lsr1
05D3 0C 01 or al,01h
;
; See if outBuf still has room, and set the THRE bit if it does.
;
05D5 80 3E 0109 R 00 lsr1: cmp pollFlg,0
05DA 75 11 jne lsr9
05DC 24 DF and al,not 20h
05DE 8B 1E 0158 R mov bx,outHead
05E2 E8 065E R call incPtr
05E5 3B 1E 015A R cmp bx,outTail
05E9 74 02 je lsr9
05EB 0C 20 or al,20h
05ED 5A lsr9: pop dx
05EE 5B pop bx
05EF C3 ret
fakeLSR endp
;
; getLSR
;
; Returns LSR in AL.
;
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-4
05F0 getLSR proc near
assume ds:code
05F0 52 push dx
05F1 83 C2 05 add dx,5 ; DX -> LSR
05F4 EC in al,dx ; AL = LSR bits
05F5 5A pop dx
05F6 C3 ret
getLSR endp
;
; getMSR
;
; Returns MSR in AL.
;
05F7 getMSR proc near
assume ds:code
05F7 52 push dx
05F8 83 C2 06 add dx,6 ; DX -> MSR
05FB EC in al,dx ; AL = MSR bits
05FC 5A pop dx
05FD C3 ret
getMSR endp
;
; setIER
;
; Sets the physical IER bits.
;
05FE setIER proc near
assume ds:code
05FE 52 push dx
05FF 83 C2 03 add dx,3 ; DX -> LCR
0602 EC in al,dx
0603 EB 00 jmp $+2
0605 24 7F and al,not 80h ; make sure the DLAB is not set, so that we can set IER
0607 EE out dx,al
0608 4A dec dx
0609 4A dec dx ; DX -> IER
060A B0 03 mov al,03h ; enable RBR (01h) and THR (02h) COM interrupts
060C EE out dx,al
060D 5A pop dx
060E C3 ret
setIER endp
;
; setDTR
;
; Sets the physical DTR bit.
;
060F setDTR proc near
assume ds:code
060F 52 push dx
0610 83 C2 04 add dx,4 ; DX -> MCR
0613 EC in al,dx
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-5
0614 80 3E 0109 R 00 cmp pollFlg,0
0619 75 02 jne dtr1
061B 0C 08 or al,08h ; OUT2 == 08h (which apparently must ALSO be set enable interrupts)
061D 0C 01 dtr1: or al,01h ; DTR == 01h
061F EE out dx,al
0620 5A pop dx
0621 C3 ret
setDTR endp
;
; setRTS
;
; Sets the physical RTS bit according to the internal rtsFlg.
;
0622 setRTS proc near
assume ds:code
0622 50 push ax
0623 52 push dx
0624 83 C2 04 add dx,4 ; DX -> MCR
0627 EC in al,dx
0628 0C 02 or al,02h ; RTS == 02h
062A 80 3E 0108 R 00 cmp rtsFlg,0
062F 75 02 jne rts9
0631 24 FD and al,not 02h
0633 EE rts9: out dx,al
log 'T',al
0634 53 1 push bx
0635 8B 1E 055C R 1 mov bx,logNext
0639 2E: C6 07 54 1 mov byte ptr cs:[bx],'T'
063D 2E: 88 47 01 1 mov byte ptr cs:[bx+1],al
0641 83 C3 02 1 add bx,2
0644 81 FB 055C R 1 cmp bx,offset logBuff + MAXLOG
0648 72 03 1 jb ??0001
064A BB 015C R 1 mov bx,offset logBuff
064D 2E: C6 07 2E 1 ??0001: mov byte ptr cs:[bx],'.'
0651 2E: C6 47 01 2E 1 mov byte ptr cs:[bx+1],'.'
0656 89 1E 055C R 1 mov logNext,bx
065A 5B 1 pop bx
065B 5A pop dx
065C 58 pop ax
065D C3 ret
setRTS endp
;
; incPtr
;
; Updates BX to next buffer position.
;
065E incPtr proc near
assume ds:code
065E 43 inc bx
065F 81 FB 0132 R cmp bx,offset inBuf + MAXBUF
0663 75 04 jne inc1
0665 BB 0112 R mov bx,offset inBuf
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-6
0668 C3 inc0: ret
0669 81 FB 0152 R inc1: cmp bx,offset outBuf + MAXBUF
066D 75 F9 jne inc0
066F BB 0132 R mov bx,offset outBuf
0672 C3 ret
incPtr endp
;
; tryIn
;
; If the DR bit is set, see if we can buffer the data.
;
; CARRY returns clear if any new data was read, otherwise it's set.
;
0673 tryIn proc near
assume ds:code
0673 50 push ax
0674 52 push dx
0675 83 C2 05 add dx,5 ; DX -> LSR
0678 EC in al,dx
0679 5A pop dx
067A A8 01 test al,01h ; DR set?
067C 75 04 jnz ti1 ; yes
067E F9 stc
067F E9 0709 R jmp ti9
0682 EC ti1: in al,dx ; AL == new data
log 'I',al
0683 53 1 push bx
0684 8B 1E 055C R 1 mov bx,logNext
0688 2E: C6 07 49 1 mov byte ptr cs:[bx],'I'
068C 2E: 88 47 01 1 mov byte ptr cs:[bx+1],al
0690 83 C3 02 1 add bx,2
0693 81 FB 055C R 1 cmp bx,offset logBuff + MAXLOG
0697 72 03 1 jb ??0002
0699 BB 015C R 1 mov bx,offset logBuff
069C 2E: C6 07 2E 1 ??0002: mov byte ptr cs:[bx],'.'
06A0 2E: C6 47 01 2E 1 mov byte ptr cs:[bx+1],'.'
06A5 89 1E 055C R 1 mov logNext,bx
06A9 5B 1 pop bx
06AA 53 push bx
06AB 8B 1E 0154 R mov bx,inHead
06AF 88 07 mov [bx],al
06B1 E8 065E R call incPtr
06B4 3B 1E 0156 R cmp bx,inTail
06B8 75 29 jne ti7
log 'F',al
06BA 53 1 push bx
06BB 8B 1E 055C R 1 mov bx,logNext
06BF 2E: C6 07 46 1 mov byte ptr cs:[bx],'F'
06C3 2E: 88 47 01 1 mov byte ptr cs:[bx+1],al
06C7 83 C3 02 1 add bx,2
06CA 81 FB 055C R 1 cmp bx,offset logBuff + MAXLOG
06CE 72 03 1 jb ??0003
06D0 BB 015C R 1 mov bx,offset logBuff
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-7
06D3 2E: C6 07 2E 1 ??0003: mov byte ptr cs:[bx],'.'
06D7 2E: C6 47 01 2E 1 mov byte ptr cs:[bx+1],'.'
06DC 89 1E 055C R 1 mov logNext,bx
06E0 5B 1 pop bx
06E1 EB 24 jmp short ti8 ; buffer full, dropping the data
06E3 89 1E 0154 R ti7: mov inHead,bx
06E7 FF 06 0152 R inc inTot
06EB 80 3E 0109 R 00 cmp pollFlg,0
06F0 75 15 jne ti8
06F2 83 3E 0152 R 18 cmp inTot,(MAXBUF/4)*3 ; have we reached the 3/4 point?
06F7 75 0E jne ti8 ; no
06F9 80 3E 0108 R 00 cmp rtsFlg,0 ; is RTS already off?
06FE 74 07 je ti8 ; yes
0700 FE 0E 0108 R dec rtsFlg ; no, so let's try turning it off now
0704 E8 0622 R call setRTS ; and hope the sender give us some space
0707 5B ti8: pop bx
0708 F8 clc
0709 58 ti9: pop ax
070A C3 ret
tryIn endp
;
; tryOut
;
; If we have some buffered data, and the THRE bit is set, output more data.
;
070B tryOut proc near
assume ds:code
070B 53 push bx
070C 8B 1E 015A R mov bx,outTail
0710 3B 1E 0158 R cmp bx,outHead
0714 74 14 je to9
0716 52 push dx
0717 83 C2 05 add dx,5 ; DX -> LSR
071A EC in al,dx
071B 5A pop dx
071C A8 20 test al,20h ; THRE set?
071E 74 0A jz to9 ; no
0720 8A 07 mov al,[bx]
0722 EE out dx,al
; log 'O',al
0723 E8 065E R call incPtr
0726 89 1E 015A R mov outTail,bx
072A 5B to9: pop bx
072B C3 ret
tryOut endp
;
; init
;
; Handles INIT requests from INT 14h.
;
072C init proc near
072C 53 push bx
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-8
072D 52 push dx
072E 1E push ds
072F 0E push cs
0730 1F pop ds
assume ds:code
0731 9C pushf
0732 FF 1E 0104 R call dword ptr [prev14]
0736 50 push ax
0737 8B 16 0110 R mov dx,comAddr
073B C7 06 0152 R 0000 mov inTot,0
0741 C7 06 0154 R 0112 R mov inHead,offset inBuf
0747 C7 06 0156 R 0112 R mov inTail,offset inBuf
074D C7 06 0158 R 0132 R mov outHead,offset outBuf
0753 C7 06 015A R 0132 R mov outTail,offset outBuf
0759 80 3E 0109 R 00 cmp pollFlg,0
075E 75 03 jne i1
0760 E8 05FE R call setIER
0763 E8 060F R i1: call setDTR
0766 C6 06 0108 R 01 mov rtsFlg,1
076B E8 0622 R call setRTS
076E 58 pop ax
076F 1F pop ds
assume ds:nothing
0770 5A pop dx
0771 5B pop bx
0772 C3 ret
init endp
;
; write
;
; Handles WRITE requests from INT 14h.
;
; If AH == 1 (the normal INT 14h write scenario), mimicking the ROM BIOS
; requires that we wait for DSR, then CTS, and finally THRE. I would prefer
; to do that by spin-waiting for MSR-based and LSR-based interrupt triggers,
; rather than adopting the ROM's totally arbitrary "let's loop 64K times" for
; each condition. But, as I'm sure the ROM BIOS authors originally thought
; too, this approach is easier.
;
0773 write proc near
0773 53 push bx
0774 51 push cx
0775 52 push dx
0776 1E push ds
0777 0E push cs
0778 1F pop ds
assume ds:code
0779 8B 16 0110 R mov dx,comAddr
077D FB sti
if DEBUG
077E 80 3E 010A R 00 cmp echoFlg,0
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-9
0783 74 08 je w0
0785 50 push ax
0786 B4 0E mov ah,0Eh
0788 B7 00 mov bh,0
078A CD 10 int 10h
078C 58 pop ax
078D w0:
endif
078D 86 E0 xchg ah,al ; stash the output data in AH
078F 2B C9 sub cx,cx
0791 E8 05F7 R w1: call getMSR
0794 24 30 and al,30h ; we're "cheating" and checking for both
0796 3C 30 cmp al,30h ; DSR and CTS at once, instead of the ROM's
0798 74 0B je w2 ; "one after the other" approach
079A E2 F5 loop w1
079C E8 05F0 R call getLSR
079F 0C 80 or al,80h ; signal a time-out error
07A1 86 E0 xchg ah,al
07A3 EB 3B jmp short w9
07A5 80 3E 0109 R 00 w2: cmp pollFlg,0 ; in polling mode, we take
07AA 74 03 je w3 ; every opportunity to check for input
07AC E8 0673 R call tryIn
07AF 2B C9 w3: sub cx,cx
07B1 E8 05F0 R w4: call getLSR
07B4 A8 20 test al,20h ; checking THRE
07B6 75 08 jnz w5
07B8 E2 F7 loop w4
07BA 0C 80 or al,80h ; signal a time-out error
07BC 86 E0 xchg ah,al
07BE EB 20 jmp short w9
07C0 FA w5: cli
07C1 2A C0 sub al,al
07C3 86 C4 xchg al,ah ; recover the output data in AL and zero AH
07C5 8B 1E 0158 R mov bx,outHead
07C9 88 07 mov [bx],al
07CB E8 065E R call incPtr
07CE 3B 1E 015A R cmp bx,outTail
07D2 75 05 jne w8
07D4 80 CC 80 or ah,80h ; buffer full, so we pretend it's a time-out
07D7 EB 07 jmp short w9
07D9 89 1E 0158 R w8: mov outHead,bx ; there was room, so update the head ptr
07DD E8 070B R call tryOut ; and since THRE was set, call tryOut
07E0 1F w9: pop ds
assume ds:nothing
07E1 5A pop dx
07E2 59 pop cx
07E3 5B pop bx
07E4 C3 ret
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-10
write endp
;
; read
;
; Handles READ requests from INT 14h.
;
07E5 read proc near
07E5 53 push bx
07E6 52 push dx
07E7 1E push ds
07E8 0E push cs
07E9 1F pop ds
assume ds:code
07EA 8B 16 0110 R mov dx,comAddr
07EE 80 3E 0109 R 00 cmp pollFlg,0 ; in polling mode, we take
07F3 74 13 je r1 ; every opportunity to check for input
07F5 E8 0673 R call tryIn
;
; If CARRY is set, nothing was read, so let's turn RTS on.
; If CARRY is clear, then something was read, so let's turn RTS off.
;
07F8 B0 00 mov al,0
07FA 12 C0 adc al,al
07FC 38 06 0108 R cmp rtsFlg,al
0800 74 06 je r1
0802 A2 0108 R mov rtsFlg,al
0805 E8 0622 R call setRTS
0808 2B C0 r1: sub ax,ax
080A E8 05C1 R call fakeLSR
080D 24 1E and al,1Eh ; READ requests only return "error" bits
080F 8A E0 mov ah,al
0811 8B 1E 0156 R mov bx,inTail
0815 3B 1E 0154 R cmp bx,inHead
0819 75 05 jne r3
081B 80 CC 80 or ah,80h
081E EB 32 jmp short r9
0820 8A 07 r3: mov al,[bx]
0822 3C 05 cmp al,05h ; Ctrl-E?
0824 75 05 jne r4 ; no
0826 80 36 010A R 01 xor echoFlg,1 ; toggle echo flag
082B E8 065E R r4: call incPtr
082E 89 1E 0156 R mov inTail,bx
0832 80 3E 0109 R 00 cmp pollFlg,0
0837 75 15 jne r8
0839 83 3E 0152 R 08 cmp inTot,MAXBUF/4 ; are we down to 1/4 full now?
083E 75 0E jne r8 ; no
0840 80 3E 0108 R 00 cmp rtsFlg,0 ; is RTS already on?
0845 75 07 jne r8 ; yes
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-11
0847 FE 06 0108 R inc rtsFlg ; no, so let's turn RTS back on
084B E8 0622 R call setRTS
084E FF 0E 0152 R r8: dec inTot
0852 1F r9: pop ds
assume ds:nothing
0853 5A pop dx
0854 5B pop bx
0855 C3 ret
read endp
;
; status
;
; Handles STATUS requests from INT 14h.
;
; We could pass STATUS requests on to the previous handler, but that would
; return the port's "raw" state, whereas we need to return our own simulated
; "buffered" state: LSR (reg #5) bits in AH, MSR (reg #6) bits in AL.
;
; It's worth noting what DOS really cares about from this call. Prior to
; reading serial input, DOS calls the STATUS function and then requires that
; both AH bit 0 (LSR Data Ready: 0x01) and AL bit 5 (MSR Data Set Ready: 0x20)
; be set before it will call READ.
;
; Also, in some cases (eg, the CTTY case), DOS requires that both AH bit 5
; (LSR Transmitter Holding Register Empty: 0x20) and AL bit 5 (MSR Data Set
; Ready: 0x20) be set before it calls WRITE, while in other cases (eg, output
; redirection), DOS simply calls WRITE and hopes for the best.
;
0856 status proc near
0856 53 push bx
0857 52 push dx
0858 1E push ds
0859 0E push cs
085A 1F pop ds
assume ds:code
085B 8B 16 0110 R mov dx,comAddr
085F 80 3E 0109 R 00 cmp pollFlg,0 ; in polling mode, we take
0864 74 03 je s1 ; every opportunity to check for input
0866 E8 0673 R call tryIn
0869 E8 05C1 R s1: call fakeLSR
086C 8A E0 mov ah,al ; AH = LSR bits
086E E8 05F7 R call getMSR ; AL = MSR bits
0871 80 3E 0109 R 00 cmp pollFlg,0
0876 74 0E je s9
0878 80 3E 0108 R 00 cmp rtsFlg,0 ; in polling mode, if RTS isn't already on
087D 75 07 jne s9 ; turn it on
087F FE 06 0108 R inc rtsFlg
0883 E8 0622 R call setRTS
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-12
0886 1F s9: pop ds
assume ds:nothing
0887 5A pop dx
0888 5B pop bx
0889 C3 ret
status endp
088A intHW proc far
088A FB sti
088B 50 push ax
088C 53 push bx
088D 52 push dx
088E 1E push ds
088F 0E push cs
0890 1F pop ds
assume ds:code
0891 8B 16 0110 R mov dx,comAddr
0895 52 hw0: push dx
0896 42 inc dx
0897 42 inc dx ; DX -> IIR
0898 EC in al,dx
0899 5A pop dx
log 'H',al
089A 53 1 push bx
089B 8B 1E 055C R 1 mov bx,logNext
089F 2E: C6 07 48 1 mov byte ptr cs:[bx],'H'
08A3 2E: 88 47 01 1 mov byte ptr cs:[bx+1],al
08A7 83 C3 02 1 add bx,2
08AA 81 FB 055C R 1 cmp bx,offset logBuff + MAXLOG
08AE 72 03 1 jb ??0004
08B0 BB 015C R 1 mov bx,offset logBuff
08B3 2E: C6 07 2E 1 ??0004: mov byte ptr cs:[bx],'.'
08B7 2E: C6 47 01 2E 1 mov byte ptr cs:[bx+1],'.'
08BC 89 1E 055C R 1 mov logNext,bx
08C0 5B 1 pop bx
08C1 3C 04 cmp al,04h ; DR condition?
08C3 75 07 jne hw1 ; no
08C5 E8 0673 R call tryIn ; read data
08C8 73 CB jnc hw0 ; assuming we read data, check IIR again
08CA EB 07 jmp short hw9
08CC 3C 02 hw1: cmp al,02h ; THRE condition?
08CE 75 03 jne hw9 ; no
08D0 E8 070B R call tryOut ; yes, so see if we have something to write
08D3 FA hw9: cli
08D4 B0 20 mov al,20h ; EOI command
08D6 E6 20 out 20h,al
08D8 1F pop ds
assume ds:nothing
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-13
08D9 5A pop dx
08DA 5B pop bx
08DB 58 pop ax
08DC CF iret
intHW endp
08DD 90 even
08DE endRes label byte ; end of resident code/data
08DE 43 4F 4D 3F 20 68 61 comMsg db "COM? handlers installed$"
6E 64 6C 65 72 73 20
69 6E 73 74 61 6C 6C
65 64 24
08F6 20 69 6E 20 70 6F 6C pollMsg db " in polled mode$"
6C 65 64 20 6D 6F 64
65 24
0906 0D 0A 24 endMsg db 13,10,'$'
0909 48 61 6E 64 6C 65 72 insMsg db "Handlers already installed",13,10,'$'
73 20 61 6C 72 65 61
64 79 20 69 6E 73 74
61 6C 6C 65 64 0D 0A
24
0926 43 4F 4D 20 70 6F 72 errMsg db "COM port not found",13,10,'$'
74 20 6E 6F 74 20 66
6F 75 6E 64 0D 0A 24
093B install proc near
assume ds:code, es:code, ss:code
;
; Let's look for a /P switch to determine polled mode,
; along with /1 to select adapter #1 at port 3F8h instead of 2F8h.
;
093B FC cld
093C BE 0080 mov si,80h ; DS:SI -> command line
093F AC lodsb
0940 98 cbw
0941 91 xchg cx,ax ; CX == line length (as a fail-safe)
0942 AC ins0: lodsb
0943 49 dec cx
0944 3C 0D cmp al,0Dh ; end of command-line?
0946 74 22 je ins3 ; yes
0948 3C 2F cmp al,'/'
094A 75 1A jne ins2
094C AC lodsb
094D 49 dec cx
094E 3C 31 cmp al,'1' ; /1?
0950 75 0A jne ins1 ; no
0952 81 06 0110 R 0100 add comAddr,100h ; bump 2F8h to 3F8h
0958 FF 06 010E R inc comIRQ ; bump IRQ3 to IRQ4
095C 24 DF ins1: and al,not 20h
095E 3C 50 cmp al,'P' ; /P?
0960 75 04 jne ins2 ; no
0962 FE 06 0109 R inc pollFlg ; yes, set pollFlg to non-zero
0966 85 C9 ins2: test cx,cx ; any more command-line characters?
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-14
0968 7F D8 jg ins0 ; yes
096A 2B C0 ins3: sub ax,ax
096C 8E C0 mov es,ax
assume es:nothing ; since ES is zero
096E A1 0110 R mov ax,comAddr
0971 BB 0400 mov bx,400h ; access RBDA @0:400 instead of 40:0
0974 2B D2 sub dx,dx
0976 26: 39 07 ins4: cmp word ptr es:[bx],ax ; matching port?
0979 74 11 je ins5 ; yes
097B 43 inc bx
097C 43 inc bx
097D 42 inc dx
097E 80 FA 04 cmp dl,4
0981 72 F3 jb ins4
0983 BA 0926 R mov dx,offset errMsg ; no matching port was found; abort
0986 B4 09 mov ah,09h
0988 CD 21 int 21h
098A CD 20 int 20h
098C 89 16 010C R ins5: mov comID,dx ; comID is 0 for COM1, 1 for COM2, etc.
0990 B4 AA mov ah,0AAh ; quick-and-dirty INT14.COM installation check
0992 CD 14 int 14h
0994 F6 D4 not ah
0996 80 FC AA cmp ah,0AAh
0999 75 09 jne ins6
099B BA 0909 R mov dx,offset insMsg ; already installed for that port
099E B4 09 mov ah,09h
09A0 CD 21 int 21h
09A2 CD 20 int 20h ; abort
09A4 B8 055E R ins6: mov ax,offset int14
09A7 26: 87 06 0050 xchg ax,es:[14h*4]
09AC A3 0104 R mov word ptr prev14,ax
09AF 8C C8 mov ax,cs
09B1 26: 87 06 0052 xchg ax,es:[14h*4+2]
09B6 A3 0106 R mov word ptr prev14+2,ax
09B9 26: 8B 17 mov dx,es:[bx] ; DX is port (eg, 3F8h or 2F8h)
09BC BB 088A R mov bx,offset intHW
09BF 80 3E 0109 R 00 cmp pollFlg,0
09C4 75 28 jne ins7
09C6 8B 3E 010E R mov di,comIRQ ; convert IRQ...
09CA 83 C7 08 add di,8 ; ...to vector
09CD 03 FF add di,di ; and multiply vector by 4
09CF 03 FF add di,di
09D1 26: 89 1D mov word ptr es:[di],bx
09D4 26: 8C 4D 02 mov es:[di+2],cs
09D8 E8 05FE R call setIER
09DB E4 21 in al,21h
09DD 8A 0E 010E R mov cl,byte ptr comIRQ
09E1 B4 01 mov ah,1
09E3 D2 E4 shl ah,cl
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Page 1-15
09E5 F6 D4 not ah ; AH == NOT (1 SHL comIRQ)
09E7 22 C4 and al,ah
09E9 E6 21 out 21h,al ; unmask the appropriate COM IRQ
09EB BB 08DE R mov bx,offset endRes
09EE E8 060F R ins7: call setDTR ; set DTR (and OUT2 as needed for interrupts)
09F1 E8 0622 R call setRTS ; rtsFlg is initially 1
09F4 8B 16 010C R mov dx,comID
09F8 80 C2 31 add dl,'1'
09FB 88 16 08E1 R mov comMsg+3,dl
09FF BA 08DE R mov dx,offset comMsg
0A02 B4 09 mov ah,09h
0A04 CD 21 int 21h
0A06 80 3E 0109 R 00 cmp pollFlg,0
0A0B 74 07 je ins9
0A0D BA 08F6 R mov dx,offset pollMsg
0A10 B4 09 mov ah,09h
0A12 CD 21 int 21h
0A14 BA 0906 R ins9: mov dx,offset endMsg
0A17 B4 09 mov ah,09h
0A19 CD 21 int 21h
0A1B 8B D3 mov dx,bx ; DX -> end of resident code/data
0A1D CD 27 int 27h
install endp
0A1F code ends
end main
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Symbols-1
Macros:
N a m e Lines
LOG . . . . . . . . . . . . . . 12
Segments and Groups:
N a m e Size Align Combine Class
CODE . . . . . . . . . . . . . . 0A1F WORD PUBLIC 'CODE'
Symbols:
N a m e Type Value Attr
COMADDR . . . . . . . . . . . . L WORD 0110 CODE
COMID . . . . . . . . . . . . . L WORD 010C CODE
COMIRQ . . . . . . . . . . . . . L WORD 010E CODE
COMMSG . . . . . . . . . . . . . L BYTE 08DE CODE
DEBUG . . . . . . . . . . . . . Number 0001
DTR1 . . . . . . . . . . . . . . L NEAR 061D CODE
ECHOFLG . . . . . . . . . . . . L BYTE 010A CODE
ENDMSG . . . . . . . . . . . . . L BYTE 0906 CODE
ENDRES . . . . . . . . . . . . . L BYTE 08DE CODE
ERRMSG . . . . . . . . . . . . . L BYTE 0926 CODE
FAKELSR . . . . . . . . . . . . N PROC 05C1 CODE Length = 002F
GETLSR . . . . . . . . . . . . . N PROC 05F0 CODE Length = 0007
GETMSR . . . . . . . . . . . . . N PROC 05F7 CODE Length = 0007
HW0 . . . . . . . . . . . . . . L NEAR 0895 CODE
HW1 . . . . . . . . . . . . . . L NEAR 08CC CODE
HW9 . . . . . . . . . . . . . . L NEAR 08D3 CODE
I1 . . . . . . . . . . . . . . . L NEAR 0763 CODE
I14A . . . . . . . . . . . . . . L NEAR 0568 CODE
I14B . . . . . . . . . . . . . . L NEAR 0599 CODE
I14C . . . . . . . . . . . . . . L NEAR 05A2 CODE
I14D . . . . . . . . . . . . . . L NEAR 05AB CODE
I14E . . . . . . . . . . . . . . L NEAR 05B4 CODE
I14X . . . . . . . . . . . . . . L NEAR 05BC CODE
INBUF . . . . . . . . . . . . . L BYTE 0112 CODE Length = 0020
INC0 . . . . . . . . . . . . . . L NEAR 0668 CODE
INC1 . . . . . . . . . . . . . . L NEAR 0669 CODE
INCPTR . . . . . . . . . . . . . N PROC 065E CODE Length = 0015
INHEAD . . . . . . . . . . . . . L WORD 0154 CODE
INIT . . . . . . . . . . . . . . N PROC 072C CODE Length = 0047
INS0 . . . . . . . . . . . . . . L NEAR 0942 CODE
INS1 . . . . . . . . . . . . . . L NEAR 095C CODE
INS2 . . . . . . . . . . . . . . L NEAR 0966 CODE
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Symbols-2
INS3 . . . . . . . . . . . . . . L NEAR 096A CODE
INS4 . . . . . . . . . . . . . . L NEAR 0976 CODE
INS5 . . . . . . . . . . . . . . L NEAR 098C CODE
INS6 . . . . . . . . . . . . . . L NEAR 09A4 CODE
INS7 . . . . . . . . . . . . . . L NEAR 09EE CODE
INS9 . . . . . . . . . . . . . . L NEAR 0A14 CODE
INSMSG . . . . . . . . . . . . . L BYTE 0909 CODE
INSTALL . . . . . . . . . . . . N PROC 093B CODE Length = 00E4
INT14 . . . . . . . . . . . . . F PROC 055E CODE Length = 0063
INTAIL . . . . . . . . . . . . . L WORD 0156 CODE
INTHW . . . . . . . . . . . . . F PROC 088A CODE Length = 0053
INTOT . . . . . . . . . . . . . L WORD 0152 CODE
LOGBUFF . . . . . . . . . . . . L BYTE 015C CODE Length = 0400
LOGNEXT . . . . . . . . . . . . L WORD 055C CODE
LSR1 . . . . . . . . . . . . . . L NEAR 05D5 CODE
LSR9 . . . . . . . . . . . . . . L NEAR 05ED CODE
MAIN . . . . . . . . . . . . . . N PROC 0100 CODE Length = 0003
MAXBUF . . . . . . . . . . . . . Number 0020
MAXLOG . . . . . . . . . . . . . Number 0400
OUTBUF . . . . . . . . . . . . . L BYTE 0132 CODE Length = 0020
OUTHEAD . . . . . . . . . . . . L WORD 0158 CODE
OUTTAIL . . . . . . . . . . . . L WORD 015A CODE
POLLFLG . . . . . . . . . . . . L BYTE 0109 CODE
POLLMSG . . . . . . . . . . . . L BYTE 08F6 CODE
PREV14 . . . . . . . . . . . . . L DWORD 0104 CODE
R1 . . . . . . . . . . . . . . . L NEAR 0808 CODE
R3 . . . . . . . . . . . . . . . L NEAR 0820 CODE
R4 . . . . . . . . . . . . . . . L NEAR 082B CODE
R8 . . . . . . . . . . . . . . . L NEAR 084E CODE
R9 . . . . . . . . . . . . . . . L NEAR 0852 CODE
READ . . . . . . . . . . . . . . N PROC 07E5 CODE Length = 0071
RTS9 . . . . . . . . . . . . . . L NEAR 0633 CODE
RTSFLG . . . . . . . . . . . . . L BYTE 0108 CODE
S1 . . . . . . . . . . . . . . . L NEAR 0869 CODE
S9 . . . . . . . . . . . . . . . L NEAR 0886 CODE
SETDTR . . . . . . . . . . . . . N PROC 060F CODE Length = 0013
SETIER . . . . . . . . . . . . . N PROC 05FE CODE Length = 0011
SETRTS . . . . . . . . . . . . . N PROC 0622 CODE Length = 003C
STATUS . . . . . . . . . . . . . N PROC 0856 CODE Length = 0034
TI1 . . . . . . . . . . . . . . L NEAR 0682 CODE
TI7 . . . . . . . . . . . . . . L NEAR 06E3 CODE
TI8 . . . . . . . . . . . . . . L NEAR 0707 CODE
TI9 . . . . . . . . . . . . . . L NEAR 0709 CODE
TO9 . . . . . . . . . . . . . . L NEAR 072A CODE
TRYIN . . . . . . . . . . . . . N PROC 0673 CODE Length = 0098
TRYOUT . . . . . . . . . . . . . N PROC 070B CODE Length = 0021
Microsoft (R) Macro Assembler Version 4.00 3/16/18 13:04:41
int14.asm Symbols-3
W0 . . . . . . . . . . . . . . . L NEAR 078D CODE
W1 . . . . . . . . . . . . . . . L NEAR 0791 CODE
W2 . . . . . . . . . . . . . . . L NEAR 07A5 CODE
W3 . . . . . . . . . . . . . . . L NEAR 07AF CODE
W4 . . . . . . . . . . . . . . . L NEAR 07B1 CODE
W5 . . . . . . . . . . . . . . . L NEAR 07C0 CODE
W8 . . . . . . . . . . . . . . . L NEAR 07D9 CODE
W9 . . . . . . . . . . . . . . . L NEAR 07E0 CODE
WRITE . . . . . . . . . . . . . N PROC 0773 CODE Length = 0072
??0000 . . . . . . . . . . . . . L NEAR 0586 CODE
??0001 . . . . . . . . . . . . . L NEAR 064D CODE
??0002 . . . . . . . . . . . . . L NEAR 069C CODE
??0003 . . . . . . . . . . . . . L NEAR 06D3 CODE
??0004 . . . . . . . . . . . . . L NEAR 08B3 CODE