; TITLE MSINIT.ASM -- MS-DOS INITIALIZATION CODE ORG 0 ; reset to beginning of data segment ; Init code below overlaps with data area INITBLOCK DB 110H DUP(0) ; Allow for segment round up INITSP DW ? INITSS DW ? BUFFSTRT DW ? ASSUME CS:DOSGROUP,DS:DOSGROUP,ES:DOSGROUP,SS:NOTHING EXTRN QUIT:NEAR,IRET:NEAR,ABSDRD:FAR,ABSDWRT:FAR EXTRN COMMAND:NEAR,CALL_ENTRY:NEAR IF NOT IBM EXTRN HEADER:BYTE ENDIF MOVDPB: ; This section of code is safe from being overwritten by block move MOV SP,CS:[INITSP] MOV SS,CS:[INITSS] REP MOVS BYTE PTR [DI],[SI] CLD MOV WORD PTR ES:[DMAADD+2],DX MOV SI,WORD PTR [DPBHEAD] ; Address of first DPB MOV WORD PTR ES:[DPBHEAD+2],ES MOV WORD PTR ES:[sft_addr+2],ES MOV CL,[NUMIO] ; Number of DPBs XOR CH,CH SETFINDPB: MOV WORD PTR ES:[SI.dpb_next_dpb+2],ES MOV ES:[SI.dpb_first_access],-1 ; Never accessed before ADD SI,DPBSIZ ; Point to next DPB LOOP SETFINDPB SUB SI,DPBSIZ MOV WORD PTR ES:[SI.dpb_next_dpb+2],-1 MOV DI,[BUFFSTRT] ; Set up one default buffer MOV WORD PTR ES:[BUFFHEAD+2],ES MOV WORD PTR ES:[BUFFHEAD],DI MOV WORD PTR ES:[DI.BUFDRV],00FFH MOV ES:[DI.BUFPRI],FREEPRI MOV WORD PTR ES:[DI.NEXTBUF],-1 MOV WORD PTR ES:[DI.NEXTBUF+2],-1 PUSH ES INC DX ; Leave enough room for the ARENA MOV BYTE PTR [CreatePDB],0FFh ; create jfns and set CurrentPDB invoke $CREATE_PROCESS_DATA_BLOCK ; Set up segment ASSUME DS:NOTHING,ES:NOTHING POP ES ASSUME ES:DOSGROUP ; ; set up memory arena ;SPECIAL NOTE FOR HIGHMEM VERSION ; At this point a process header has been built where the start of the ; CONSTANTS segment as refed by CS is. From this point until the return ; below be careful about references off of CS. ; PUSH AX MOV AX,[CurrentPDB] MOV ES:[CurrentPDB],AX ; Put it in the REAL location MOV BYTE PTR ES:[CreatePDB],0h ; reset flag in REAL location DEC AX MOV ES:[arena_head],AX PUSH DS MOV DS,AX MOV DS:[arena_signature],arena_signature_end MOV DS:[arena_owner],arena_owner_system SUB AX,ES:[ENDMEM] NEG AX DEC AX MOV DS:[arena_size],AX POP DS POP AX MOV DI,OFFSET DOSGROUP:sftabl + sft_table ; Point to sft 0 MOV AL,3 STOSB ; Adjust Refcount MOV DI,OFFSET DOSGROUP:SYSINITVAR XXX PROC FAR RET XXX ENDP DATA ENDS ; the next segment defines a new class that MUST appear last in the link map. ; This defines several important locations for the initialization process that ; must be the first available locations of free memory. LAST SEGMENT BYTE PUBLIC 'LAST' PUBLIC SYSBUF PUBLIC MEMSTRT SYSBUF LABEL WORD ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING DOSINIT: CLI CLD MOV [ENDMEM],DX MOV [INITSP],SP MOV [INITSS],SS MOV SP,OFFSET DOSGROUP:INITSTACK MOV AX,CS MOV SS,AX ASSUME SS:DOSGROUP MOV WORD PTR [DEVHEAD+2],DS MOV WORD PTR [DEVHEAD],SI ; DS:SI Points to CONSOLE Device CALL CHARINIT PUSH SI ADD SI,SDEVNAME ; Point to name PUSH CS POP ES ASSUME ES:DOSGROUP MOV DI,OFFSET DOSGROUP:sftabl + sft_table ; Point to sft 0 MOV AL,3 STOSB ; Refcount DEC AL STOSB ; Access rd/wr XOR AL,AL STOSB ; Drive byte STOSB ; attribute MOV CX,4 REP MOVSW ; Name MOV CL,3 MOV AL," " REP STOSB ; Extension ADD DI,12 ; Skip MOV AL,0C0H OR ISCIN OR ISCOUT STOSB POP SI MOV AX,SI STOSW ; Device pointer in FIRCLUS MOV AX,DS STOSW OR BYTE PTR [SI.SDEVATT],ISCIN OR ISCOUT MOV WORD PTR [BCON],SI MOV WORD PTR [BCON+2],DS CHAR_INIT_LOOP: LDS SI,DWORD PTR [SI] ; AUX device CALL CHARINIT TEST BYTE PTR [SI.SDEVATT],ISCLOCK JZ CHAR_INIT_LOOP MOV WORD PTR [BCLOCK],SI MOV WORD PTR [BCLOCK+2],DS MOV BP,OFFSET DOSGROUP:MEMSTRT ; ES:BP points to DPB PERDRV: LDS SI,DWORD PTR [SI] ; Next device CMP SI,-1 JZ CONTINIT CALL CHARINIT TEST [SI.SDEVATT],DEVTYP JNZ PERDRV ; Skip any other character devs MOV CL,[CALLUNIT] XOR CH,CH MOV [SI.SDEVNAME],CL ; Number of units in name field MOV DL,[NUMIO] XOR DH,DH ADD [NUMIO],CL PUSH DS PUSH SI LDS BX,[CALLBPB] PERUNIT: MOV SI,[BX] ; DS:SI Points to BPB INC BX INC BX ; On to next BPB MOV ES:[BP.dpb_drive],DL MOV ES:[BP.dpb_UNIT],DH PUSH BX PUSH CX PUSH DX invoke $SETDPB MOV AX,ES:[BP.dpb_sector_size] CMP AX,[MAXSEC] JBE NOTMAX MOV [MAXSEC],AX NOTMAX: POP DX POP CX POP BX MOV AX,DS ; Save DS POP SI POP DS MOV WORD PTR ES:[BP.dpb_driver_addr],SI MOV WORD PTR ES:[BP.dpb_driver_addr+2],DS PUSH DS PUSH SI INC DH INC DL MOV DS,AX ADD BP,DPBSIZ LOOP PERUNIT POP SI POP DS JMP PERDRV CONTINIT: PUSH CS POP DS ASSUME DS:DOSGROUP ; Calculate true address of buffers, FATs, free space MOV DI,BP ; First byte after current DPBs MOV BP,[MAXSEC] MOV AX,OFFSET DOSGROUP:SYSBUF MOV [BUFFSTRT],AX ADD AX,BP ; One I/O buffer ADD AX,BUFINSIZ MOV WORD PTR [DPBHEAD],AX ; True start of DPBs MOV DX,AX SUB DX,OFFSET DOSGROUP:SYSBUF MOV BP,DX ADD BP,DI ; Allocate buffer space SUB BP,ADJFAC ; True address of free memory PUSH BP MOV DI,OFFSET DOSGROUP:MEMSTRT ; Current start of DPBs ADD DI,dpb_next_dpb ; Point at dpb_next_dpb field MOV CL,[NUMIO] XOR CH,CH TRUEDPBAD: ADD AX,DPBSIZ ; Compute address of next DPB STOSW ; Set the link to next DPB ADD DI,DPBSIZ-2 ; Point at next address LOOP TRUEDPBAD SUB DI,DPBSIZ ; Point at last dpb_next_dpb field MOV AX,-1 STOSW ; End of list ADD BP,15 ;True start of free space (round up to segment) MOV CL,4 SHR BP,CL ; Number of segments for DOS resources MOV DX,CS ADD DX,BP ; First free segment MOV BX,0FH MOV CX,[ENDMEM] IF HIGHMEM SUB CX,BP MOV BP,CX ; Segment of DOS MOV DX,CS ; Program segment ENDIF IF NOT HIGHMEM MOV BP,CS ENDIF ; BP has segment of DOS (whether to load high or run in place) ; DX has program segment (whether after DOS or overlaying DOS) ; CX has size of memory in paragraphs (reduced by DOS size if HIGHMEM) MOV [ENDMEM],CX MOV ES,BP ASSUME ES:DOSGROUP IF HIGHMEM XOR SI,SI MOV DI,SI MOV CX,OFFSET DOSGROUP:SYSBUF ;# bytes to move SHR CX,1 ;# words to move (carry set if odd) REP MOVSW ; Move DOS to high memory JNC NOTODD MOVSB NOTODD: ENDIF MOV WORD PTR ES:[DSKCHRET+3],ES XOR AX,AX MOV DS,AX MOV ES,AX ASSUME DS:NOTHING,ES:NOTHING MOV DI,INTBASE+2 MOV AX,BP MOV BYTE PTR DS:[ENTRYPOINT],mi_Long_JMP MOV WORD PTR DS:[ENTRYPOINT+1],OFFSET DOSGROUP:CALL_ENTRY MOV WORD PTR DS:[ENTRYPOINT+3],AX EXTRN DIVOV:near MOV WORD PTR DS:[0],OFFSET DOSGROUP:DIVOV ; Set default divide ; trap address MOV DS:[2],AX MOV CX,17 REP STOSW ; Set 9 segments (skip 2 between each) IF ALTVECT MOV DI,ALTBASE+2 MOV CX,15 REP STOSW ; Set 8 segments (skip 2 between each) ENDIF MOV WORD PTR DS:[addr_int_abort],OFFSET DOSGROUP:QUIT MOV WORD PTR DS:[addr_int_command],OFFSET DOSGROUP:COMMAND MOV WORD PTR DS:[addr_int_terminate],100H MOV WORD PTR DS:[addr_int_terminate+2],DX MOV WORD PTR DS:[addr_int_ctrl_c],OFFSET DOSGROUP:IRET ; Ctrl-C exit MOV WORD PTR DS:[addr_int_fatal_abort],OFFSET DOSGROUP:IRET ; Fatal error exit MOV WORD PTR DS:[addr_int_disk_read],OFFSET DOSGROUP:ABSDRD ; INT 25 MOV WORD PTR DS:[addr_int_disk_write],OFFSET DOSGROUP:ABSDWRT ; INT 26 EXTRN Stay_resident:NEAR MOV WORD PTR DS:[addr_int_keep_process],OFFSET DOSGROUP:Stay_resident MOV WORD PTR DS:[addr_int_spooler],OFFSET DOSGROUP:IRET ; Spooler IF NOT ALTVECT MOV CX,12 XOR AX,AX MOV DI,2AH*4 REP STOSW ;Zero interrupt locs for ints 2AH-2FH ENDIF PUSH CS POP DS PUSH CS POP ES ASSUME DS:DOSGROUP,ES:DOSGROUP MOV AX,OFFSET DOSGROUP:INITBLOCK ADD AX,0Fh ; round to a paragraph MOV CL,4 SHR AX,CL MOV DI,DS ADD DI,AX INC DI MOV [CurrentPDB],DI PUSH BP PUSH DX ; Save COMMAND address MOV AX,[ENDMEM] MOV DX,DI invoke SETMEM ; Basic Header ASSUME DS:NOTHING,ES:NOTHING PUSH CS POP DS ASSUME DS:DOSGROUP MOV DI,PDB_JFN_Table XOR AX,AX STOSW STOSB ; 0,1 and 2 are CON device MOV AL,0FFH MOV CX,FilPerProc - 3 REP STOSB ; Rest are unused PUSH CS POP ES ASSUME ES:DOSGROUP MOV WORD PTR [sft_addr+2],DS ; Must be set to print messages ; After this points the char device functions for CON will work for ; printing messages IF NOT IBM IF NOT ALTVECT MOV SI,OFFSET DOSGROUP:HEADER invoke OUTMES PUSH CS ; Outmes stomps on segments POP DS PUSH CS POP ES ENDIF ENDIF ; Move the FATs into position POP DX ; Restore COMMAND address POP BP POP CX ; True address of free memory MOV SI,OFFSET DOSGROUP:MEMSTRT ; Place to move DPBs from MOV DI,WORD PTR [DPBHEAD] ; Place to move DPBs to SUB CX,DI ; Total length of DPBs CMP DI,SI JBE MOVJMP ; Are we moving to higher or ; lower memory? DEC CX ; Move backwards to higher memory ADD DI,CX ADD SI,CX INC CX STD MOVJMP: MOV ES,BP ASSUME ES:DOSGROUP JMP MOVDPB CHARINIT: ASSUME DS:NOTHING,ES:NOTHING ; DS:SI Points to device header MOV [DEVCALL.REQLEN],DINITHL MOV [DEVCALL.REQUNIT],0 MOV [DEVCALL.REQFUNC],DEVINIT MOV [DEVCALL.REQSTAT],0 PUSH ES PUSH BX PUSH AX MOV BX,OFFSET DOSGROUP:DEVCALL PUSH CS POP ES invoke DEVIOCALL2 POP AX POP BX POP ES RET DB 80H DUP(?) INITSTACK LABEL BYTE DW ? MEMSTRT LABEL WORD ADJFAC EQU MEMSTRT-SYSBUF do_ext LAST ENDS