This repository was archived by the owner on Apr 25, 2024. It is now read-only.
- Notifications
You must be signed in to change notification settings - Fork 4.5k
/
Copy pathCOMMAND.ASM
788 lines (704 loc) · 23.4 KB
/
COMMAND.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
;
; This version of COMMAND is divided into three distinct parts. First is the
; resident portion, which includes handlers for interrupts 22H (terminate),
; 23H (Cntrl-C), 24H (fatal error), and 27H (stay resident); it also has code
; to test and, if necessary, reload the transient portion. Following the
; resident is the init code, which is overwritten after use. Then comes the
; transient portion, which includes all command processing (whether internal
; or external). The transient portion loads at the end of physical memory,
; and it may be overlayed by programs that need as much memory as possible.
; When the resident portion of command regains control from a user program, a
; checksum is performed on the transient portion to see if it must be
; reloaded. Thus programs which do not need maximum memory will save the time
; required to reload COMMAND when they terminate.
;
; REV 1.17
; 05/19/82 Fixed bug in BADEXE error (relocation error must return to
; resident since the EXELOAD may have overwritten the transient.
; REV 1.18
; 05/21/82 IBM version always looks on drive A
; MSVER always looks on default drive
;
; REV 1.19
; 06/03/82 Drive spec now entered in command line
; 06/07/82 Added VER command (print DOS version number) and VOL command
; (print volume label)
; REV 1.20
; 06/09/82 Prints "directory" after directories
; 06/13/82 MKDIR, CHDIR, PWD, RMDIR added
; REV 1.50
; Some code for new 2.0 DOS, sort of HACKey. Not enough time to
; do it right.
; REV 1.70
; EXEC used to fork off new processes
; REV 1.80
; C switch for single command execution
; REV 1.90
; Batch uses XENIX
; Rev 2.00
; Lots of neato stuff
; IBM 2.00 level
; Rev 2.01
; 'D' switch for date time suppression
; Rev 2.02
; Default userpath is NUL rather than BIN
; same as IBM
; COMMAND split into pieces
; Rev 2.10
; INTERNATIONAL SUPPORT
; Rev 2.11 COMMAND split into more pieces
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSW.ASM
INCLUDE COMEQU.ASM
CODERES SEGMENT PUBLIC
CODERES ENDS
DATARES SEGMENT PUBLIC BYTE
EXTRN COMBAD:BYTE,NEEDCOM:BYTE,DRVMSG:BYTE
EXTRN DEFMSG:BYTE,PROMPT:BYTE,EXECEMES:BYTE,EXEBAD:BYTE
EXTRN TOOBIG:BYTE,NOCOM:BYTE,RBADNAM:BYTE,INT_2E_RET:DWORD
EXTRN NOHANDMES:BYTE,BMEMMES:BYTE,HALTMES:BYTE,FRETMES:BYTE
EXTRN PARENT:WORD,HANDLE01:WORD,LOADING:BYTE,BATCH:WORD
EXTRN TRNSEG:WORD,COMDRV:BYTE,MEMSIZ:WORD,SUM:WORD,EXTCOM:BYTE
EXTRN IO_SAVE:WORD,PERMCOM:BYTE,SINGLECOM:WORD,VERVAL:WORD
EXTRN PIPEFLAG:BYTE,SAVE_PDB:WORD,COMSPEC:BYTE,TRANS:WORD
EXTRN TRANVARS:BYTE,LTPA:WORD,RSWITCHAR:BYTE,RDIRCHAR:BYTE
EXTRN RETCODE:WORD,FORFLAG:BYTE
IF IBMVER
EXTRN SYS_CALL:DWORD,ZEXEC:WORD,EXESEG:WORD,EXESUM:WORD
EXTRN USER_SS:WORD,USER_SP:WORD
ENDIF
DATARES ENDS
ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment
ENVIRONMENT ENDS
INIT SEGMENT PUBLIC PARA
EXTRN CONPROC:NEAR
INIT ENDS
TAIL SEGMENT PUBLIC PARA
TAIL ENDS
TRANCODE SEGMENT PUBLIC PARA
TRANCODE ENDS
TRANDATA SEGMENT PUBLIC BYTE
EXTRN TRANDATAEND:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE
EXTRN TRANSPACEEND:BYTE,HEADCALL:DWORD
TRANSPACE ENDS
TRANTAIL SEGMENT PUBLIC PARA
TRANTAIL ENDS
ZEXEC_CODE SEGMENT PUBLIC PARA
ZEXEC_CODE ENDS
ZEXEC_DATA SEGMENT PUBLIC BYTE
ZEXEC_DATA ENDS
RESGROUP GROUP CODERES,DATARES,ENVIRONMENT,INIT,TAIL
TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL
EGROUP GROUP ZEXEC_CODE,ZEXEC_DATA
ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment
PUBLIC ECOMSPEC,ENVIREND,PATHSTRING
ORG 0
ENVARENA DB 10H DUP (?) ; Pad for mem arena
PATHSTRING DB "PATH="
USERPATH LABEL BYTE
DB0 ; Null path
DB"COMSPEC="
ECOMSPEC DB "/COMMAND.COM"
DB134 DUP (0)
ENVIREND LABEL BYTE
ENVIRONSIZ EQU $-PATHSTRING
ENVIRONSIZ2 EQU $-ECOMSPEC
ENVIRONMENT ENDS
; START OF RESIDENT PORTION
CODERES SEGMENT PUBLIC
PUBLIC GETCOMDSK2,LODCOM,THEADFIX,CONTCTERM,LOADCOM,INT_2E,LODCOM1
PUBLIC CHKSUM,SETVECT,EXT_EXEC,TREMCHECK,RESTHAND,CONTC,RSTACK
PUBLIC SAVHAND
IF IBMVER
PUBLIC EXECHK,SYSCALL,EXEC_WAIT
ENDIF
ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN RPRINT:NEAR,ASKEND:NEAR,DSKERR:NEAR
ORG 0
ZERO = $
ORG 100H
PROGSTART:
JMP RESGROUP:CONPROC
DB (80H-3) DUP (?)
RSTACK LABEL WORD
IF IBMVER
SYSCALL:
CMPAH,EXEC
JZ do_exec
JMP DWORD PTR [SYS_CALL]
do_exec:
PUSHES
PUSHDS
PUSHBP
PUSHDI
PUSHSI
PUSHDX
PUSHCX
PUSHBX
PUSHAX
MOV[user_ss],SS
MOV[user_sp],SP
;
; are we running on RSTACK already?
;
PUSHCS
POPBX ; BX <- CS
PUSHSS
POPAX ; AX <- SS
CMPAX,BX ; IF AX == BX then no stack switch!
JZ Get_mem
MOVSS,BX
ASSUME SS:RESGROUP
MOVSP,OFFSET RESGROUP:RSTACK
Get_mem:
MOVBX,0FFFFH ; allocate all of memory
MOVAH,ALLOC
INT int_command
MOVAX,OFFSET EGROUP:ZEXECDATAEND +15
MOVCL,4
SHRAX,CL
MOVCX,AX ; Save in CX
CMPBX,AX ; enough for EXEC?
JB EXECMER ; nope... cry
MOVAH,ALLOC
INT int_command
JC EXECMER ; Memory arenas probably trashed
ADDBX,AX
MOV[MEMSIZ],BX
SUBBX,CX
MOV[EXESEG],BX ; exec
MOVES,AX
MOVAH,DEALLOC
INT int_command
PUSHCS
POPDS
ASSUME DS:RESGROUP
CALL EXECHK
CMPDX,[EXESUM]
JZ HAVEXEC ; EXEC OK
MOVDX,OFFSET RESGROUP:COMSPEC
MOVAX,OPEN SHL8
INT int_command ; Open COMMAND.COM
JC EXECMER
MOVBX,AX ; Handle
MOVDX,OFFSET RESGROUP:TRANSTART
ADDDX,OFFSET TRANGROUP:EXECSTART -100H
XORCX,CX ; Seek loc
MOVAX,LSEEK SHL8
INT int_command
MOVCX,OFFSET EGROUP:ZEXECCODEEND
MOVDS,[EXESEG]
ASSUME DS:NOTHING
MOVAH,READ
INT int_command
PUSHAX
MOVAH,CLOSE
INT int_command ; Close COMMAND.COM
POPCX
CMPCX,OFFSET EGROUP:ZEXECCODEEND
JNZ EXECMER ; Size matched
CALL EXECHK
CMPDX,[EXESUM]
JNZ EXECMER
HAVEXEC:
MOV[LOADING],0 ; Flag to DSKERR
CALL DWORD PTR [ZEXEC]
JMP SHORT EXECRET
execmer:
LDSSI,DWORD PTR [user_Sp]
MOV[SI.user_AX],exec_not_enough_memory
PUSH[SI.user_F]
POPF
STC
PUSHF
POP[SI.user_F]
execret:
MOVSS,[user_SS]
ASSUME SS:NOTHING
MOVSP,[user_SP]
POPAX ; PUSH ES
POPBX ; PUSH DS
POPCX ; PUSH BP
POPDX ; PUSH DI
POPSI ; PUSH SI
POPDI ; PUSH DX
POPBP ; PUSH CX
POPDS ; PUSH BX
POPES ; PUSH AX
IRET
EXECHK:
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
PUSHDS
MOVDS,[EXESEG]
MOVCX,OFFSET EGROUP:ZEXECCODEEND
XORSI,SI
JMP CHECK_SUM
ENDIF
EXEC_ERR: ; Select the correct error message
MOVDX,OFFSET RESGROUP:RBADNAM
CMPAX,exec_file_not_found
JZ GOTEXECEMES
CMPAX,error_access_denied
JZ GOTEXECEMES
MOVDX,OFFSET RESGROUP:TOOBIG
CMPAX,exec_not_enough_memory
JZ GOTEXECEMES
MOVDX,OFFSET RESGROUP:EXEBAD
CMPAX,exec_bad_format
JZ GOTEXECEMES
MOVDX,OFFSET RESGROUP:EXECEMES
GOTEXECEMES:
PUSHCS
POPDS
CALL RPRINT
JMP SHORT NOEXEC
EXT_EXEC:
;
; we are now running in free space. anything we do from here
; on may get trashed. Move the stack (also in free space) to
; allocated space because since EXEC restores the stack,
; somebody may trash what is on the stack.
;
MOVCX,CS
MOVSS,CX
MOVSP,OFFSET RESGROUP:RSTACK
;
; Oops!! We have to make sure that the EXEC code doesn't blop a newstack!
;
;
INT int_command ; Do the EXEC
JC EXEC_ERR ; EXEC failed
EXEC_WAIT:
MOVAH,WAIT
INT int_command ; Get the return code
MOV[RETCODE],AX
NOEXEC:
JMP LODCOM
CONTC:
STI
MOVAX,CS
MOVDS,AX
ASSUME DS:RESGROUP
MOVAH,DISK_RESET
INT int_command ; Reset disks in case files were open
TEST[BATCH],-1
JZ CONTCTERM
JMP ASKEND ; See if user wants to terminate batch
CONTCTERM:
XORBP,BP ; Indicate no read
MOV[FORFLAG],0 ; Turn off for processing
MOV[PIPEFLAG],0 ; Turn off any pipe
CMP[SINGLECOM],0 ; See if we need to set SINGLECOM
JZ NOSETSING
MOV[SINGLECOM],-1 ; Cause termination on pipe, batch, for
NOSETSING:
CMP[EXTCOM],0
JNZ DODAB ; Internal ^C
JMP LODCOM1
DODAB:
STC ; Tell DOS to abort
ZZY PROC FAR
RET ; Leave flags on stack
ZZY ENDP
BADMEMERR: ; Allocation error loading transient
MOVDX,OFFSET RESGROUP:BMEMMES
FATALC:
PUSHCS
POPDS
CALL RPRINT
CMP[PERMCOM],0
JZ FATALRET
CMP[SINGLECOM],0 ; If PERMCOM and SINGLECOM
JNZ FATALRET ; Must take INT_2E exit
MOVDX,OFFSET RESGROUP:HALTMES
CALL RPRINT
STALL:
JMP STALL ; Crash the system nicely
FATALRET:
MOVDX,OFFSET RESGROUP:FRETMES
CALL RPRINT
FATALRET2:
CMP[PERMCOM],0 ; If we get here and PERMCOM,
JNZ RET_2E ; must be INT_2E
IF IBM
LDSDX,DWORD PTR [SYS_CALL]
ASSUME DS:NOTHING
MOVAX,(SET_INTERRUPT_VECTOR SHL8) + INT_COMMAND
INT int_command
ENDIF
MOVAX,[PARENT]
MOV WORD PTR CS:[PDB_Parent_PID],AX
MOVAX,(EXIT SHL8) ; Return to lower level
INT int_command
RET_2E:
PUSHCS
POPDS
ASSUME DS:RESGROUP,ES:NOTHING,SS:NOTHING
MOV[SINGLECOM],0 ; Turn off singlecom
MOVES,[LTPA]
MOVAH,DEALLOC
INT int_command ; Free up space used by transient
MOVBX,[SAVE_PDB]
MOVAH,SET_CURRENT_PDB
INT int_command ; Current process is user
MOVAX,[RETCODE]
CMP[EXTCOM],0
JNZ GOTECODE
XORAX,AX ; Internals always return 0
GOTECODE:
MOV[EXTCOM],1 ; Force external
JMP[INT_2E_RET] ;"IRET"
INT_2E: ; Magic command executer
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
POP WORD PTR [INT_2E_RET]
POP WORD PTR [INT_2E_RET+2] ;Get return address
POPAX ;Chuck flags
PUSHCS
POPES
MOVDI,80H
MOVCX,64
REPMOVSW
MOVAH,GET_CURRENT_PDB
INT int_command ; Get user's header
MOV[SAVE_PDB],BX
MOVAH,SET_CURRENT_PDB
MOVBX,CS
INT int_command ; Current process is me
MOV[SINGLECOM],81H
MOV[EXTCOM],1 ; Make sure this case forced
LODCOM: ; Termination handler
CMP[EXTCOM],0
JZ LODCOM1 ; If internal, memory already allocated
MOVBX,0FFFFH
MOVAH,ALLOC
INT int_command
MOVAX,OFFSET TRANGROUP:TRANSPACEEND +15
MOVCL,4
SHRAX,CL
IF IBM
PUSHAX
MOVAX,OFFSET EGROUP:ZEXECDATAEND +15
MOVCL,4
SHRAX,CL
POPCX
ADDAX,CX
ENDIF
ADDAX,20H
CMPBX,AX ; Is less than 512 byte buffer worth it?
JNC MEMOK
BADMEMERRJ:
JMP BADMEMERR ; Not enough memory
MEMOK:
MOVAH,ALLOC
INT int_command
JC BADMEMERRJ ; Memory arenas probably trashed
MOV[EXTCOM],0 ; Flag not to ALLOC again
MOV[LTPA],AX ; New TPA is base just allocated
ADDBX,AX
MOV[MEMSIZ],BX
MOVAX,OFFSET TRANGROUP:TRANSPACEEND +15
MOVCL,4
SHRAX,CL
IF IBM
PUSHAX
MOVAX,OFFSET EGROUP:ZEXECDATAEND +15
MOVCL,4
SHRAX,CL
POPCX
ADDAX,CX
ENDIF
SUBBX,AX
MOV[TRNSEG],BX ; Transient starts here
LODCOM1:
MOVAX,CS
MOVSS,AX
ASSUME SS:RESGROUP
MOVSP,OFFSET RESGROUP:RSTACK
MOVDS,AX
ASSUME DS:RESGROUP
CALL HEADFIX ; Make sure files closed stdin and stdout restored
XORBP,BP ; Flag command ok
MOVAX,-1
XCHGAX,[VERVAL]
CMPAX,-1
JZ NOSETVER
MOVAH,SET_VERIFY_ON_WRITE ; AL has correct value
INT int_command
NOSETVER:
CMP[SINGLECOM],-1
JNZ NOSNG
JMP FATALRET2 ; We have finished the single command
NOSNG:
CALL SETVECT
IF IBMVER
CALL EXECHK ; Check exe loader
CMPDX,[EXESUM]
JNZ BOGUS_COM
ENDIF
CALL CHKSUM ; Check the transient
CMPDX,[SUM]
JZ HAVCOM ; Transient OK
BOGUS_COM:
MOV[LOADING],1 ; Flag DSKERR routine
CALL LOADCOM
CHKSAME:
IF IBMVER
CALL EXECHK
CMPDX,[EXESUM]
JNZ ALSO_BOGUS
ENDIF
CALL CHKSUM
CMPDX,[SUM]
JZ HAVCOM ; Same COMMAND
ALSO_BOGUS:
CALL WRONGCOM
JMP SHORT CHKSAME
HAVCOM:
MOVAX,CHAR_OPER SHL8
INT int_command
MOV[RSWITCHAR],DL
CMPDL,'/'
JNZ USESLASH
MOV[RDIRCHAR],'\' ; Select alt path separator
USESLASH:
MOV[LOADING],0 ; Flag to DSKERR
MOVSI,OFFSET RESGROUP:TRANVARS
MOVDI,OFFSET TRANGROUP:HEADCALL
MOVES,[TRNSEG]
CLD
MOVCX,8
REPMOVSW ; Transfer INFO to transient
MOVAX,[MEMSIZ]
MOV WORD PTR DS:[PDB_block_len],AX ; Adjust my own header
JMP DWORD PTR [TRANS]
; Far call to REMCHECK for TRANSIENT
TREMCHECK PROC FAR
CALL REMCHECK
RET
TREMCHECK ENDP
REMCHECK:
;All registers preserved. Returns zero if media removable, NZ if fixed
; AL is drive (0=DEF, 1=A,...)
IF IBM
PUSHAX
ORAL,AL
JNZ GOTDRV2
MOVAH,GET_DEFAULT_DRIVE
INT int_command
INCAL ;A=1
GOTDRV2:
PUSHBX
MOVBL,AL
INT11H ;IBM EQUIP CALL
ROLAL,1
ROLAL,1
ANDAL,3
JNZ NOT_SINGLE
INCAL
NOT_SINGLE:
INCAL ; AL is now MAX floppy #
CMPBL,AL
POPBX
JBE SETREM ; Is an IBM floppy and so is removable
ORAL,AL ; Know AL is non-zero
JMP SHORT SETNREM
SETREM:
ELSE
PUSHAX
ENDIF
XORAX,AX ;Zero
IF IBM
SETNREM:
ENDIF
POPAX
RET
; Far call to HEADFIX for TRANSIENT
THEADFIX PROC FAR
CALL HEADFIX
RET
THEADFIX ENDP
HEADFIX:
XORBX,BX ; Clean up header
MOVCX,[IO_SAVE]
MOVDX,WORD PTR DS:[PDB_JFN_Table]
CMPCL,DL
JZ CHK1 ; Stdin matches
MOVAH,CLOSE
INT int_command
MOVDS:[PDB_JFN_Table],CL ; Restore stdin
CHK1:
INCBX
CMPCH,DH ; Stdout matches
JZ CHKOTHERHAND
MOVAH,CLOSE
INT int_command
MOVDS:[PDB_JFN_Table+1],CH ; Restore stdout
CHKOTHERHAND:
ADDBX,4 ; Skip 2,3,4
MOVCX,FilPerProc -5 ; Already done 0,1,2,3,4
CLOSELOOP:
MOVAH,CLOSE
INT int_command
INCBX
LOOP CLOSELOOP
RET
SAVHAND:
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
PUSHDS
PUSHBX ; Set stdin to sterr, stdout to stderr
PUSHAX
MOVAH,GET_CURRENT_PDB
INT int_command ; Get user's header
MOVDS,BX
MOVAX,WORD PTR DS:[PDB_JFN_Table]
MOV[HANDLE01],AX ; Save user's stdin, stdout
MOVAL,DS:[PDB_JFN_Table+2]
MOVAH,AL
MOV WORD PTR DS:[PDB_JFN_Table],AX ; Dup stderr
POPAX
POPBX
POPDS
RET
ASSUME DS:RESGROUP
GETCOMDSK2:
CALL GETCOMDSK
JMP LODCOM1 ; Memory already allocated
RESTHAND:
PUSHDS
PUSHBX ; Restore stdin, stdout to user
PUSHAX
MOVAH,GET_CURRENT_PDB
INT int_command ; Point to user's header
MOVAX,[HANDLE01]
MOVDS,BX
ASSUME DS:NOTHING
MOV WORD PTR DS:[PDB_JFN_Table],AX ; Stuff his old 0 and 1
POPAX
POPBX
POPDS
RET
ASSUME DS:RESGROUP,SS:RESGROUP
HOPELESS:
MOVDX,OFFSET RESGROUP:NOCOM
JMP FATALC
GETCOMDSK:
MOVDX,OFFSET RESGROUP:NEEDCOM
GETCOMDSK3:
MOVAL,[COMDRV]
CALL REMCHECK
JNZ HOPELESS ;Non-removable media
CALL RPRINT
MOVDX,OFFSET RESGROUP:DRVMSG
CMP[COMDRV],0
JNZ GETCOM1
MOVDX,OFFSET RESGROUP:DEFMSG
GETCOM1:
CALL RPRINT
MOVDX,OFFSET RESGROUP:PROMPT
CALL RPRINT
CALL GetRawFlushedByte
RET
; flush world and get raw input
GetRawFlushedByte:
MOVAX,(STD_CON_INPUT_FLUSH SHL8) OR RAW_CON_INPUT
INT int_command ; Get char without testing or echo
MOVAX,(STD_CON_INPUT_FLUSH SHL8) +0
INT int_command
return
LOADCOM: ; Load in transient
INCBP ; Flag command read
MOVDX,OFFSET RESGROUP:COMSPEC
MOVAX,OPEN SHL8
INT int_command ; Open COMMAND.COM
JNC READCOM
CMPAX,open_too_many_open_files
JNZ TRYDOOPEN
MOVDX,OFFSET RESGROUP:NOHANDMES
JMP FATALC ; Fatal, will never find a handle
TRYDOOPEN:
CALL GETCOMDSK
JMP SHORT LOADCOM
READCOM:
MOVBX,AX ; Handle
MOVDX,OFFSET RESGROUP:TRANSTART
XORCX,CX ; Seek loc
MOVAX,LSEEK SHL8
INT int_command
JC WRONGCOM1
MOVCX,OFFSET TRANGROUP:TRANSPACEEND -100H
IF IBM
ADDCX,15
ANDCX,0FFF0H
ADDCX,OFFSET EGROUP:ZEXECCODEEND
ENDIF
PUSHDS
MOVDS,[TRNSEG]
ASSUME DS:NOTHING
MOVDX,100H
MOVAH,READ
INT int_command
POPDS
ASSUME DS:RESGROUP
WRONGCOM1:
PUSHF
PUSHAX
MOVAH,CLOSE
INT int_command ; Close COMMAND.COM
POPAX
POPF
JC WRONGCOM ; If error on READ
CMPAX,CX
JZ RET10 ; Size matched
WRONGCOM:
MOVDX,OFFSET RESGROUP:COMBAD
CALL GETCOMDSK3
JMP SHORT LOADCOM ; Try again
CHKSUM: ; Compute transient checksum
PUSHDS
MOVDS,[TRNSEG]
MOVSI,100H
MOVCX,OFFSET TRANGROUP:TRANDATAEND -100H
CHECK_SUM:
CLD
SHRCX,1
XORDX,DX
CHK:
LODSW
ADDDX,AX
LOOP CHK
POPDS
RET10: RET
SETVECT: ; Set useful vectors
MOVDX,OFFSET RESGROUP:LODCOM
MOVAX,(SET_INTERRUPT_VECTOR SHL8) OR22H ; Set Terminate address
INT int_command
MOVDX,OFFSET RESGROUP:CONTC
MOVAX,(SET_INTERRUPT_VECTOR SHL8) OR23H ; Set Ctrl-C address
INT int_command
MOVDX,OFFSET RESGROUP:DSKERR
MOVAX,(SET_INTERRUPT_VECTOR SHL8) OR24H ; Set Hard Disk Error address
INT int_command
RET
CODERES ENDS
; This TAIL segment is used to produce a PARA aligned label in the resident
; group which is the location where the transient segments will be loaded
; initial.
TAIL SEGMENT PUBLIC PARA
ORG 0
TRANSTART LABEL WORD
TAIL ENDS
; This TAIL segment is used to produce a PARA aligned label in the transient
; group which is the location where the exec segments will be loaded
; initial.
TRANTAIL SEGMENT PUBLIC PARA
ORG 0
EXECSTART LABEL WORD
TRANTAIL ENDS
IF IBMVER
INCLUDE EXEC.ASM
ENDIF
END PROGSTART