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
|
TITLE CHKDSK - MS-DOS Disk consistancy checker
; CHKDSK Version 2.30
; Verifies and repairs MS-DOS disk directory.
; To build CHKDSK you need three modules:
; CHKDSK CHKPROC CHKMES
; They should be linked the that order as well.
; REVISION HISTORY
;REV 1.1
; 05/21/82 Added rev number
;REV 1.5
; Mod by NANCYP to report on extents
; Mod by AARONR to report volume ID
;REV 2.0
; Total rewrite for directories
;REV 2.1
; Added ^C and INT 24H handlers
;REV 2.2
; INTERNATIONAL support
;REV 2.3
; Split into two modules to allow assembly on a PC
; CHKDSK and CHKPROC
FALSE EQU 0
TRUE EQU NOT FALSE
DRVCHAR EQU ":"
;The following defines the ranges of DOS version numbers for which this CHKDSK
; is good
DOSVER_LOW EQU 0136H ;1.54 in hex
DOSVER_HIGH EQU 020BH ;2.11 in hex
INCLUDE DOSSYM.ASM
FCB EQU 5CH
;Drive parameter block from DOS header
SUBTTL Segments used in load order
CODE SEGMENT PUBLIC
CODE ENDS
CONST SEGMENT PUBLIC BYTE
CONST ENDS
DATA SEGMENT PUBLIC WORD
DATA ENDS
DG GROUP CODE,CONST,DATA
SUBTTL Initialized Data
PAGE
CONST SEGMENT PUBLIC BYTE
PUBLIC HECODE,SWITCHAR,NOISY,DOFIX,CONBUF,ORPHCNT,ORPHSIZ,DOFIX
PUBLIC HIDCNT,HIDSIZ,DIRCNT,DIRSIZ,FILCNT,FILSIZ,BADSIZ,LCLUS
PUBLIC DOTENT,HAVFIX,SECONDPASS,NUL,ALLFILE,PARSTR,ERRSUB,LCLUS
PUBLIC DIRTYFAT,BADSIZ,DDOTENT,CROSSCNT,ORPHFCB,ORPHEXT,ALLDRV
PUBLIC FRAGMENT,USERDIR,DIRBUF,USERDIR,FIXMFLG,DOTMES,DIRCHAR
EXTRN IDMES1:BYTE,IDPOST:BYTE,VNAME:BYTE,MONTAB:BYTE
EXTRN TCHAR:BYTE,BADREAD_PRE:BYTE,BADREAD_POST:BYTE
EXTRN CRLF:BYTE,BADVER:BYTE,BADSUBDIR:BYTE,CENTRY:BYTE
EXTRN BADDRV:BYTE,BADCD:BYTE,BADRDMES:BYTE,OPNERR:BYTE
EXTRN CONTAINS:BYTE,EXTENTS:BYTE,NOEXTENTS:BYTE
EXTRN BADDRVM:BYTE,BADDRVM2:BYTE,BADIDBYT:BYTE
DIRBUF LABEL BYTE ;Entry buffer for searches
VOLID DB -1,0,0,0,0,0,8 ;Volume ID FCB
VOLNAM DB 0,"???????????"
DB 25 DUP(0)
ALLFILE DB -1,0,0,0,0,0,1EH ;Extended FCB
ALLDRV DB 0,"???????????"
DB 25 DUP (?)
ORPHFCB DB 0,"FILE0000"
ORPHEXT DB "CHK"
DB 25 DUP (?)
;Non-message data
SWITCHAR DB "-"
ROOTSTR LABEL BYTE
DIRCHAR DB "/"
NUL DB 0
PARSTR DB "..",0
DOTMES DB ".",0
DOTENT DB ". "
DDOTENT DB ".. "
HECODE DB ?
FIXMFLG DB 0 ;Flag for printing fixmes
ERRSUB DW 0 ;Flag for bad subdir error
FRAGMENT DB 0 ;Flag for extent processing
DIRTYFAT DB 0 ;Dirty flag for FAT
DIRCNT DW 0 ;# directories
DIRSIZ DW 0 ;# alloc units in directories
FILCNT DW 0 ;# reg files
FILSIZ DW 0 ;# alloc units in reg files
HIDCNT DW 0 ;# hidden files
HIDSIZ DW 0 ;# alloc units in hidden files
BADSIZ DW 0 ;# alloc units in bad sectors
ORPHCNT DW 0 ;# orphan files made
ORPHSIZ DW 0 ;# alloc units in orphan files
LCLUS DW 0 ;# alloc units in lost clusters
DISPFLG DB 0 ;used by number routines
CROSSCNT DW 0 ;# crosslinked files (first pass)
SECONDPASS DB 0 ;Pass flag
HAVFIX DB 0 ;non zero if any fixes
DOFIX DB 0 ;flag for F switch
NOISY DB 0 ;flag for V switch
USERDIR DB "/",0 ;Users current dir for drive
DB (DIRSTRLEN-1) DUP (?)
CONBUF DB 15,0 ;Input buffer
DB 15 DUP (?)
CONST ENDS
SUBTTL Un-initialized Data
PAGE
DATA SEGMENT PUBLIC WORD
PUBLIC ZEROTRUNC,NAMBUF,MCLUS,THISDPB,STACKLIM,ERRCNT
PUBLIC SRFCBPT,ISCROSS,CSIZE,DSIZE,SSIZE,FAT,FATMAP
PUBLIC HARDCH,CONTCH,USERDEV,SECBUF,DOTSNOGOOD
HARDCH DD ? ;Pointer to real INT 24 handler
CONTCH DD ? ;Pointer to real INT 23 handler
THISDPB DD ? ;Pointer to drive DPB
USERDEV DB ? ;Users current device
CSIZE DB ? ;Sectors per cluster
SSIZE DW ? ;bytes per sector
DSIZE DW ? ;# alloc units on disk
MCLUS DW ? ;DSIZE + 1
NAMBUF DB 14 DUP (?) ;Buffer
DOTSNOGOOD DB ? ;. or .. error flag
ZEROTRUNC DB ? ;Trimming flag
ISCROSS DB ? ;Crosslink flag
OLDCLUS DW ?
SRFCBPT DW ?
FATMAP DW OFFSET DG:FAT ;Offset of FATMAP table
SECBUF DW ? ;Offset of sector buffer
ERRCNT DB ? ;Used by FATread and write
STACKLIM DW ? ;Stack growth limit
INTERNATVARS internat_block <>
DB (internat_block_max - ($ - INTERNATVARS)) DUP (?)
FAT LABEL WORD
DATA ENDS
SUBTTL Start of CHKDSK
CODE SEGMENT PUBLIC
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
PUBLIC SUBERRP,DOTCOMBMES,FIGREC,FCB_TO_ASCZ,PRTCHR,EPRINT
PUBLIC PRINT,DOCRLF,DISP16BITS,DISP32BITS,DISPCLUS,CHECKFILES
EXTRN RDSKERR:NEAR,SETSWITCH:NEAR,PROMPTYN:NEAR,REPORT:NEAR
EXTRN PRINTCURRDIRERR:NEAR,PRINTTHISEL2:NEAR,CHECKERR:NEAR
EXTRN INT_23:NEAR,INT_24:NEAR,FINDCHAIN:NEAR,DONE:NEAR,AMDONE:NEAR
EXTRN FATAL:NEAR,DIRPROC:NEAR,CHKMAP:NEAR,CHKCROSS:NEAR,UNPACK:NEAR
ORG 100H
CHKDSK:
JMP SHORT CHSTRT
HEADER DB "Ver 2.30"
CHSTRT:
;Code to print header.
; PUSH AX
; MOV DX,OFFSET DG:HEADER
; CALL PRINT
; POP AX
PUSH AX ;Save DRIVE validity info
MOV AH,GET_VERSION
INT 21H
XCHG AH,AL ;Turn it around to AH.AL
CMP AX,DOSVER_LOW
JB GOTBADDOS
CMP AX,DOSVER_HIGH
JBE OKDOS
GOTBADDOS:
MOV DX,OFFSET DG:BADVER
JMP CERROR
OKDOS:
POP AX ;Get back drive info
MOV BX,0FFF0H
MOV DX,SP
CMP DX,BX
JAE STACKOK ;Lots of stack
MOV DX,DS:[2] ;High break
MOV CX,CS
SUB DX,CX
CMP DX,0FFFH
JAE SETSTACK ;Lots to grab
MOV CX,4 ;Suck up more stack (blast command)
SHL DX,CL
MOV BX,DX
SETSTACK:
CLI
MOV SP,BX
STI
STACKOK:
PUSH AX
MOV AH,DISK_RESET ;Flush everything, and invalidate
INT 21H
POP AX
CMP AL,0FFH ;Illegal drive specifier?
JNZ FILECHK ;No -- check for filename
DRVERR:
MOV DX,OFFSET DG:BADDRV
CERROR:
PUSH CS ;Make sure DS is OK
POP DS
CALL PRINT ;Print error message
INT 20H
CERROR2:
PUSH DX
CALL DONE ;Reset users disk
POP DX
JMP SHORT CERROR
FILECHK:
MOV AX,(CHAR_OPER SHL 8)
INT 21H
MOV [SWITCHAR],DL
CMP DL,"/"
JNZ SLASHOK
MOV [DIRCHAR],"\"
MOV [USERDIR],"\"
SLASHOK:
CMP DS:(BYTE PTR FCB+1)," " ;Filename specified?
JZ DRVCHK ;No -- get the correct drive
MOV AL,[SWITCHAR]
CMP DS:(BYTE PTR FCB+1),AL ;Filename specified?
JZ DRVCHK ;No -- get the correct drive
MOV BYTE PTR [FRAGMENT],1 ;Set flag to perform fragment
;check on specified files
DRVCHK:
CALL SETSWITCH ;Look for switches
MOV AH,GET_DEFAULT_DRIVE ;Get current drive
INT 21H
MOV [USERDEV],AL ;Save for later
MOV AH,AL
INC AH ;A = 1
MOV BH,DS:(BYTE PTR FCB) ;See if drive specified
OR BH,BH
JZ SETDSK
MOV AL,BH
MOV AH,AL
DEC AL ;A = 0
SETDSK:
MOV [ALLDRV],AH ;Target drive
MOV [VOLNAM],AH ;A = 1
MOV [ORPHFCB],AH ;A = 1
ADD [BADDRVM],AL ;A = 0
ADD [BADDRVM2],AL ;A = 0
MOV DL,AH ;A = 1
MOV AH,GET_DPB ;Get the DPB
INT 21H
ASSUME DS:NOTHING
CMP AL,-1
JNZ DRVISOK ;Bad drive (should always be ok)
MOV DX,OFFSET DG:BADDRV
CERROR2J: JMP CERROR2
DRVISOK:
DEC DL ;A = 0
MOV AH,SET_DEFAULT_DRIVE ;Set Target
INT 21H
CMP [BX.dpb_current_dir],0
JZ CURRISROOT ;Save users current dir for target
MOV SI,BX
ADD SI,dpb_dir_text
MOV DI,OFFSET DG:USERDIR + 1
SETDIRLP:
LODSB
STOSB
OR AL,AL
JZ CURRISROOT
JMP SHORT SETDIRLP
CURRISROOT:
MOV WORD PTR [THISDPB+2],DS
PUSH CS
POP DS
ASSUME DS:DG
MOV WORD PTR [THISDPB],BX
MOV AX,(GET_INTERRUPT_VECTOR SHL 8) OR 23H
INT 21H
MOV WORD PTR [CONTCH],BX
MOV WORD PTR [CONTCH+2],ES
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H
MOV DX,OFFSET DG:INT_23
INT 21H
MOV AX,(GET_INTERRUPT_VECTOR SHL 8) OR 24H
INT 21H
MOV WORD PTR [HARDCH],BX
MOV WORD PTR [HARDCH+2],ES
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 24H
MOV DX,OFFSET DG:INT_24
INT 21H
PUSH CS
POP ES
MOV DX,OFFSET DG:ROOTSTR
MOV AH,CHDIR ;Start at root
INT 21H
MOV DX,OFFSET DG:BADCD
JC CERROR2J ;Couldn't get there
MOV DX,OFFSET DG:FAT ;Scratch space
MOV AH,SET_DMA
INT 21H
MOV DX,OFFSET DG:VOLID ;Look for VOL ID
MOV AH,DIR_SEARCH_FIRST
INT 21H
CMP AL,-1
JZ NOTVOLID
CALL PRINTID ;Have a VOL ID
NOTVOLID:
LDS BX,[THISDPB]
ASSUME DS:NOTHING
MOV AX,[BX.dpb_sector_size]
MOV [SSIZE],AX ;Sector size in bytes
MOV AL,[BX.dpb_cluster_mask]
INC AL
MOV [CSIZE],AL ;Sectros per cluster
MOV AX,[BX.dpb_max_cluster]
MOV [MCLUS],AX ;Bound for FAT searching
DEC AX
MOV [DSIZE],AX ;Total data clusters on disk
MOV AL,[BX.dpb_FAT_size] ;Sectors for one fat
XOR AH,AH
MOV CX,AX
MUL [SSIZE] ;Bytes for FAT
ADD [FATMAP],AX ;Allocate FAT space
MOV AX,[FATMAP]
ADD AX,[MCLUS]
ADD AX,2 ;Insurance
MOV [SECBUF],AX ;Allocate FATMAP space
ADD AX,[SSIZE]
ADD AX,20 ;Insurance
MOV [STACKLIM],AX ;Limit on recursion
MOV DI,CX
MOV CL,[BX.dpb_FAT_count] ;Number of FATs
MOV DX,[BX.dpb_first_FAT] ;First sector of FAT
PUSH CS
POP DS
ASSUME DS:DG
MOV BX,OFFSET DG:FAT
MOV AL,[ALLDRV]
DEC AL
MOV AH,'1'
RDLOOP:
XCHG CX,DI
PUSH DX
PUSH CX
PUSH DI
PUSH AX
INT 25H ;Read in the FAT
MOV [HECODE],AL
POP AX ;Flags
JNC RDOK
MOV DX,OFFSET DG:BADREAD_PRE ;Barfed
CALL PRINT
POP AX
PUSH AX
MOV DL,AH
CALL PRTCHR
MOV DX,OFFSET DG:BADREAD_POST
CALL PRINT
POP AX
POP CX
POP DI
POP DX
INC AH
ADD DX,DI
LOOP RDLOOP ;Try next FAT
CALL RDSKERR
JNZ NORETRY1
JMP NOTVOLID
NORETRY1:
MOV BX,OFFSET DG:BADRDMES
JMP FATAL ;Couldn't read any FAT, BARF
RDOK:
POP AX ;Clean up
POP AX
POP AX
POP AX
MOV SI,OFFSET DG:FAT
LODSB ;Check FAT ID byte
CMP AL,0F8H
JAE IDOK
MOV DX,OFFSET DG:BADIDBYT ;FAT ID bad
CALL PROMPTYN ;Ask user
JZ IDOK
JMP ALLDONE ;User said stop
IDOK:
MOV DI,[FATMAP]
MOV CX,[MCLUS]
INC CX
XOR AL,AL
REP STOSB ;Initialize FATMAP to all free
MOV DX,OFFSET DG:DIRBUF ;FOR ALL SEARCHING
MOV AH,SET_DMA
INT 21H
XOR AX,AX
PUSH AX ;I am root
PUSH AX ;Parent is root
CALL DIRPROC
CALL CHKMAP ;Look for badsectors, orphans
CALL CHKCROSS ;Check for second pass
CALL DOCRLF
CALL REPORT
ALLDONE:
CALL AMDONE
INT 20H ;Fini
ASSUME DS:DG
SUBTTL Check for extents in specified files
PAGE
CHECKFILES:
;Search the directory for the files specified on the command line
;and report the number of fragmented allocation units found in
;each one.
CALL DOCRLF
MOV AH,SET_DMA
MOV DX,[FATMAP] ;Use the first free space available
MOV BP,DX
ADD BP,27 ;cluster in the directory entry
INT 21H
MOV AH,DIR_SEARCH_FIRST ;Look for the first file
FRAGCHK:
MOV DX,FCB
INT 21H
OR AL,AL ;Did we find it?
JNZ MSGCHK ;No -- we're done
XOR AX,AX ;Initialize the fragment counter
MOV SI,[BP] ;Get the first cluster
CALL UNPACK
CMP DI,0FF8H ;End-of-file?
JAE NXTCHK ;Yes -- go report the results
INC SI
CMP SI,DI
JZ EACHCLUS
INC AX
EACHCLUS:
MOV [OLDCLUS],DI ;Save the last cluster found
MOV SI,DI ;Get the next cluster
CALL UNPACK
INC [OLDCLUS] ;Bump the old cluster
CMP DI,[OLDCLUS] ;Are they the same?
JNZ LASTCLUS ;No -- check for end-of-file
JMP SHORT EACHCLUS ;Continue processing
LASTCLUS:
CMP DI,0FF8H ;End-of-file?
JAE NXTCHK ;Yes -- go report the results
INC AX ;No -- found a fragement
JMP SHORT EACHCLUS ;Continue processing
NXTCHK:
OR AX,AX
JZ GETNXT
MOV [FRAGMENT],2 ;Signal that we output at least one file
PUSH AX ;Save count of fragments
MOV SI,[FATMAP]
INC SI
CALL PRINTTHISEL2
CALL DOCRLF
MOV DX,OFFSET DG:CONTAINS ;Print message
CALL PRINT
POP SI ;Number of fragments found
INC SI ;Number non-contig blocks
XOR DI,DI
MOV BX,OFFSET DG:EXTENTS
PUSH BP
CALL DISP16BITS
POP BP
GETNXT:
MOV AH,DIR_SEARCH_NEXT ;Look for the next file
JMP FRAGCHK
MSGCHK:
CMP AH,DIR_SEARCH_FIRST
JNZ FILSPOK
MOV SI,FCB + 1 ;File not found error
CALL PRINTTHISEL2
CALL DOCRLF
MOV DX,OFFSET DG:OPNERR
CALL PRINT ;Bad file spec
RET
FILSPOK:
CMP BYTE PTR [FRAGMENT],2
JZ CDONE
MOV DX,OFFSET DG:NOEXTENTS
CALL PRINT
CDONE:
RET
FIGREC:
;Convert cluster number in BX to sector # AH of cluster in DX
LDS DI,[THISDPB]
ASSUME DS:NOTHING
MOV CL,[DI.dpb_cluster_shift]
MOV DX,BX
DEC DX
DEC DX
SHL DX,CL
OR DL,AH
ADD DX,[DI.dpb_first_sector]
PUSH CS
POP DS
ASSUME DS:DG
RET
SUBTTL PRINTID - Print Volume ID info
PAGE
PRINTID:
ASSUME DS:DG
MOV DX,OFFSET DG:INTERNATVARS
MOV AX,INTERNATIONAL SHL 8
INT 21H
MOV [DISPFLG],1 ;Don't sub spaces for leading zeros
MOV SI,OFFSET DG:FAT + 8
MOV DI,OFFSET DG:VNAME
MOV CX,11
REP MOVSB
MOV DX,OFFSET DG:IDMES1
CALL PRINT ;Print ID message
ADD SI,13
LODSW ;Get date
PUSH SI
MOV DX,AX
MOV AX,[INTERNATVARS.Date_tim_format]
OR AX,AX
JZ USPDAT
DEC AX
JZ EUPDAT
CALL P_YR
CALL P_DSEP
CALL P_MON
CALL P_DSEP
MOV CX,1000H ;Do not supress leading zeroes
CALL P_DAY
JMP P_TIME
USPDAT:
CALL P_MONTH_NAM
MOV CX,1110H ;Supress at most 1 leading 0
CALL P_DAY
PUSH DX
MOV DL,','
CALL PRTCHR
MOV DL,' '
CALL PRTCHR
POP DX
PYA:
CALL P_YR
JMP P_TIME
EUPDAT:
MOV CX,1110H ;Supress at most 1 leading 0
CALL P_DAY
PUSH DX
MOV DL,' '
CALL PRTCHR
POP DX
CALL P_MONTH_NAM
JMP PYA
P_DSEP:
PUSH DX
MOV DL,[INTERNATVARS.Date_sep]
CALL PRTCHR
POP DX
RET
P_MONTH_NAM:
MOV AX,DX
PUSH DX
MOV CL,5
SHR AX,CL
AND AX,0FH ;Month in AX
DEC AX ;Make 0 indexed
MOV CX,AX
SHL AX,1
ADD AX,CX ;Mult by 3 chars/mo
MOV SI,OFFSET DG:MONTAB
ADD SI,AX
LODSB
MOV DL,AL
CALL PRTCHR
LODSB
MOV DL,AL
CALL PRTCHR
LODSB
MOV DL,AL
CALL PRTCHR
MOV DL,' '
CALL PRTCHR
POP DX
RET
P_MON:
MOV SI,DX
PUSH DX
MOV CL,5
SHR SI,CL
AND SI,0FH ;Month in SI
CALL CONVERT
MOV DL,AL
MOV CX,1000H ;Do not supress leading 0
CALL OUTBYTE ;Print month
POP DX
RET
P_DAY:
MOV SI,DX
PUSH DX
PUSH CX
AND SI,01FH ;SI has day
CALL CONVERT
POP CX
MOV DL,AL
CALL OUTBYTE ;Print day
POP DX
RET
P_YR:
MOV SI,DX
PUSH DX
MOV CL,9
SHR SI,CL
AND SI,07FH ;SI has raw year
ADD SI,1980 ;Real year
CALL CONVERT
MOV CX,1000H ;Do not supress leading zeros
CALL OUTWORD ;Print year
POP DX
RET
P_TIME:
MOV DL,' '
CALL PRTCHR
POP SI
ADD SI,-4
LODSW ;Get time
MOV DI,AX
MOV SI,DI
MOV CL,11
SHR SI,CL
AND SI,01FH ;SI has hour
CMP [INTERNATVARS.Time_24],0
JNZ ISOK2 ;24 hour time?
CMP SI,12
JB ISOK ;Is AM
MOV [TCHAR],'p'
JZ ISOK ;Is 12-1p
SUB SI,12 ;Is PM
ISOK:
OR SI,SI
JNZ ISOK2
MOV SI,12 ;0 is 12a
ISOK2:
CALL CONVERT
MOV CX,1110H ;Supress at most 1 leading 0
MOV DL,AL
CALL OUTBYTE ;Print hour
MOV DL,BYTE PTR [INTERNATVARS.Time_sep]
CALL PRTCHR
MOV SI,DI
MOV CL,5
SHR SI,CL
AND SI,03FH ;SI has minute
CALL CONVERT
MOV CX,1000H ;Do not supress leading zeroes
MOV DL,AL
CALL OUTBYTE ;Print minute
MOV DL,[TCHAR]
CMP [INTERNATVARS.Time_24],0
JNZ NOAP ;24 hour time, no a or p
CALL PRTCHR ;Print a or p
NOAP:
MOV DX,OFFSET DG:IDPOST
CALL PRINT
MOV [DISPFLG],0
RET
CONVERT:
MOV CX,16
XOR AX,AX
CNVLOOP:
SHL SI,1
CALL CONVWRD
CLC
LOOP CNVLOOP
RET
SUBTTL Misc Routines - Mostly I/O
PAGE
CONVWRD:
ADC AL,AL
DAA
XCHG AL,AH
ADC AL,AL
DAA
XCHG AL,AH
RET1: RET
UNSCALE:
SHR CX,1
JC RET1
SHL SI,1
RCL DI,1
JMP SHORT UNSCALE
DISP16BITS:
MOV BYTE PTR DISPFLG,1
JMP SHORT DISP32BITS
DISPCLUS:
MUL [SSIZE]
MOV CL,[CSIZE]
XOR CH,CH
MOV SI,AX
MOV DI,DX
CALL UNSCALE
DISP32BITS:
PUSH BP
PUSH BX
XOR AX,AX
MOV BX,AX
MOV BP,AX
MOV CX,32
CONVLP:
SHL SI,1
RCL DI,1
XCHG AX,BP
CALL CONVWRD
XCHG AX,BP
XCHG AX,BX
CALL CONVWRD
XCHG AX,BX
ADC AL,0
LOOP CONVLP
; Conversion complete
MOV CX,1310H ;Print 3-digit number with 2 leading blanks
CMP BYTE PTR DISPFLG,0
JNZ FOURDIG
MOV CX,1810H ;Print 8-digit number with 2 leading blanks
XCHG DX,AX
CALL DIGIT
XCHG AX,BX
CALL OUTWORD
FOURDIG:
MOV AX,BP
CALL OUTWORD
MOV BYTE PTR DISPFLG,0
POP DX
CALL PRINT
POP BP
RET
OUTWORD:
PUSH AX
MOV DL,AH
CALL OUTBYTE
POP DX
OUTBYTE:
MOV DH,DL
SHR DL,1
SHR DL,1
SHR DL,1
SHR DL,1
CALL DIGIT
MOV DL,DH
DIGIT:
AND DL,0FH
JZ BLANKZER
MOV CL,0
BLANKZER:
DEC CH
AND CL,CH
OR DL,30H
SUB DL,CL
CMP BYTE PTR DISPFLG,0
JZ PRTCHR
CMP DL,30H
JL RET2
PRTCHR:
MOV AH,STD_CON_OUTPUT
INT 21H
RET2: RET
PRINTCNT:
LODSB
MOV DL,AL
INT 21H
LOOP PRINTCNT
RET
EPRINT:
CALL CHECKERR
JNZ RET$1
JMP SHORT PRINT
DOCRLF:
MOV DX,OFFSET DG:CRLF
PRINT:
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
RET$1: RET
DOTCOMBMES:
CMP [NOISY],0
JZ SUBERRP
PUSH DX
CALL PRINTCURRDIRERR
MOV DX,OFFSET DG:CENTRY
CALL EPRINT
POP DX
CALL EPRINT
CALL DOCRLF
RET
SUBERRP:
MOV AL,1
XCHG AL,[ERRSUB]
CMP AL,0
JNZ RET32
MOV SI,OFFSET DG:NUL
CALL PRINTCURRDIRERR
MOV DX,OFFSET DG:BADSUBDIR
CALL EPRINT
RET32: RET
FCB_TO_ASCZ: ;Convert DS:SI to ASCIIZ ES:DI
MOV CX,8
MAINNAME:
LODSB
CMP AL,' '
JZ SKIPSPC
STOSB
SKIPSPC:
LOOP MAINNAME
LODSB
CMP AL,' '
JZ GOTNAME
MOV AH,AL
MOV AL,'.'
STOSB
XCHG AL,AH
STOSB
MOV CL,2
EXTNAME:
LODSB
CMP AL,' '
JZ GOTNAME
STOSB
LOOP EXTNAME
GOTNAME:
XOR AL,AL
STOSB
RET
CODE ENDS
END CHKDSK
|