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

📄 tskdos.asm

📁 这是一个关于C++编程开发的算法!
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;
;	CTask - DOS access module.
;
;	Public Domain Software written by
;		Thomas Wagner
;		Patschkauer Weg 31
;		D-1000 Berlin 33
;		West Germany
;
;
; The DOS interrupt (and the related direct disk I/O interrupts) are
; not reentrant. Access to DOS thus has to be channelled such that no
; two tasks use DOS services simultaneously. However, there is one
; exception to this rule. Whenever DOS is waiting for the keyboard, it
; issues a special interrupt, INT 28h, to signal that background
; processing for functions > 0Ch may be performed. This is used in the
; DOS interface for CTask in the following manner:
;
;   A task issuing a DOS interrupt will request one of two resources:
;   "lower_dos" for functions <= 0C, "upper_dos" for functions > 0C.
;   If a task gets access to "lower_dos", it will also request the
;   "upper_dos" resource to lock out other tasks from interrupting.
;   This "upper_dos" resource is shortly released on each INT 28, and
;   then immediately reclaimed, with task priority temporarily raised
;   to the maximum value. The first task waiting to execute a 
;   function > 0C will thus be scheduled to execute the request, but
;   the resource will be reassigned to the INT 28 handler as soon as
;   this request terminates, so the waiting task will not be delayed too
;   long.
;
; There are two additional safety measures which have to be taken to
; avoid getting into conflicts with other resident background programs,
; especially the DOS PRINT background spooler:
;
;   Before requesting any resource, the status of the DOS critical section
;   flag is checked. If this flag is set, the task is made waiting for
;   the flag to be cleared.
;   Only the task that set the flag will be allowed access to DOS.
;
;   Before actually executing the request, the status of the DOS in-use
;   flag is checked. If this flag is set, the task enters a busy waiting
;   loop, calling the scheduler so that the processor is not tied up.
;
; NOTE: The method for checking the status of DOS is described in-depth
;	in the book "The MS-DOS Encyclopedia" from Microsoft Press, in
;	the chapter on TSR programming. The logic in this module was
;	developed without the help of this book, so if you compare
;	the code here with the routines in the Encyclopedia, you may
;	notice that not all re-entry conditions are checked here.
;	According to my experience with debugging TSR's and CTask, the
;	logic should be sufficient for all but the most obscure TSR's.
;	If you want to be completely on the safe side, you might consider
;	adding the more thorough checks listed in the Encyclopedia.
;
;
	name	tskdos
;
	.model	large
;
	public	_tsk_install_dos
	public	_tsk_remove_dos
;
;
	include	tsk.mac
;
CSECT		=	2ah	; Critical Section Interrupt
get_in_use_flag	=	34h	; DOS-function to get in_use_flag address
;
;
intseg	segment at 0
		org	20h*4
termoff		dw	?	; program terminate vector
termseg		dw	?
		org	21h*4
idosoff		dw	?	; dos interrupt
idosseg		dw	?
		org	25h*4
absreadoff	dw	?	; absolute disk read
absreadseg	dw	?
		org	26h*4
abswriteoff	dw	?	; absolute disk write
abswriteseg	dw	?
		org	27h*4
keepoff		dw	?	; Terminate but stay resident
keepseg		dw	?
		org	28h*4
idleoff		dw	?	; dos idle interrupt
idleseg		dw	?
		org	CSECT*4
csectoff	dw	?	; dos critical section
csectseg	dw	?
;
intseg	ends
;
;----------------------------------------------------------------------------
;
;       externally defined variables
;
        extrn   _tsk_current: dword
        extrn   _lower_dos: resource
        extrn   _upper_dos: resource
        extrn   _critical: flag
;
;       externally defined functions
;
        extrn   _asm_request_resource: far
        extrn   _asm_release_resource: far
        extrn   _asm_set_flag: far
        extrn   _asm_clear_flag: far
        extrn   _asm_wait_flag_clear: far
        extrn   _asm_remove_tasker: far
        extrn   scheduler: far
;
	.data
;
;
term_err_msg	db	0dh,0ah,"Program terminated - CTask uninstalled"
		db	0dh,0ah,'$'
;
idle_active	db	0    		; Idle-Interrupt active
dos310		db	0		; DOS version >= 3.10
;
;
	.data?
;
in_use		dd	?		; Adress of DOS in-use-flag
in_error	dd	?		; Adress of DOS error-mode-flag
;
;
idle_ss		dw	?		; Stack save
idle_sp		dw	?
;
		dw	256 dup(?)	; Stack for IDLE-Interrupt
local_stack	label	word
;
	.code
;
;	Original Interrupt-Entries
;
savtermoff	dw	?		; Terminate vector save
savtermseg	dw	?
;
savdos		label	dword		; original DOS-Entry
savdosoff	dw	?
savdosseg	dw	?
;
savidle		label	dword		; original IDLE-Entry
savidleoff	dw	?
savidleseg	dw	?
;
savcsect	label	dword		; Critical Section save
savcsectoff	dw	?
savcsectseg	dw	?
;
savabsread	label	dword		; Absolute Disk Read save
savabsreadoff	dw	?
savabsreadseg	dw	?
;
savabswrite	label	dword		; Absolute Disk Write save
savabswriteoff	dw	?
savabswriteseg	dw	?
;
savkeepoff	dw	?		; Terminate resident vector save
savkeepseg	dw	?
;
critsect_active	db	0		; DOS Critical Section active
ctask_active	db	0		; CTask DOS call active
crit_task	dd	?		; Task requesting critical section
;
;
dos	macro
	pushf
	cli
	call	cs:savdos
	endm
;
;---------------------------------------------------------------------------
;
	.code
;
;
;	void tsk_install_dos (void)
;
;		Install DOS handler
;
;       Invoked by tasker_class::tasker_class
;
_tsk_install_dos	proc
;
;
;	Get the address of DOS's in_use-flag. This flag indicates that
;	DOS is already active. This might happen if there are other
;	background tasks, like popups or print spoolers, active in
;	parallel to CTask.
;	This is also the address of the critical error flag in DOS. Beginning 
;	with DOS 3.10 the flag is located one byte before the in_use_flag.
;	With older DOS versions, we would have to search through DOS for the 
;	address. This is omitted here, but you could include the code
;	for pre 3.1 versions from pages 378-379 of the MS-DOS Encyclopedia.
;	
	mov	ah,get_in_use_flag
	int	21h
	mov	word ptr in_use,bx
	mov	word ptr in_use+2,es
	mov	word ptr in_error+2,es
;
	push	bx
	mov	ah,30h
	int	21h
	pop	bx
	cmp	al,3
	jb	not_dos3
	cmp	al,0ah
	je	not_dos3	; OS/2 compatibility box
	cmp	ah,10
	jb	not_dos3
	inc	dos310
	dec	bx
	mov	word ptr in_error,bx
	jmp	short save_ints
;
not_dos3:

;
;	Save old interrupt vectors
;
save_ints:
        push    es
	xor	ax,ax
	mov	es,ax
;
        assume  es:intseg
;
	mov	ax,termoff		; DOS
	mov	savtermoff,ax
	mov	ax,termseg
	mov	savtermseg,ax
;
	mov	ax,idosoff		; DOS
	mov	savdosoff,ax
	mov	ax,idosseg
	mov	savdosseg,ax
;
	mov	ax,idleoff		; IDLE
	mov	savidleoff,ax
	mov	ax,idleseg
	mov	savidleseg,ax
;
	mov	ax,csectoff		; Critical Section
	mov	savcsectoff,ax
	mov	ax,csectseg
	mov	savcsectseg,ax
;
	mov	ax,absreadoff		; Absolute Disk read
	mov	savabsreadoff,ax
	mov	ax,absreadseg
	mov	savabsreadseg,ax
;
	mov	ax,abswriteoff		; Absolute Disk write
	mov	savabswriteoff,ax
	mov	ax,abswriteseg
	mov	savabswriteseg,ax
;
	mov	ax,keepoff		; Terminate Resident
	mov	savkeepoff,ax
	mov	ax,keepseg
	mov	savkeepseg,ax
;
;	Enter new Interrupt-Entries
;
	cli
	mov	idosoff,offset dosentry		; DOS-Entry
	mov	idosseg,cs
	mov	idleoff,offset idleentry	; Idle-Entry
	mov	idleseg,cs
	mov	termoff,offset terminate_int	; Terminate Process Entry
	mov	termseg,cs
	mov	csectoff,offset critsectint	; Critical Section Entry
	mov	csectseg,cs
	mov	keepoff,offset keep_int		; Keep Process Entry
	mov	keepseg,cs
	mov	absreadoff,offset absread_int	; Absolute Disk Read Entry
	mov	absreadseg,cs
	mov	abswriteoff,offset abswrite_int	; Absolute Disk Write Entry
	mov	abswriteseg,cs
	sti
        pop     es
;
	ret
;
	assume	es:nothing
;
_tsk_install_dos	endp
;
;
;	void tsk_remove_dos (void)
;
;       Un-install DOS handler
;
_tsk_remove_dos	proc
;
;	Delete resources & flags
;
        push    es
	xor	ax,ax
	mov	es,ax
;
        assume  es:intseg
;
;	Restore interrupt entries
;
	cli
	mov	ax,savtermoff
	mov	termoff,ax
	mov	ax,savtermseg
	mov	termseg,ax
;
	mov	ax,savdosoff
	mov	idosoff,ax
	mov	ax,savdosseg
	mov	idosseg,ax
;
	mov	ax,savidleoff
	mov	idleoff,ax
	mov	ax,savidleseg
	mov	idleseg,ax
;
	mov	ax,savcsectoff
	mov	csectoff,ax
	mov	ax,savcsectseg
	mov	csectseg,ax
;
	mov	ax,savabsreadoff
	mov	absreadoff,ax
	mov	ax,savabsreadseg
	mov	absreadseg,ax
;
	mov	ax,savabswriteoff
	mov	abswriteoff,ax
	mov	ax,savabswriteseg
	mov	abswriteseg,ax
;
	mov	ax,savkeepoff
	mov	keepoff,ax
	mov	ax,savkeepseg
	mov	keepseg,ax
;
	sti
;
        pop     es
	ret
;
	assume	es:nothing
;
_tsk_remove_dos	endp
;
;
;---------------------------------------------------------------------------
;
;	Stack-Offsets relative to BP
;
caller_cs	=	4		; Caller's CS
caller_flags	=	6		; Caller's Flags
;
;
;---------------------------------------------------------------------------
;
;	INT 25: Absolute Disk Read 
;
;	This interrupt is translated into INT 21, function C0.
;	This function is re-translated later after the necessary resources
;	have been requested.
;
absread_int:
	mov	ah,0c0h
	jmp	short absrw_int
;
;
;---------------------------------------------------------------------------
;
;	INT 26: Absolute Disk Write
;
;	This interrupt is translated into INT 21, function C1.
;	This function is re-translated later after the necessary resources
;	have been requested.
;
abswrite_int:
	mov	ah,0c1h
;
;	Interrupts 25 und 26 leave the flag-word on the stack.
;	Since flags are removed in normal processing, the flag-word
;	has to be duplicated on the stack here.
;
absrw_int:
	push	bp			; reserve space
	push	bp			; save BP
	mov	bp,sp
	sti
	push	ax
	mov	ax,4[bp]		; Move return offset, segment down
	mov	2[bp],ax
	mov	ax,6[bp]
	mov	4[bp],ax
	mov	ax,8[bp]		; duplicate flags
	mov	6[bp],ax
	pop	ax
	push	caller_flags[bp]
	jmp	short dosentry_2
;
;---------------------------------------------------------------------------
;
;	INT 27: Terminate But Stay Resident Interrupt
;
;	This interrupt is translated to INT 21, function 31.
;
keep_int:
	push	bp
	mov	bp,sp
	push	caller_flags[bp]	; flags (bp-2)
	sti				; allow interrupts
;
	add	dx,0fh			; last addr + 0f to round
	sub	dx,caller_cs[bp]	; minus CS (= PSP)
	mov	cl,4
	shr	dx,cl			; div 16 = paragraphs

	mov	ax,3100h		; Keep process
	jmp	short dosentry_2
;
;---------------------------------------------------------------------------
;
;	INT 20: Terminate Program interrupt
;
;	This interrupt is translated to INT 21, function 0.
;
terminate_int:
	mov	ah,0
;
;	fall through
;
;---------------------------------------------------------------------------
;
;	INT 21: DOS-Interrupt
;
dosentry        proc    far
;
;	Save registers
;
	push	bp
	mov	bp,sp
	push	caller_flags[bp]	; flags (bp-2)
;
dosentry_2:
	push	es
	push    ds
	push	dx
	push	cx
	push	bx
	push	ax
	push	si
	push	di
	cld
	mov	bx,SEG dgroup
	mov	ds,bx
	mov	es,bx
;
;
;	Here we check if the DOS critical region is active.
;	If yes, this means that some outside background process has
;	started DOS (most likely DOS PRINT).
;	To avoid busy waiting, we wait for the "critical" flag to be
;	cleared, if this is *not* the task that set the flag.
;	The task that set the critical task is *not* made waiting.
;
wait_crit_loop:
	cli
	cmp	cs:critsect_active,0
	je	no_crit
	mov	ax,word ptr cs:crit_task
	cmp	word ptr _tsk_current,ax
	jne	wait_crit
	mov	ax,word ptr cs:crit_task+2
	cmp	word ptr _tsk_current+2,ax
	je	no_crit
;
wait_crit:
	xor	ax,ax

⌨️ 快捷键说明

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