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

📄 doexec.asm

📁 Microsoft MS-DOS6.0 完整源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	push	bx

	cmp	_sigintseg,0	; has ^C been hooked ?
	je	letsgo		; no, do the exec

	push	ds
	mov	dx,_sigintoff	; load system default address
	mov	ds,_sigintseg	; load system default segment
	mov	ax,DOS_setvector shl 8 + 23H ; reset ^C vector (INT 23H)
	callos
	pop	ds		; restore registers
l	letsgo


;
;	IMPORTANT NOTE:
;
;	DOS 3.30 and later allow the user to increase the size of the
;	file handle table.  If the file handle count > 20, then a far
;	segment is allocated to store the table.  This segment must be
;	freed up before the child program is exec-ed.  This code relies
;	on the fact that DOS will free up that far segment if the handle
;	count is set back to 20.  If DOS ever changes, this code will fail.
;
	mov	ax,word ptr [_osmajor]
	xchg	ah,al		; AH = _osmajor, AL = _osminor
	cmp	ax,(3 shl 8) + 30
	jb	pre_DOS330	; _osmajor:_osminor < 3:30?

	mov	bx,20		; IF >= DOS 3.30 THEN
	mov	ah,67h		; Set Handle Count on principle
	callos			; set number of handles to default value
pre_DOS330:

	pop	bx
	pop	dx

;	WARNING - any errors past this point - must go to execpanic

;	now free all blocks of memory belonging to this process
;	except the PSP and new environment block

;	bx = PSP
;	dx = environment segment

l	freemore
	push	bx		; save PSP
	mov	ah,52h		; magic DOS call
	int	21h
	mov	ax,es:[bx-2]	; ax = first arena segment!!!
	pop	bx		; restore PSP

;	ax = current segment to check

l	findused
	mov	es,ax
	inc	ax
	cmp	ax,bx		; is it PSP?
	je	atend		;   yes - skip
	cmp	ax,dx		; is it environment?
	je	atend		;   yes - skip

	cmp	es:[own],bx	; do we own it?
	jne	atend		;   no -skip

	mov	es,ax		; es = must be one past arena header
	callos	freemem		; free up the segment
	jmp	freemore	;   and start over - even if error

l	atend
	add	ax,es:[asiz]	; add in segment size
	jc	freemore	;   error - changed arena - retry
	cmp	es:[sig],'Z'	; last segment?
	jne	findused	;   no - check next segment

;	increase size of PSP to maximum amount available
;
;	bx = PSP

	mov	es,bx		; es= PSP
	mov	bx,-1
	callos	setmem
	callos	setmem		; allocates on second try
	jnc	bigPSP

l	execpanic		; error in exec after memory freed
	mov	dx,word ptr [emsg]	;[1] DS:DX = "Not enough memory"
	mov	ax,word ptr [emsgseg]	;[1]
	mov	ds,ax		;[1]
	callos	message
	mov	ax,DOS_terminate shl 8 + 255
	callos			; error code = 255

l	bigPSP
	mov	ax,es
	add	ax,bx		; bx = size of PSP block
	mov	es:[DOS_maxpara],ax ; set new memory limit in PSP

;	ax = top of PSP segment
;	((sp)) = (exec code size)

	pop	cx		; cx = exec code size
	sub	bx,cx		; reduce PSP size
	jc	execpanic
	sub	ax,cx
	mov	word ptr [target+2],ax ; set up final jump address

;	move the exec code and its data up to hi mem
;
;	ax = exec code segment

	mov	es,ax		; es = exec code segment
	push	es		; save exec code segment

	push	ds		; save DGROUP

	push	cs
	pop	ds		; ds points into code segment
	xor	di,di
	mov	cx,BYTE PTR exesz ;[1] assume exe file
	mov	si,codeOFFSET a
	cmp	flag,0		; .exe or .com?
	je	exe4		;   .exe
	mov	cx,BYTE PTR comsz ;[1]
	mov	si,codeOFFSET b

l	exe4
	rep	movsb		; move code to exec code segment

	pop	ds		; restore DGROUP

	push	ds		;[1] save DGROUP
	mov	cx,[emsgln]	;[1] count of bytes to move
	mov	si,word ptr [emsg]	;[1] DS:SI = start of 3 error messages
	mov	ax,word ptr [emsgseg]	;[1]
	mov	ds,ax		;[1]
	rep	movsb		;[1] move 3 error messages
	pop	ds		;[1] restore DGROUP

	mov	bx,di		; (bx) = offset of data/name (save)
	cmp	flag,0		; .exe or .com?
	jne	com5		;   .com

; for .exe save initial register values

	mov	ax,initss
	stosw
	mov	ax,initsp
	stosw
	mov	ax,initcs
	stosw
	mov	ax,initip
	stosw
l	com5

if	sizeD
	push	ds		; save DGROUP
	lds	si,nam
else
	mov	si,nam
endif

	mov	cx,nlength
	rep	movsb		; move name

if	sizeD
	pop	ds		; restore DGROUP
endif

; exec code and its data are in hi mem. set the dma and fix the psp (the
; command line at offset 80h, and the fcbs)

	mov	es,[_psp]	; psp seg

; set the dma to psp:80h

	push	ds		; save DGROUP
	push	es
	pop	ds		; psp segment
	mov	dx,80h		; default dma=psp:80h
	callos	setdma
	pop	ds		; restore DGROUP

; set up the command line

	mov	di,DOS_cmdline

if	sizeD
	push	ds		; save DGROUP
	lds	si,command
else
	mov	si,command
endif
	mov	cl,[si]		; length of command
	inc	cx		; (ch) = 0 from last rep movsb (name)
	inc	cx		; count byte & terminating <cr>
	rep	movsb		; move the command line into psp:80h

; set up the fcbs

	mov	dx,bx		; (dx) = data/name offset

	mov	di,FCB1		; fcb at offset 5ch
	xchg	ax,cx		; null byte to store
				; (cx) = 0 from last rep movsb (command line)
	mov	cx,20h		; length of 2 fcbs
	rep	stosb		; zero the fcbs
	mov	di,FCB1		; fcb at offset 5ch

if	sizeD
	lds	si,command
else
	mov	si,command
endif
	inc	si		; si points to arg1 (or space before it)
	mov	ax,DOS_fcbparse shl 8 + 1
	callos			; parse filename
	cmp	al,0ffh		; see if invalid drive letter
	je	bad1
	xor	al,al
l	bad1
	mov	bl,al		; first drive letter
	mov	di,FCB2		; second fcb in psp
	mov	ax,DOS_fcbparse shl 8 + 1
	callos			; parse filename
	cmp	al,0ffh		; see if invalid drive letter
	je	bad2
	xor	al,al
l	bad2
	mov	bh,al		; bx = drive letter flags

if	sizeD
	pop	ds		; restore DGROUP
endif

; setup stack in exec code segment

	pop	cx		; exec code segment
	mov	si,dx		; data/name offset in exec code
	add	si,STKSIZ	; push it up to produce a stack
	cmp	flag,0		; .exe or .com? (last frame reference)
	mov	bp,bx		; initial ax
	cli			; disable interrupts until stack set up
	mov	ss,cx
	mov	sp,si
	sti			; temporary stack set up

	jne	join6		;   was .com

	push	dx		; save data offset to init. register values
	add	dx,8		; name offset in hi mem

l	join6

	mov	ax,es		; (ax) = paras from 0:0 to psp:0
	add	ax,10h		; (ax) = paras from 0:0 to parameter block
	mov	bx,100h		; psp:100h is parameter block for load/exec
	mov	es:[bx],ax	; word segment address to load at
	mov	es:[bx+2],ax	; word relocation factor to be applied
	push	ax		; save relocation factor
	mov	ax,DOS_exec shl 8 + 3

;	(ax) = dos code for load/exec (4b03h)
;	(dx) = name offset in exec segment
;	(es:bx) = psp:100 (parameter block)
;	(ds) = DGROUP seg
;	(bp) = initial ax
;
;	di and si are free

	jmp	dword ptr [target] ; and away we go!

;-----------------------------------------------------------------------------

NOMEM	equ	5
BADFORM	equ	6
BADENV	equ	7

execom	macro	lab,fil
l	lab
	push	cs
	pop	ds		; DS = exec code segment

	callos			; overlay parent with child
	jnc	allok&lab

	mov	bx,BADFORM - NOMEM
	cmp	al,E_ifunc	; invalid format
	je	die&lab

	mov	bl,BADENV - NOMEM
	cmp	al,E_badenv	; bad environment
	je	die&lab

	mov	bl,BADFORM - NOMEM
	cmp	al,E_badfmt	; bad format
	je	die&lab

	xor	bx,bx		; NOMEM - NOMEM

l	die&lab
	push	cs
	pop	es		; es = exec code segment

	xor	ax,ax
	mov	cx,-1
	mov	di,BYTE PTR fil&sz	;[2]
	or	bx,bx
	jz	outmsg&lab
	jmp	short nmsg&lab


;	Warning if you change this section above you must
;	leave the following bytes for DOS 2.0 to walk all
;	over without walking on data DOS walks on DS:2E to
;	DS:31  extra slop just incase!

	org	lab + 32h
l	nmsg&lab
	repne	scasb
	inc	di		; skip past message number
	inc	di
	dec	bx
	jnz	nmsg&lab

l	outmsg&lab
	mov	dx,di
	callos	message
	mov	ax,DOS_terminate shl 8 + 255
	callos			; terminate (255)

l	allok&lab
	endm


;-----------------------------------------------------------------------------
;
;	.exe  exec code

	execom	a,exe		; expand for .exe file

	pop	di		; relocation factor
	pop	si		; data offset of initial register values

	lodsw			; initss
	add	ax,di		; relocation factor (paras) from 0:0
	xchg	dx,ax
	lodsw			; initsp
	cli
	mov	ss,dx		; reloc'd ss
	mov	sp,ax
	sti

	lodsw			; initcs
	add	di,ax
	lodsw
	push	di		; save INIT CS
	push	ax		; save INIT IP

	push	es
	pop	ds		; es = ds = PSP
	mov	ax,bp		; ax = valid drive letter flags

xglobal	proc	far
	ret			; force far return to dos int 21h handler
xglobal	endp

z:

;-----------------------------------------------------------------------------
;
;	.com  exec code

	execom	b,com		; expand for .com file

	pop	di		; burn relocation factor (not used)
	mov	bx,cs		; get exec code segment
	mov	ax,es		; get PSP segment
	sub	bx,ax		; bx = size of program area (in paragraphs)

	mov	cl,4
	test	bx,0f000h	; will we lost precision when we shift?
	jz	doit
	mov	bx,1000h	;   yes, set ss:sp = psp:0000
doit:
	shl	bx,cl		; make byte offset from psp:0
	dec	bx
	dec	bx
	cli			; disable interrupts until stack's ok
	mov	ss,ax
	mov	sp,bx		; reserved para offset (stack grows down)
	sti			; enable interrupts; stack's ok now
	mov	word ptr ss:[bx],0 ; put 0000 on top of stack for return

	push	es
	mov	ax,100h
	push	ax		; INIT CS:IP = PSP:100h
	push	es
	pop	ds		; DS = ES = CS = PSP
	mov	ax,bp		; ax = valid drive letter flags

cglobal	proc	far
	ret			; force far return
cglobal	endp

y:

cEnd	nogen


sEnd
	end

⌨️ 快捷键说明

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