From 80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6 Mon Sep 17 00:00:00 2001 From: Rich Turner Date: Fri, 12 Aug 1983 17:53:34 -0700 Subject: MS-DOS v2.0 Release --- v2.0/source/COMMAND.ASM | 788 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 788 insertions(+) create mode 100644 v2.0/source/COMMAND.ASM (limited to 'v2.0/source/COMMAND.ASM') diff --git a/v2.0/source/COMMAND.ASM b/v2.0/source/COMMAND.ASM new file mode 100644 index 0000000..db2783a --- /dev/null +++ b/v2.0/source/COMMAND.ASM @@ -0,0 +1,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 + + DB 0 ; Null path + DB "COMSPEC=" +ECOMSPEC DB "/COMMAND.COM" + DB 134 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: + CMP AH,EXEC + JZ do_exec + JMP DWORD PTR [SYS_CALL] + +do_exec: + PUSH ES + PUSH DS + PUSH BP + PUSH DI + PUSH SI + PUSH DX + PUSH CX + PUSH BX + PUSH AX + MOV [user_ss],SS + MOV [user_sp],SP +; +; are we running on RSTACK already? +; + PUSH CS + POP BX ; BX <- CS + PUSH SS + POP AX ; AX <- SS + CMP AX,BX ; IF AX == BX then no stack switch! + JZ Get_mem + MOV SS,BX +ASSUME SS:RESGROUP + MOV SP,OFFSET RESGROUP:RSTACK + +Get_mem: + MOV BX,0FFFFH ; allocate all of memory + MOV AH,ALLOC + INT int_command + MOV AX,OFFSET EGROUP:ZEXECDATAEND + 15 + MOV CL,4 + SHR AX,CL + MOV CX,AX ; Save in CX + CMP BX,AX ; enough for EXEC? + JB EXECMER ; nope... cry + MOV AH,ALLOC + INT int_command + JC EXECMER ; Memory arenas probably trashed + ADD BX,AX + MOV [MEMSIZ],BX + SUB BX,CX + MOV [EXESEG],BX ; exec + MOV ES,AX + MOV AH,DEALLOC + INT int_command + PUSH CS + POP DS +ASSUME DS:RESGROUP + CALL EXECHK + CMP DX,[EXESUM] + JZ HAVEXEC ; EXEC OK + MOV DX,OFFSET RESGROUP:COMSPEC + MOV AX,OPEN SHL 8 + INT int_command ; Open COMMAND.COM + JC EXECMER + MOV BX,AX ; Handle + MOV DX,OFFSET RESGROUP:TRANSTART + ADD DX,OFFSET TRANGROUP:EXECSTART - 100H + XOR CX,CX ; Seek loc + MOV AX,LSEEK SHL 8 + INT int_command + MOV CX,OFFSET EGROUP:ZEXECCODEEND + MOV DS,[EXESEG] +ASSUME DS:NOTHING + MOV AH,READ + INT int_command + PUSH AX + MOV AH,CLOSE + INT int_command ; Close COMMAND.COM + POP CX + CMP CX,OFFSET EGROUP:ZEXECCODEEND + JNZ EXECMER ; Size matched + + CALL EXECHK + CMP DX,[EXESUM] + JNZ EXECMER +HAVEXEC: + MOV [LOADING],0 ; Flag to DSKERR + CALL DWORD PTR [ZEXEC] + JMP SHORT EXECRET +execmer: + LDS SI,DWORD PTR [user_Sp] + MOV [SI.user_AX],exec_not_enough_memory + PUSH [SI.user_F] + POPF + STC + PUSHF + POP [SI.user_F] +execret: + MOV SS,[user_SS] +ASSUME SS:NOTHING + MOV SP,[user_SP] + POP AX ; PUSH ES + POP BX ; PUSH DS + POP CX ; PUSH BP + POP DX ; PUSH DI + POP SI ; PUSH SI + POP DI ; PUSH DX + POP BP ; PUSH CX + POP DS ; PUSH BX + POP ES ; PUSH AX + IRET + +EXECHK: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSH DS + MOV DS,[EXESEG] + MOV CX,OFFSET EGROUP:ZEXECCODEEND + XOR SI,SI + JMP CHECK_SUM +ENDIF + +EXEC_ERR: ; Select the correct error message + MOV DX,OFFSET RESGROUP:RBADNAM + CMP AX,exec_file_not_found + JZ GOTEXECEMES + CMP AX,error_access_denied + JZ GOTEXECEMES + MOV DX,OFFSET RESGROUP:TOOBIG + CMP AX,exec_not_enough_memory + JZ GOTEXECEMES + MOV DX,OFFSET RESGROUP:EXEBAD + CMP AX,exec_bad_format + JZ GOTEXECEMES + MOV DX,OFFSET RESGROUP:EXECEMES +GOTEXECEMES: + PUSH CS + POP DS + 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. +; + MOV CX,CS + MOV SS,CX + MOV SP,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: + MOV AH,WAIT + INT int_command ; Get the return code + MOV [RETCODE],AX +NOEXEC: + JMP LODCOM + +CONTC: + STI + MOV AX,CS + MOV DS,AX +ASSUME DS:RESGROUP + MOV AH,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: + XOR BP,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 + MOV DX,OFFSET RESGROUP:BMEMMES +FATALC: + PUSH CS + POP DS + CALL RPRINT + CMP [PERMCOM],0 + JZ FATALRET + CMP [SINGLECOM],0 ; If PERMCOM and SINGLECOM + JNZ FATALRET ; Must take INT_2E exit + MOV DX,OFFSET RESGROUP:HALTMES + CALL RPRINT +STALL: + JMP STALL ; Crash the system nicely + +FATALRET: + MOV DX,OFFSET RESGROUP:FRETMES + CALL RPRINT +FATALRET2: + CMP [PERMCOM],0 ; If we get here and PERMCOM, + JNZ RET_2E ; must be INT_2E +IF IBM + LDS DX,DWORD PTR [SYS_CALL] +ASSUME DS:NOTHING + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) + INT_COMMAND + INT int_command +ENDIF + MOV AX,[PARENT] + MOV WORD PTR CS:[PDB_Parent_PID],AX + MOV AX,(EXIT SHL 8) ; Return to lower level + INT int_command + +RET_2E: + PUSH CS + POP DS +ASSUME DS:RESGROUP,ES:NOTHING,SS:NOTHING + MOV [SINGLECOM],0 ; Turn off singlecom + MOV ES,[LTPA] + MOV AH,DEALLOC + INT int_command ; Free up space used by transient + MOV BX,[SAVE_PDB] + MOV AH,SET_CURRENT_PDB + INT int_command ; Current process is user + MOV AX,[RETCODE] + CMP [EXTCOM],0 + JNZ GOTECODE + XOR AX,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 + POP AX ;Chuck flags + PUSH CS + POP ES + MOV DI,80H + MOV CX,64 + REP MOVSW + MOV AH,GET_CURRENT_PDB + INT int_command ; Get user's header + MOV [SAVE_PDB],BX + MOV AH,SET_CURRENT_PDB + MOV BX,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 + MOV BX,0FFFFH + MOV AH,ALLOC + INT int_command + MOV AX,OFFSET TRANGROUP:TRANSPACEEND + 15 + MOV CL,4 + SHR AX,CL + + IF IBM + PUSH AX + MOV AX,OFFSET EGROUP:ZEXECDATAEND + 15 + MOV CL,4 + SHR AX,CL + POP CX + ADD AX,CX + ENDIF + + ADD AX,20H + CMP BX,AX ; Is less than 512 byte buffer worth it? + JNC MEMOK +BADMEMERRJ: + JMP BADMEMERR ; Not enough memory +MEMOK: + MOV AH,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 + ADD BX,AX + MOV [MEMSIZ],BX + + MOV AX,OFFSET TRANGROUP:TRANSPACEEND + 15 + MOV CL,4 + SHR AX,CL + + IF IBM + PUSH AX + MOV AX,OFFSET EGROUP:ZEXECDATAEND + 15 + MOV CL,4 + SHR AX,CL + POP CX + ADD AX,CX + ENDIF + + SUB BX,AX + MOV [TRNSEG],BX ; Transient starts here +LODCOM1: + MOV AX,CS + MOV SS,AX +ASSUME SS:RESGROUP + MOV SP,OFFSET RESGROUP:RSTACK + MOV DS,AX +ASSUME DS:RESGROUP + CALL HEADFIX ; Make sure files closed stdin and stdout restored + XOR BP,BP ; Flag command ok + MOV AX,-1 + XCHG AX,[VERVAL] + CMP AX,-1 + JZ NOSETVER + MOV AH,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 + CMP DX,[EXESUM] + JNZ BOGUS_COM +ENDIF + + CALL CHKSUM ; Check the transient + CMP DX,[SUM] + JZ HAVCOM ; Transient OK +BOGUS_COM: + MOV [LOADING],1 ; Flag DSKERR routine + CALL LOADCOM +CHKSAME: + +IF IBMVER + CALL EXECHK + CMP DX,[EXESUM] + JNZ ALSO_BOGUS +ENDIF + + CALL CHKSUM + CMP DX,[SUM] + JZ HAVCOM ; Same COMMAND +ALSO_BOGUS: + CALL WRONGCOM + JMP SHORT CHKSAME +HAVCOM: + MOV AX,CHAR_OPER SHL 8 + INT int_command + MOV [RSWITCHAR],DL + CMP DL,'/' + JNZ USESLASH + MOV [RDIRCHAR],'\' ; Select alt path separator +USESLASH: + MOV [LOADING],0 ; Flag to DSKERR + MOV SI,OFFSET RESGROUP:TRANVARS + MOV DI,OFFSET TRANGROUP:HEADCALL + MOV ES,[TRNSEG] + CLD + MOV CX,8 + REP MOVSW ; Transfer INFO to transient + MOV AX,[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 + PUSH AX + OR AL,AL + JNZ GOTDRV2 + MOV AH,GET_DEFAULT_DRIVE + INT int_command + INC AL ;A=1 +GOTDRV2: + PUSH BX + MOV BL,AL + INT 11H ;IBM EQUIP CALL + ROL AL,1 + ROL AL,1 + AND AL,3 + JNZ NOT_SINGLE + INC AL +NOT_SINGLE: + INC AL ; AL is now MAX floppy # + CMP BL,AL + POP BX + JBE SETREM ; Is an IBM floppy and so is removable + OR AL,AL ; Know AL is non-zero + JMP SHORT SETNREM +SETREM: + ELSE + PUSH AX + ENDIF + + XOR AX,AX ;Zero + + IF IBM +SETNREM: + ENDIF + + POP AX + RET + +; Far call to HEADFIX for TRANSIENT +THEADFIX PROC FAR + CALL HEADFIX + RET +THEADFIX ENDP + +HEADFIX: + XOR BX,BX ; Clean up header + MOV CX,[IO_SAVE] + MOV DX,WORD PTR DS:[PDB_JFN_Table] + CMP CL,DL + JZ CHK1 ; Stdin matches + MOV AH,CLOSE + INT int_command + MOV DS:[PDB_JFN_Table],CL ; Restore stdin +CHK1: + INC BX + CMP CH,DH ; Stdout matches + JZ CHKOTHERHAND + MOV AH,CLOSE + INT int_command + MOV DS:[PDB_JFN_Table+1],CH ; Restore stdout +CHKOTHERHAND: + ADD BX,4 ; Skip 2,3,4 + MOV CX,FilPerProc - 5 ; Already done 0,1,2,3,4 +CLOSELOOP: + MOV AH,CLOSE + INT int_command + INC BX + LOOP CLOSELOOP + RET + +SAVHAND: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSH DS + PUSH BX ; Set stdin to sterr, stdout to stderr + PUSH AX + MOV AH,GET_CURRENT_PDB + INT int_command ; Get user's header + MOV DS,BX + MOV AX,WORD PTR DS:[PDB_JFN_Table] + MOV [HANDLE01],AX ; Save user's stdin, stdout + MOV AL,DS:[PDB_JFN_Table+2] + MOV AH,AL + MOV WORD PTR DS:[PDB_JFN_Table],AX ; Dup stderr + POP AX + POP BX + POP DS + RET + +ASSUME DS:RESGROUP +GETCOMDSK2: + CALL GETCOMDSK + JMP LODCOM1 ; Memory already allocated + +RESTHAND: + PUSH DS + PUSH BX ; Restore stdin, stdout to user + PUSH AX + MOV AH,GET_CURRENT_PDB + INT int_command ; Point to user's header + MOV AX,[HANDLE01] + MOV DS,BX +ASSUME DS:NOTHING + MOV WORD PTR DS:[PDB_JFN_Table],AX ; Stuff his old 0 and 1 + POP AX + POP BX + POP DS + RET +ASSUME DS:RESGROUP,SS:RESGROUP + +HOPELESS: + MOV DX,OFFSET RESGROUP:NOCOM + JMP FATALC + +GETCOMDSK: + MOV DX,OFFSET RESGROUP:NEEDCOM +GETCOMDSK3: + MOV AL,[COMDRV] + CALL REMCHECK + JNZ HOPELESS ;Non-removable media + CALL RPRINT + MOV DX,OFFSET RESGROUP:DRVMSG + CMP [COMDRV],0 + JNZ GETCOM1 + MOV DX,OFFSET RESGROUP:DEFMSG +GETCOM1: + CALL RPRINT + MOV DX,OFFSET RESGROUP:PROMPT + CALL RPRINT + CALL GetRawFlushedByte + RET + +; flush world and get raw input +GetRawFlushedByte: + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR RAW_CON_INPUT + INT int_command ; Get char without testing or echo + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0 + INT int_command + return + +LOADCOM: ; Load in transient + INC BP ; Flag command read + MOV DX,OFFSET RESGROUP:COMSPEC + MOV AX,OPEN SHL 8 + INT int_command ; Open COMMAND.COM + JNC READCOM + CMP AX,open_too_many_open_files + JNZ TRYDOOPEN + MOV DX,OFFSET RESGROUP:NOHANDMES + JMP FATALC ; Fatal, will never find a handle + +TRYDOOPEN: + CALL GETCOMDSK + JMP SHORT LOADCOM + +READCOM: + MOV BX,AX ; Handle + MOV DX,OFFSET RESGROUP:TRANSTART + XOR CX,CX ; Seek loc + MOV AX,LSEEK SHL 8 + INT int_command + JC WRONGCOM1 + MOV CX,OFFSET TRANGROUP:TRANSPACEEND - 100H + + IF IBM + ADD CX,15 + AND CX,0FFF0H + ADD CX,OFFSET EGROUP:ZEXECCODEEND + ENDIF + + PUSH DS + MOV DS,[TRNSEG] +ASSUME DS:NOTHING + MOV DX,100H + MOV AH,READ + INT int_command + POP DS +ASSUME DS:RESGROUP +WRONGCOM1: + PUSHF + PUSH AX + MOV AH,CLOSE + INT int_command ; Close COMMAND.COM + POP AX + POPF + JC WRONGCOM ; If error on READ + CMP AX,CX + JZ RET10 ; Size matched +WRONGCOM: + MOV DX,OFFSET RESGROUP:COMBAD + CALL GETCOMDSK3 + JMP SHORT LOADCOM ; Try again + +CHKSUM: ; Compute transient checksum + PUSH DS + MOV DS,[TRNSEG] + MOV SI,100H + MOV CX,OFFSET TRANGROUP:TRANDATAEND - 100H + +CHECK_SUM: + CLD + SHR CX,1 + XOR DX,DX +CHK: + LODSW + ADD DX,AX + LOOP CHK + POP DS +RET10: RET + +SETVECT: ; Set useful vectors + MOV DX,OFFSET RESGROUP:LODCOM + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 22H ; Set Terminate address + INT int_command + MOV DX,OFFSET RESGROUP:CONTC + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H ; Set Ctrl-C address + INT int_command + MOV DX,OFFSET RESGROUP:DSKERR + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 24H ; 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 + \ No newline at end of file -- cgit v1.2.3