⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process.a86

📁 一个dos操作系统DRDOS的源码
💻 A86
📖 第 1 页 / 共 3 页
字号:
	mov	word ptr [bx],0		; zero on user stack
	pop	ds

	lea	si,EXE_IP[si]		; point at IP
	lodsw ! stosw			; copy it, and get in AX for return
	movsw				; copy EXE_CS too
	jmp	return_AX_CLC		; all went OK

start_child_go:
;--------------
;
;	Set the initial registers conditions for a DOS process
;	Check the validity of the drives specified in FCB 1 and FCB 2
;	of the loading PSP and initialise the AX register accordingly.
;
	xor	dx,dx			; start with valid drives
	mov	es,current_psp		; Get the PSP Address and check
	push	dx
	mov	al,PSP_FCB1		; if the drive specifier for FCB1
	call	valid_drive		; is invalid set AL to FF
	pop	dx
	 jz	reg_s10
	mov	dl,0FFh
reg_s10:
	push	dx
	mov	al,PSP_FCB2		; if the drive specifier for FCB2
	call	valid_drive		; is invalid set AH to FF
	pop	dx
	 jz	reg_s20
	mov	dh,0FFh
reg_s20:
	mov	di,EXE_SP[si]		; Get the new stack address
	push	di			; save it
	mov	cl,4
	shr	di,cl			; convert SP to para's
	 jnz	reg_s30
	mov	di,1000h		; if 0k make it 64k
reg_s30:
	mov	ax,load_max		; find top of prog area
	sub	ax,EXE_SS[si]		; find para's left for stack
	cmp	di,ax			; SP too high ?
	pop	di			; assume OK
	 jb	reg_s40
	mov	di,ax			; no, so lower SP
	shl	di,cl			; convert to bytes
reg_s40:
	mov	cx,EXE_SS[si]		; CX:DI -> initial stack
	les	si,dword ptr EXE_IP[si]	; get initial CS:IP
	cli
	mov	ax,current_psp		; AX = PSP we are going to use
	xchg	ax,dx
	mov	indos_flag,0		; zap the indos flag
if 0
	mov	ss,cx			; switch to new USER stack
	mov	sp,di
	push	es
	push	si			; CS:IP on USER stack
	mov	ds,dx			; DS = ES = PSP we are exec'ing
	mov	es,dx
	xor	bx,bx			; BX = zero, set flags
	sti
	retf				; lets go!
else
	jmpf	exec_stub
endif

eject
;	*****************************
;	***    DOS Function 00    ***
;	***   Terminate Process	  ***
;	*****************************
;
;	This code is executed for both INT 20 and INT 21/00 and they both
;	implicitly set the current PSP to the users calling CODE segment.
;	This overwrites the correct value held in CURRENT_PSP.
;
	Public	func00
func00:
	mov	byte ptr int21AX,0	; force return code of zero
	les	di,int21regs_ptr
	mov	bx,es:reg_CS[di]	; normally users CS is current_psp
	mov	ax,current_psp		; but application call here
	cmp	ax,bx			;  with an Int 20 at funny moments
	 je	func4c			;  (I have "NOW!" in mind)
	mov	es,bx			; fiddle CS PSP parent so we return to
	mov	PSP_PARENT,ax		;  current_psp then fiddle current_psp
	mov	current_psp,bx		;  to be user CS

;	*****************************
;	***    DOS Function 4C    ***
;	***   Terminate Process	  ***
;	*****************************
;
	Public	func4C
func4c:
	mov	ax,current_psp		; the current PSP is terminating
	mov	term_psp,ax		;  so set term_psp and load_psp
	mov	load_psp,ax		;  to that value

f31_term:				; INT27 and INT21/31 Entry Point
	push	ds
	mov	ds,term_psp
	xor	ax,ax
	mov	es,ax			; Copy the Three interrupt vectors
	mov	si,offset PSP_TERM_IP	; saved on process creation from the 
	mov	di,INT22_OFFSET		; termination PSP to the interrupt
	mov	cx,6			; vector table.
	rep	movsw
	mov	ax,8200h		; call the REDIR hooks to clean up
	int	2ah			; first the server hook
	mov	ax,I2F_PTERM		; then call cleanup code
	int	2fh			; via magic INT 2F call
	pop	ds			; back to PCMODE data
	mov	al,byte ptr int21AX	; Get the User Return Code
	mov	user_retcode,al		; Save the User Ret Code and Set the 
	mov	al,TERM_NORMAL		; Now get the Termination Type
	xchg	al,exit_type		; and exchange with the default value
	mov	system_retcode,al	; EXIT_TYPE is set so Non-Zero values
					; when a Special Form of termination
					; takes place. ie INT 27h

; But thence came VTERM, and it looked upon terminating the ROOT process,
; and saw that it was good.
;
; VTERM gives access to the cmdline by doing func31 and becoming a TSR. You can
; then re-invoke it with a hot-key but the next time you invoke the cmdline
; option does a func4C in whatever context it was re-invoked in. This will
; either blow away an application, or try and terminate the ROOT process.


	mov	es,term_psp		; make the terminating PSP's
	mov	ax,es:PSP_PARENT	;  parental PSP into the
	mov	bx,current_psp
	cmp	ax,bx			; Is the user trying to terminate
	 jz	f4C_20			;  the ROOT DOS process if YES then
					;  skip freeing resources (VTERM)

	mov	cx,load_psp		; if we are TSR'ing
	 jcxz	f4C_20			;  skip the free

	push	ax			; save parental PSP
	mov	es,bx			; ES = current PSP
	xor	bx,bx			; start with handle zero
f4C_10:
	mov	ah,MS_X_CLOSE		; close this handle
	call	dos_entry		; so freeing up PSP entry
	inc	bx			; onto next handle
	cmp	bx,PSP_XFNMAX		; done them all yet?
	 jb	f4C_10
	mov	FD_FUNC,FD_EXIT		; Must Close all Open FCB's
	call	fdos_nocrit
	push	ds 			; We have already closed all the
	pop	es			; open MSNET files we know about
	mov	ax,I2F_PCLOSE		; but we will call the MSNET
	int	2fh			; extention's cleanup code anyway

	push ss ! pop ds		; reload DS with data segment

	mov	bx,current_psp		; free all memory associated
	call	free_all		;  with this PSP

	pop	ax			; recover parental PSP
f4C_20:
	mov	current_psp,ax		; make current PSP = parental PSP

;
;	Function 4C requires a different termination technique. It needs
;	to return to the parent process on the stack that was used on the
;	function 4B. The interrupt structure has been forced to contain
;	the interrupt 22 vector. Therefore all registers will contain
;	their original values unless the stack has been overlayed
;
;
	cli				; Stop anybody interfering
	mov	indos_flag,0		; Force the INDOS_FLAG to 0 for PCTOOLS
	mov	error_flag,0		; and SideKick Plus.
	mov	ax,retcode
	mov	ds,current_psp
	mov	ss,ds:PSP_USERSS	; Retrieve the entry SS and SP from
	mov	sp,ds:PSP_USERSP	;  the PSP and return with all
	mov	bp,sp			;  registers as on user entry
	mov	ss:reg_AX[bp],ax	; Set AX to the Process RETCODE
	xor	ax,ax
	mov	ds,ax
	mov	ax,ds:word ptr .INT22_OFFSET
	mov	ss:reg_IP[bp],ax   	; PSP_TERM_IP
	mov	ax,ds:word ptr .INT22_OFFSET+WORD
	mov	ss:reg_CS[bp],ax   	; PSP_TERM_CS
	mov	ss:reg_FLAGS[bp],0b202h	; force flags to 0F202h
					;  ie Interrupts enabled and
					;  NEC processor Mode Switch SET
					; changed to B202 to have clear
					; NT flag (DPMS doesn't like it)
	jmp	int21_exit		; Jump to the Exit routine	


eject
;	*****************************
;	***    DOS Function 4D    ***
;	*** Get Sub-Func Ret-Code ***
;	*****************************
;
	Public	func4D
func4D:
	xor	ax,ax			; Zero the return code for
	xchg	ax,retcode		; subsequent calls and return the
	jmp	return_AX_CLC		; saved value to the caller

eject
;****************************************
;*					*
;*	Process Control Subroutines	*
;*					*
;****************************************

;
; We need a full pathname for the application to inherit in it's environment.
; MS_X_EXPAND can't do the job - it returns a PHYSICAL path which may be
; unreachable (bug circa DRDOS 3.41).
; On Entry:
;	ES:DX	Points to the Original FileName
; On Exit:
;	None
;

get_filename:
	push	ds
	push	es			; swap ES and DS
	pop	ds
	pop	es
	mov	si,dx			; DS:SI -> filename
	mov	di,offset load_file	; ES:DI -> local buffer
	mov	cx,MAX_PATHLEN-4	; max length (allow for d:\,NUL)
	lodsw				; get 1st two chars in filename
	cmp	ah,':'			; is a drive specified ?
	 je	get_filename10
	dec si ! dec si			; forget we looked
	mov	al,ss:current_dsk	; and use the default drive
	add	al,'A'
get_filename10:
	stosb				; put in the drive
	and	al,1fh			; convert from ASCII to 1 based
	xchg	ax,dx			; keep in DL for ms_x_curdir
	mov	ax,':'+256*'\'		; make it "d:\"
	stosw
	lodsb				; do we start at the root ?
	cmp	al,'\'
	 je	get_filename20
	cmp	al,'/'
	 je	get_filename20
	dec	si			; forget we looked for a root
	push	si			; save where we were
	mov	ah,MS_X_CURDIR
	mov	si,di			; ES:SI -> buffer
	call	dos_entry		; get current directory
	xor	ax,ax
	repne	scasb			; look for NUL
	xchg	ax,si			; AX = start of path
	pop	si			; recover pointer to source
	 jne	get_filename30
	dec	di			; point at NUL
	cmp	ax,di			; are we at the root ?
	 je	get_filename20
	mov	al,'\'
	stosb				; no, append a '\'
get_filename20:
	rep	movsb			; copy the remainder of the string
get_filename30:
	xor	ax,ax
	stosb				; ensure we are terminated
	push	es
	pop	ds			; DS back to nornal
	ret


;
;	BUILD_ENV determines the size of the Source environment and 
;	allocates memory and finally copies it.
;
;	ON entry AX contains the segment address of the environment
;	to be used or zero if the parents is to be copied.
build_env:
	mov	es,ax			; Assume user has specified the
	or	ax,ax			; environment to be used. If AX is
	 jnz	b_e10			; 0000 then use the current environment
	mov	es,current_psp
	mov	cx,PSP_ENVIRON		; Current Environment Segment 
	mov	es,cx			; If the current environment segment
	mov	di,cx			; is zero then return a size of
	 jcxz	b_e35			; zero bytes

b_e10:
	xor	ax,ax			; Now determine the Environment size
	mov	cx,32*1024		; CX is maximum size
	mov	di,ax
b_e20:
	repnz	scasb			; Look for two zero bytes which
	 jcxz	b_e40			; mark the end of the environment
	cmp	al,es:byte ptr [di]	; continue search till the end is found
	 jnz	b_e20
	dec	di			; DI == Environment Size - 2

b_e30:
	mov	si,offset load_file	; Get the Load pathname length
	call	strlen			; String length returned in CX
	inc	cx			; Add in the terminator

	push	bx
	mov	bx,cx			; Get the String Length
	add	bx,di			; Add the environment size
	add	bx,15 + 4		; and convert to paragraphs
	shr bx,1 ! shr bx,1
	shr bx,1 ! shr bx,1
	mov	load_envsize,bx		; Save the Environment Size
	call	mem_alloc		; allocate the memory
	pop	bx
	 jc	b_e50
	mov	load_env,ax		; Save the Environment location
	push cx ! push di		; Save STRLEN and Offset
	push	ds			; Save DS
	push	es
	mov	es,ax			; Point ES at the NEW environment
	pop	ds			; Point DS at the Old environment
	mov	cx,di			; Get the environment size
	xor si,si ! mov di,si		; Initialize the pointers
	rep	movsb 			; and copy. Nothing moves if CX == 0
	pop	ds

	pop di ! pop cx			; Get the string pointers
	xor ax,ax ! stosw		; Add terminating zeros
	inc ax ! stosw			; Initialise the String COUNT field


	mov	si,offset load_file	; and size information and 
	rep	movsb			; copy the load filename.
b_e35:
	clc				; Return with no errors	
	ret
b_e40:
	mov	ax,ED_ENVIRON		; Invalid environment
b_e50:
	stc
	ret


;	Calculate the new program segment prefix
;	save:	bx -> Handle
calc_psp:
	push	bx
	mov	si,offset exe_buffer	; Calculate the Minimum and Maximum
					; amount of memory required to load
	call	image_size		; the program image (Returned in DX)
	add	dx,PSPLEN/16		; Do not forget the PSP
	mov	cx,dx			; Save the Load Image Size
	mov	bx,dx			; BX will be memory required
	mov	ax,ED_MEMORY
	add	dx,EXE_MINPARA[si]	; force DX to be the minimum and if
	 jc	cp_exit			;  more than 1 MByte exit with error
	add	bx,EXE_MAXPARA[si]	; add the maximum amount of memory
	 jnc	c_p10			;  to the load image size
	mov	bx,0FFFFh		;  clipping to 1 MByte
c_p10:
if HILOAD
	test	mem_strategy,80h	; HILOAD ON ?
	 jz	c_p15
	mov	bx,dx			; use minimum amount of memory
	add	bx,40h			; add 1 K extra for luck (stack etc)
	call	mem_alloc		; Allocate the requested block
	 jc	cp_exit			; if alloc fails exit with error
	push	ds
	mov	ds,ax
	mov	bx,0ffffh		; find how much we can grow this block
	call	mem_setblock
	call	mem_setblock		; then grow it to that size
	mov	ax,ds			; ax = base of the block again
	pop	ds
	jmps	c_p20			
c_p15:
endif
	call	mem_alloc		; allocate size and if error occurs
	 jnc	c_p20			; then the maximum size is greater
	cmp	bx,dx			; than the minimum required
	 jc	cp_exit			; if not exit with error

	call	mem_alloc		; Allocate what we've got
	 jc	cp_exit			; Exit on error	
c_p20:
	mov	load_psp,ax		; Save the load paragraph == PSP
	add	bx,ax			; Save the block top
	mov	load_top,bx
	mov	load_max,bx		; save top of block for SP adjust
	add	ax,PSPLEN/16		; Set AX to be the Relocation Paragraph

	cmp	exe_loadhigh,0		; Should the Load Image be
	 jz	c_p30			; forced into to High Memory with the
	mov	ax,bx			; data area and PSP loaded low.
	sub	ax,cx			; Subtract the Load Image Size from
	mov	cx,PSPLEN/16		; the top of allocated memory and
	add	ax,cx			; load at that address.	

c_p30:
	mov	load_image,ax		; Save the Address of the Load Image
cp_exit:
	pop	bx
	ret

eject
;LOADIMAGE:
;
;	This function reads in the load image of the file into memory
;	(Paragraph DI) asserting the relocation factor (SI) if any relocation
;	items exist in the file. The size of the load image is calculated 
;	using the EXE_SIZE and EXE_FINAL fields enough memory exists at DI
;	to load the image. The valid .EXE header has been moved to exe_buffer.
;
;	Read in and relocate the EXE image
;	entry:	bx -> handle
;		di = load segment
;		si = reloc segment
;	exit:	cf = 1, ax = Error Code if load fails
;
loadimage:
;---------
	call	readfile		; Read the load image into memory
	 jc	load_error		; Exit if error

	mov	cx,exe_buffer+EXE_RELCNT
					; get number of reloc entries
	 jcxz	load_done		; if none there, forget it .COM's
					; drop out here because RELCNT is zero

	push	cx			; seek to 1st relocation entry
	xor	cx,cx			;  in the file
	mov	dx,exe_buffer+EXE_RELOFF
	mov	ax,(MS_X_LSEEK*256)+0
	call	dos_entry
	pop	cx
	 jc	load_error		; stop on error
	xchg	ax,cx			; AX = # items to relocate
	call	reloc_image		; relocate the image
	 jc	load_error
load_done:
	mov	load_handle,-1
	mov	ah,MS_X_CLOSE		; and close the loadfile
	jmp	dos_entry		; close the com file

load_error:				; Error exit from relocation
	push	ax			; save error code
	call	load_done		; close the file
	pop	ax			; recover error code
	stc				; say we had an error
	ret
	
;
;	The following code will relocate CX items from the open handle BX
;
reloc_image:
; On Entry:
;	BX = handle
;	AX = # items to relocate
;	SI = relocation segment
;	DI = relocation fixup
;
; On Exit:
;	CY clear if OK, else AX = error code


	push ds ! pop es		; ES -> Local Buffer Segment
	mov	dx,offset reloc_buf	; DX -> Local Buffer Offset

	mov	cx,RELOC_CNT		; AX -> Buffer Size
	shl	cx,1			; convert reloc size from paras
	shl	cx,1			;  to an item count
	sub	ax,cx			; buffer. which contains a maximum
	 jnc	reloc_i10		; of RELOC_SIZE items.
	add	cx,ax			; CX contains # of items to Read
	xor	ax,ax			; AX contains # left to read
reloc_i10:
	push	ax			; save # items left to read
	push	cx			; and # reloc to read
	shl cx,1 ! shl cx,1		; calculate # byte to read
	mov	ah,MS_X_READ		; relocation buffer.
	call	dos_entry
	pop	cx
	 jnc	reloc_i20		; Exit on Error
	pop	cx			; clean up stack
	ret				; return with error

reloc_i20:
	push	bx			; save handle
	xchg	ax,di			; AX = reloc fixup

	mov	bx,dx			; Get buffer offset
reloc_i30:
	add	word ptr 2[bx],ax	; Correct segment to Load Seg
	les	di,dword ptr [bx]	; es:di = reloc entry
	add	es:[di],si		; add reloc seg into image
	add	bx,4			; and update for next entry

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -