MS-DOS/v2.0/source/MSINIT.ASM

408 lines
13 KiB
NASM
Raw Normal View History

1983-08-13 00:53:34 +00:00
; 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