mirror of https://github.com/microsoft/MS-DOS.git
408 lines
13 KiB
NASM
408 lines
13 KiB
NASM
|
; 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
|
|||
|
|