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

📄 cwswapr.asm

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
.386

;*****************************
;* Equates                   *
;*****************************

SWAPPERERROR	EQU	9999
WEDGEOFFSET	EQU	180h

;*****************************
;* Public declarations       *
;*****************************

PUBLIC	CWSwap_
;PUBLIC	SWPRUNCMD
;PUBLIC	OverLay
;PUBLIC	O_RUNX

;PUBLIC	Done

;*****************************
;* External data             *
;*****************************

;EXTRN	__retni:FAR
;EXTRN	__parclen:FAR
;EXTRN	__parc:FAR

;*****************************
;* SPAWN Structures          *
;*****************************

;
;	--- Version 3.3 92-03-30 21:39 ---
;
;	SPAWN.ASM - Main function for memory swapping spawn call.
;
;	Public Domain Software written by
;		Thomas Wagner
;		Ferrari electronic GmbH
;		Beusselstrasse 27
;		D-1000 Berlin 21
;		Germany
;
;
; Assemble with
;
; tasm  /DPASCAL spawn,spawnp  		- Turbo Pascal (Tasm only), near
; tasm  /DPASCAL /DFARCALL spawn,spawnp	- Turbo Pascal (Tasm only), far
; ?asm  spawn;		  		- C, default model (small)
; ?asm  /DMODL=large spawn  		- C, large model
;
;	NOTE:	For C, change the 'model' directive below according to your
;		memory model, or define MODL=xxx on the command line.
;
;		For Turbo C Huge model, you must give /DTC_HUGE on the
;		command line, or define it here.
;
;
; Main function:
;

;   C:
;   	int do_spawn (int swapping,
;		      char *execfname,
;		      char *cmdtail,
;		      unsigned envlen,
;		      char *envp,
;		      char *stdin,
;		      char *stdout,
;		      char *stderr)
;
;   Parameters:
;
;	swapping - swap/spawn/exec function:
;			< 0: Exec, don't swap
;		  	  0: Spawn, don't swap
;			> 0: Spawn, swap
;			     in this case, prep_swap must have
;			     been called beforehand (see below).
;
;	cmdtail - command tail for EXEC.
;
;	execfname - name and path of file to execute.
;
;	envlen - length of environment copy (may be 0).
;
;	envp -  pointer to environment block (must be aligned on
;		paragraph boundary). Unused if envlen is 0.
;
;	'cmdtail' and 'execfname' must be zero terminated, even when
;	calling from Pascal. For Pascal, the length byte of the string
;	is ignored.
;
;   Returns:
;	0000..00ff:	Returncode of EXECed program
;	03xx:		DOS-Error xx calling EXEC
;	0500:		Swapping requested, but prep_swap has not
;			been called or returned an error
;	0501:		MCBs don't match expected setup
;	0502:		Error while swapping out
;	06xx:		DOS-Error xx on redirection
;
;
; For swapping, the swap method must be prepared before calling do_spawn.
;
;   C:
;	int prep_swap (unsigned method, char *swapfname)
;
;   Parameters:
;
;	method	- bit-map of allowed swap devices:
;			01 - Allow EMS
;			02 - Allow XMS
;			04 - Allow File swap
;			10 - Try XMS first, then EMS
;			40 - Create file as "hidden"
;			80 - Use "create temp" call for file swap
;		       100 - Don't preallocate file
;		       200 - Check for Network, don't preallocate if net
;		      4000 - Environment block will not be swapped
;
;	swapfname - swap file name (may be undefined if the
;		    "method" parameters disallows file swap).
;		    The string must be zero terminated, even
;		    when calling from Pascal. For Pascal, the
;		    length byte of the string is ignored.
;
;   Returns:
;
;   	A positive integer on success:
;		1 - EMS swap initialized
;		2 - XMS swap initialized
;		4 - File swap initialized
;	A negative integer on failure:
;		-1 - Couldn't allocate swap space
;		-2 - The spawn module is located too low in memory
;
;--------------------------------------------------------------------------
;
;
;	Set NO_INHERIT to FALSE if you don't want do_exec to mess with
;	the handle table in the PSP, and/or you do want the child process
;	to inherit all open files.
;	If NO_INHERIT is TRUE, only the first five handles (the standard
;	ones) will be inherited, all others will be hidden. This allows
;	the child to open more files, and also protects you from the child
;	messing with any open handles.
;	NO_INHERIT should always be TRUE if you use functions to extend
;	the handle table (for more than 20 open files).
;
;	Set REDIRECT to FALSE if you do not want do_spawn to support redirection.
;
;
;
FALSE		=	0
TRUE		=	NOT FALSE
;
NO_INHERIT	=	TRUE
REDIRECT	=	FALSE
;
;
;
;	IFNDEF	MODL
;	.model	small,c
;	%out	small model
;	ELSE
;%	.model	MODL,c
;%	%out	MODL model
;	ENDIF
;
;ptrsize	=	@DataSize
ptrsize	=	1
;
;	extrn	_psp: word
;
;	public	do_spawn
;	public	prep_swap
;	public	swap_prep
;
stacklen	=	256		; local stack
;
;	"ems_size" is the EMS block size: 16k.
;
ems_size	=	16 * 1024	; EMS block size
ems_parasize	=	ems_size / 16	; same in paragraphs
ems_shift	=	10		; shift factor for paragraphs
ems_paramask	=	ems_parasize-1	; block mask
;
;	"xms_size" is the unit of measurement for XMS: 1k
;
xms_size	=	1024		; XMS block size
xms_parasize	=	xms_size / 16	; same in paragraphs
xms_shift	=	6		; shift factor for paragraphs
xms_paramask	=	xms_parasize-1	; block mask
;
;	Method flags
;
USE_EMS		=	01h
USE_XMS		=	02h
USE_FILE	=	04h
XMS_FIRST	=	10h
HIDE_FILE	=	40h
CREAT_TEMP	=	80h
NO_PREALLOC	=	100h
CHECK_NET	=	200h
DONT_SWAP_ENV	=	4000h
;
;	Return codes
;
RC_TOOLOW	=	0102h
RC_BADPREP	=	0500h
RC_MCBERROR	=	0501h
RC_SWAPERROR	=	0502h
RC_REDIRFAIL	=	0600h
;
EMM_INT		=	67h
;
;	The EXEC function parameter block
;
exec_block	struc
envseg	dw	?		; environment segment
ppar	dw	?		; program parameter string offset
pparseg	dw	?		; program parameter string segment
fcb1	dw	?		; FCB offset
fcb1seg	dw	?		; FCB segment
fcb2	dw	?		; FCB offset
fcb2seg	dw	?		; FCB segment
exec_block	ends
;
;	Structure of an XMS move control block
;
xms_control	struc
lenlo		dw	?	; length to move (doubleword)
lenhi		dw	?
srchnd		dw	?	; source handle (0 for standard memory)
srclo		dw	?	; source address (doubleword or seg:off)
srchi		dw	?
desthnd		dw	?	; destination handle (0 for standard memory)
destlo		dw	?	; destination address (doubleword or seg:off)
desthi		dw	?
xms_control	ends
;
;	The structure of the start of an MCB (memory control block)
;
mcb		struc
id		db	?
owner		dw	?
paras		dw	?
mcb		ends
;
;	The structure of an internal MCB descriptor.
;	CAUTION: This structure is assumed to be no larger than 16 bytes
;	in several places in the code, and to be exactly 16 bytes when
;	swapping in from file. Be careful when changing this structure.
;
mcbdesc		struc
addr		dw	?	; paragraph address of the MCB
msize		dw	?	; size in paragraphs (excluding header)
swoffset	dw	?	; swap offset (0 in all blocks except first)
swsize		dw	?	; swap size (= msize + 1 except in first)
num_follow	dw	?	; number of following MCBs
		dw	3 dup(?) ; pad to paragraph (16 bytes)
mcbdesc		ends
;
;	The variable block set up by prep_swap
;
prep_block	struc
xmm		dd	?		; XMM entry address
first_mcb	dw	?		; Segment of first MCB
psp_mcb		dw	?		; Segment of MCB of our PSP
env_mcb		dw	?		; MCB of Environment segment
noswap_mcb	dw	?		; Env MCB that may not be swapped
noswap2_mcb	dw	?		; Wedge MCB that may not be swapped
noswap3_mcb	dw	?		; File handle MCB that may not be swapped
ems_pageframe	dw	?		; EMS page frame address
handle		dw	?		; EMS/XMS/File handle
total_mcbs	dw	?		; Total number of MCBs
swapmethod	db	?		; Method for swapping
sp_swapfilename	db	81 dup(?)	; Swap file name if swapping to file
prep_block	ends
;
;----------------------------------------------------------------------
;
;	Since we'll be moving code and data around in memory,
;	we can't address locations in the resident block with
;	normal address expressions. MASM does not support
;	defining variables with a fixed offset, so we have to resort
;	to a kludge, and define the shrunk-down code as a structure.
;	It would also be possible to use an absolute segment for the
;	definition, but this is not supported by the Turbo Pascal linker.
;
;	All references to low-core variables from low-core itself
;	are made through DS, so we define a text macro "lmem" that
;	expands to "ds:". When setting up low core from the normal
;	code, ES is used to address low memory, so this can't be used.
;
lmem	equ	<ds:>
;
;	The memory structure for the shrunk-down code, excluding the
;	code itself. The code follows this block.
;	The start of this block is the PSP.
;
parseg		struc
		db	18h dup(?)
psp_handletab	db	20 dup(?)	; Handle Table
psp_envptr	dw	?		; Environment Pointer
		dd	?
psp_handlenum	dw	?		; Number of Handles (DOS >= 3.3)
psp_handleptro	dw	?		; Handle Table Pointer (DOS >= 3.3)
psp_handleptrs	dw	?		; Handle Table Pointer Segment
		db	5ch-38h dup(?)	; start after PSP
;
save_ss		dw	?		; 5C - saved global ss
save_sp		dw	?		; 5E - saved global sp
xfcb1		db	16 dup(?)	; 60..6F - default FCB
xfcb2		db	16 dup(?)	; 70..7F - default FCB
zero		dw	?		; 80 Zero command tail length (dummy)
;
expar		db	TYPE exec_block dup (?) ; exec-parameter-block
spx		dw	?		; saved local sp
div0_off	dw	?		; divide by zero vector save
div0_seg	dw	?
lhandlesave	db	26 dup(?)	; saved handle table and pointer
		IF	REDIRECT
lredirsav	db	6 dup(?)	; saved redirection handles
lstdinsav	dw	3 dup(?)	; duped redirection handles
		ENDIF
filename	db	82 dup(?)	; exec filename
progpars	db	128 dup(?)	; command tail
		db	stacklen dup(?)	; local stack space
mystack		db	?
lprep		db	TYPE prep_block dup(?)	; the swapping variables
lcurrdesc	db	TYPE mcbdesc dup(?)	; the current MCB descriptor
lxmsctl		db	TYPE xms_control dup(?)
eretcode	dw	?		; EXEC return code
retflags	dw	?		; EXEC return flags
cgetmcb		dw	?		; address of get_mcb
dtasave		DD	?		; address of original DTA
GoToWedge	DD	?		; address of wedge code
;
parseg	ends
;
param_len	=	((TYPE parseg + 1) / 2) * 2	; make even
codebeg		=	param_len
;

;*****************************
;* Code begins               *
;*****************************

SWAP_TEXT	SEGMENT PARA PRIVATE USE16 'CODE'

ASSUME	cs:SWAP_TEXT

CodeStart	=	$

;lookie	DW	keep_paras

;
;------------------------------------------------------------------------
;
lowcode_begin:
;
;       The following parts of the program code will be moved to
;	low core and executed there, so there must be no absolute
;	memory references.
;	The call to get_mcb must be made indirect, since the offset
;	from the swap-in routine to get_mcb will not be the same
;	after moving.
;
;
;	get_mcb allocates a block of memory by modifying the MCB chain
;	directly.
;
;	On entry, lcurrdesc has the mcb descriptor for the block to
;		  allocate.
;
;	On exit,  Carry is set if the block couldn't be allocated.
;
;	Uses 	AX, BX, CX, ES
;	Modifies lprep.first_mcb
;
get_mcb	proc	near
;
	mov	ax,lmem lprep.first_mcb
	mov	bx,lmem lcurrdesc.addr
;
getmcb_loop:
	mov	es,ax
	cmp	ax,bx
	ja	gmcb_abort		; halt if MCB > wanted
	je	mcb_found		; jump if same addr as wanted
	add	ax,es:paras		; last addr
	inc	ax			; next mcb
	cmp	ax,bx
	jbe	getmcb_loop		; Loop if next <= wanted
;
;
;	The wanted MCB starts within the current MCB. We now have to
;	create a new MCB at the wanted position, which is initially
;	free, and shorten the current MCB to reflect the reduced size.
;
	cmp	es:owner,0
	jne	gmcb_abort		; halt if not free
	mov	bx,es			; current
	inc	bx			; + 1 (header doesn't count)
	mov	ax,lmem lcurrdesc.addr
	sub	ax,bx			; paragraphs between MCB and wanted
	mov	bx,es:paras		; paras in current MCB
	sub	bx,ax			; remaining paras
	dec	bx			; -1 for header
	mov	es:paras,ax		; set new size for current
	mov	cl,es:id		; old id
	mov	es:id,4dh		; set id: there is a next
	mov	ax,lmem lcurrdesc.addr
	mov	es,ax
	mov	es:id,cl		; and init to free
	mov	es:owner,0
	mov	es:paras,bx
;
;	We have found an MCB at the right address. If it's not free,
;	abort. Else check the size. If the size is ok, we're done
;	(more or less).
;
mcb_found:
	mov	es,ax
	cmp	es:owner,0
	je	mcb_check		; continue if free
;
gmcb_abort:
	stc
	ret
;
mcb_check:
	mov	ax,es:paras		; size
	cmp	ax,lmem lcurrdesc.msize	; needed size
	jae	mcb_ok			; ok if enough space
;
;	If there's not enough room in this MCB, check if the next
;	MCB is free, too. If so, coalesce both MCB's and check again.
;
	cmp	es:id,4dh
	jnz	gmcb_abort		; halt if no next
	push	es			; save current
	mov	bx,es
	add	ax,bx
	inc	ax			; next MCB
	mov	es,ax
	cmp	es:owner,0		; next free ?
	jne	gmcb_abort		; halt if not
	mov	ax,es:paras		; else load size
	inc	ax			; + 1 for header
	mov	cl,es:id		; and load ID
	pop	es			; back to last MCB
	add	es:paras,ax		; increase size
	mov	es:id,cl		; and store ID
	jmp	mcb_check		; now try again
;
;	The MCB is free and large enough. If it's larger than the
;	wanted size, create another MCB after the wanted.
;
mcb_ok:
	mov	bx,es:paras
	sub	bx,lmem lcurrdesc.msize
	jz	mcb_no_next		; ok, no next to create
	push	es
	dec	bx			; size of next block
	mov	ax,es
	add	ax,lmem lcurrdesc.msize
	inc	ax			; next MCB addr
	mov	cl,es:id		; id of this block
	mov	es,ax			; address next
	mov	es:id,cl		; store id
	mov	es:paras,bx		; store size
	mov	es:owner,0		; and mark as free
	pop	es			; back to old MCB
	mov	es:id,4dh		; mark next block present
	mov	ax,lmem lcurrdesc.msize	; and set size to wanted
	mov	es:paras,ax
;
mcb_no_next:
	mov	es:owner,cx		; set owner to current PSP
;
;	Set the 'first_mcb' pointer to the current one, so we don't
;	walk through all the previous blocks the next time.
;	Also, check if the block we just allocated is the environment
;	segment of the program. If so, restore the environment pointer
;	in the PSP.
;
	mov	ax,es
	mov	lmem lprep.first_mcb,ax
;	cmp	lmem lprep.env_mcb,ax
;	jne	getmcb_finis
;	inc	ax
;	mov	lmem psp_envptr,ax
;
getmcb_finis:
	clc
	ret				; all finished (whew!)
;
get_mcb	endp
;
;
ireti:
	iret
;
;
;	The actual EXEC call.
;	Registers on entry:
;		BX	= paragraphs to keep (0 if no swap)
;		CX 	= length of environment to copy (words) or zero
;		DS:SI	= environment source
;		ES:DI	= environment destination
;		(ES = our low core code segment)
;
;
;	copy environment buffer down if present
;
doexec:
;	jcxz	noenvcpy
;	rep movsw
;
noenvcpy:
	push	es			; DS = ES = low core = PSP
	pop	ds
	or	bx,bx
	jz	no_shrink
;
;	first, shrink the base memory block down.
;
;	int	3

IFDEF SHRINKPSP
	mov	ah,04ah
	int	21h                     ; resize memory block
ENDIF
;
;	Again walk all MCBs. This time, all blocks owned by the
;	current process are released.
;
	mov	si,lmem lprep.first_mcb
	or	si,si
	jz	no_shrink
	mov	dx,lmem lprep.psp_mcb
	mov	bx,dx
	inc	bx			; base PSP (MCB owner)
	mov	di,lmem lprep.noswap_mcb
	mov	cx,lmem lprep.noswap2_mcb
;
free_loop:
	cmp	si,dx
	je	free_next		; don't free base block
	cmp	si,di
	je	free_next
	cmp	si,cx
	je	free_next
	cmp	si,lmem lprep.noswap3_mcb
	je	free_next

	mov	es,si
	cmp	bx,es:owner		; our process?
	jne	free_next		; next if not
;	cmp	si,lmem lprep.env_mcb	; is this the environment block?
;	jne	free_noenv
;	mov	ds:psp_envptr,0		; else clear PSP pointer
;
free_noenv:
	inc	si
	mov	es,si
	dec	si
	mov	ah,049h			; free memory block
	int	21h
;
free_next:
	mov	es,si
	cmp	es:id,4dh		; normal block?
	jne	free_ready		; ready if end of chain
	add	si,es:paras		; start + length
	inc	si			; next MCB
	jmp	free_loop
;
free_ready:
no_shrink:
	mov	ah,2fh		; get DTA address
	int	21h
	mov	WORD PTR lmem dtasave,bx	; save original DTA
	mov	WORD PTR lmem dtasave+2,es
	mov	ax,ds
	mov	es,ax
	mov	WORD PTR lmem GoToWedge,0
	mov	WORD PTR lmem GoToWedge+2,fs
;

;	int	3

	mov	dx,filename		; params for exec
	mov	bx,expar

⌨️ 快捷键说明

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