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

📄 doexec.asm

📁 Microsoft MS-DOS6.0 完整源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	page	,132
	title	doexec	-- (xenix) exec a child process
;***
;doexec.asm - execute a child process
;
;	Copyright (c) 1985-1988, Microsoft Corporation.  All rights reserved.
;
;Purpose:
;	defines _doexec() - execute a child process (overlay existing process)
;	This is complicated and involves some knowledge of DOS
;	arena headers.
;
;*******************************************************************************

?DF	=	1	; tell cmacros.inc we want to define our own segments

.xlist
include	version.inc
include	cmacros.inc
include	msdos.inc
.list

assumesdata	macro	seg	;;[1] Newer versions of CMACROS reject
assumes	seg,DGROUP		;;[1]
endm				;;[1]

createSeg _TEXT, code,	word,	public, CODE,	<>
createSeg _DATA, data,	word,	public, DATA,	DGROUP
createSeg EXEC,	eseg,	word,	common, DATA,	DGROUP

defGrp	DGROUP			; define DGROUP

codeOFFSET equ	offset _TEXT:
dataOFFSET equ	offset DGROUP:



l	macro	nam		;;[1] Conditionally make label public
nam:				;;[1]
	endm			;;[1]


arena	struc			; first 5 bytes of the arena header
	sig	db	0		; 'M' or 'Z' for last block
	own	dw	0		; PSP value of owner process or 0 if free
	asiz	dw	0		; size of block (not including header)
arena	ends

extrn	b$EX_MSG_BEG:FAR	;[1]
extrn	b$EX_MSG_END:FAR	;[1]

sBegin	data
assumesdata	ds		;[1]

externW	_psp			; psp segment
externB	_osmajor 		; dos major version number
externW	_sigintseg 		; SIGINT default signal handler (segment)
externW	_sigintoff 		; SIGINT default signal handler (offset)

globalW	_p_overlay,2 		; OLD_P_OVERLAY value

staticW	freepsp,0 		; arena of last free segment contiguous with PSP



staticW emsg,<2+ OFFSET b$EX_MSG_BEG> ;[1] +2 to skip first msg number
staticW emsgseg,<SEG b$EX_MSG_BEG>    ;[1]
staticW	emsgln,<OFFSET b$EX_MSG_END>;[1] must subtract emsg from it

staticD	target,0 		; for long jump to 'exec code'

sEnd


FCB1	=	5ch		; offset in psp
FCB2	=	6ch

DOS2CMD= 280h			; size of DOS 2.0 non-resident COMMAND.COM


externP execve

sBegin	eseg

	dd	execve		; force in execve() if called from spawnve

sEnd

sBegin	code
assumes	cs,code
assumesdata	ds		;[1]


page
;***
;_doexec - execute a child process (overlay existing)
;
;Purpose:
;
;Entry:
;
;Exit:
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************

cProc	_doexec,<PUBLIC>,<si,di>

	parmw	flag
	parmdp	nam
	parmw	nlength
	parmdp	command
	parmdp	envblock
	parmw	elength
	parmw	siz
	parmw	initss
	parmw	initsp
	parmw	initcs
	parmw	initip
	parmw	fsiz

cBegin

;	exec overlays the current process using its PSP and all memory
;	above it.

	push	ds		; save DGROUP

;	check for trashed arena before we go on - will assume OK from here on
;	DGROUP is on the top of the stack

	assumes	ds,nothing
l	checkmem
	pop	ds		; restore DGROUP
	assumesdata	ds	;[1]

	mov	bx,-1		; request max memory
	callos	allocmem	; will always fail
	cmp	al,E_arena
	je	ov0		;   arena is trashed

;	find out how much contiguous memory there is that is either free
;	or belongs to the current process

	mov	bx,[_psp]
	mov	dx,bx		; dx = current owner
	dec	bx		; bx = current arena header
	xor	cx,cx		; last free block in contiguous area

	push	ds		; save DGROUP
l	maxloop
	assumes	ds,nothing
	mov	ds,bx		; ds = current arena
	mov	ax,ds:[own]
	cmp	ax,dx		; do we own it?
	je	maxadd		;   yes - count it
	or	ax,ax		; is it free?
	jne	maxend		;   no - end of contiguous memory

	mov	cx,bx		; last free block of memory

l	maxadd
	inc	bx
	add	bx,ds:[asiz]
	jc	checkmem	;   carry - assuming arena is trashed
	mov	al,ds:[sig]	; get arena signature
	cmp	al,'M'		; are we at end of memory?
	je	maxloop		;   no - have good next block
	cmp	al,'Z'		;
	jne	checkmem	;   unknown sig byte - assuming arena is trashed

;	bx = top of contiguous area for current process
;	cx = last free segment contiguous with PSP

l	maxend
	sub	bx,dx		; bx = size
	pop	ds		; restore DS
	assumesdata	ds	;[1]
	mov	[freepsp],cx	; save last free segment contiguous with PSP

	cmp	[_osmajor],2	; see if 2.x or above
	ja	nohole		;   3.x or above, don't need hole for loader

	sub	bx,DOS2CMD+1	; leave 280h paras (10K) for the system's loader
	jnc	nohole		;   enough space

;-----	memory overflow or error before user memory is released

l	ov
	mov	ax,E_nomem	; not enough memory
l	ov0

	mov	AH,4CH		;[1]get code to terminate
	INT	21H		;[1]immediate termination

;-----

l	nohole

; see how big the exec code will be. it must sit in hi mem. it consists of
; code between a: and z: below (or b: and y: for .coms), the filename, (in the
; case of .exe files) a para of data (initial register values), and some room
; (160 bytes) for a local stack


STKSIZ=	160
exesz=	z-a
exeln=	exesz	+ STKSIZ	; .exe loader size + stack
comsz	=	y-b
comln=	comsz	+ STKSIZ	; .com loader size + stack

	push	bx		; save max length possible


	sub	[emsgln],offset b$EX_MSG_BEG ;[1] compute message length
	mov	ax,[emsgln]	;[1] need emsgln in calculations
	

	add	ax,BYTE PTR exeln	;[2] assume .exe
	cmp	flag,0
	je	join0		;   was .exe
___tmp=	comln-exeln
	add	ax,BYTE PTR ___tmp	;[2] was .com
l	join0

	mov	cl,4
	add	ax,nlength	; plus filename
	add	ax,0fh		; exec code rounded up to next para
	shr	ax,cl		; (ax) = paras for exec code

	mov	dx,elength	; new env length (in bytes)
	add	dx,0fh		; env rounded up to next para
	shr	dx,cl		; (dx) = paras for new env

	pop	bx		; restore the maximum length to bx

;	ax = exec code + data size
;	dx = environment size
;	bx = PSP contiguous size

	sub	bx,dx		; reduce PSP by environment segment
	jbe	ov

	sub	bx,2		; reduce by 2 (arena header + DOS 4.0 slop)
	jc	ov

;	bx = PSP contiguous size

	mov	cx,siz		; cx = assumed .exe size

	cmp	flag,0		; .exe or .com?
	je	join1		;   was .exe

	mov	cx,fsiz		; size of .com child in paras
	inc	cx		; plus para for stack
	jz	ov

l	join1
	add	cx,10h		; child must have a PSP
	jc	ov

;	ax = exec code + data size
;	cx = minimum size of child
;	bx = PSP contiguous size

	cmp	bx,cx		; enough for child?
	jb	ov		;   no

	push	ax		; save exec code size
	push	dx		; save env size

;	allocate and link all free memory in the system
;	assume the arena is good here and all errors are not enough memory

	xor	cx,cx		; cx = free link

l	allocloop
	mov	bx,1		; allocate 1 paragraph block
	callos	allocmem
	jc	allocall	;   all linked up

	mov	es,ax		; es = segment to allocate
	mov	bx,-1		; bx = maximum request
l	allocretry
	callos	setmem		; grow segment
	jc	allocretry	;  force it to be allocated

	mov	es:[0],cx	; save last free block
	mov	cx,es		; cx = current free link
	mov	dx,bx		; dx = size of last block
	jmp	allocloop	; keep allocating

l	allocall
	mov	bx,dx

;	es = cx = free segment linked list
;	bx = size of last free block

	cmp	[_osmajor],2	; check for DOS 2.0
	jne	allocenv	;   no - just try allocing environment

	sub	bx,DOS2CMD+1	; size to cut back
	jnc	shrinkdos2

;-----	release all "free" blocks because of error

l	freefree 		; free all linked up "free" memory
	jcxz	allfree
	mov	es,cx
	mov	cx,es:[0]	; next free block
	callos	freemem
	jnc	freefree	; keep freeing linked blocks

l	allfree			; if freemem error, just give up
	jmp	ov		; fail with no memory error

;-----

l	shrinkdos2
	callos	setmem
	jc	freefree	; any error at this point is no memory

;	es = cx = free segment linked list
;	bx = size of last free block

l	allocenv
	pop	dx		; dx = environment size
	push	dx
	inc	dx
	inc	dx		; dx = envsize + 2 (for arena header + DOS 4.0)
	sub	bx,dx
	jnc	haveenv		; have space in this block for environment

;	no space for environment in this block - try end of PSP contiguous area

	mov	ax,[freepsp]	; ax = last free segment in PSP-contiguous area
	or	ax,ax
	jz	tryotherfree	;   none here - try other free blocks

	inc	ax		; convert arena address to segment address
	mov	es,ax
	mov	bx,-1
	callos	setmem		; find size of segment
	cmp	al,E_nomem
	jne	freefree	;   must be something like arena trashed
	sub	bx,dx		; enough room?
	jnc	haveenv		;   yes - do actual environment allocation
				; else go try somewhere else

;	try other free blocks if above attempts fail

l	tryotherfree
	jcxz	allfree
	mov	ax,cx
;
;	dx = environment size in paragraphs + 2 (for arena hdr + DOS 4.0 slop)
;	cx = pointer to beginning of "free" list (segment address)
;	ax = pointer into "free" list (segment address)
;

l	tryotherloop
	dec	ax		;[1] AX = header address (temporarily)
	mov	es,ax		;    header of current free block
	mov	bx,es:[asiz]	;    size of current free block (in header)
	inc	ax		;[1] convert header addr back into seg addr
	mov	es,ax		;[1] AX = ES = segment address
	sub	bx,dx		; will environment fit?
	jnc	haveenv		;   yes - do actual environment allocation
	mov	ax,es:[0]	; else go on to next free block
	or	ax,ax		; end of list?
	jz	freefree	;   yes - not enough memory; clean up and fail
	jmp	short tryotherloop ; keep trying

;	es = segment to shrink for environment
;	bx = size to which to shrink chosen "free" segment

l	haveenv
	callos	setmem
	jc	freefree	; any error at this point is no memory

	pop	bx
	callos	allocmem	; allocate environment segment
	jc	freefree	; any error at this point is no memory

;	ax = environment segment

	mov	es,[_psp]
	mov	bx,es
	mov	es:[DOS_envp],ax ; new env segment
	mov	es,ax
	xor	di,di		; es:di points to new env

if	sizeD
	push	ds		; save DGROUP
	lds	si,envblock
else
	mov	si,envblock
endif
	mov	cx,elength
	rep	movsb		; move env to new segment
if	sizeD
	pop	ds		; restore DGROUP
endif

	mov	dx,es		; dx = environment segment

;	bx = PSP
;	dx = environment segment

	push	dx		; save needed registers

⌨️ 快捷键说明

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