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

📄 tskdos.asm

📁 一个嵌入式实时操作系统源码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
	xor	ax,ax
	mov	es,ax
;
        assume  es:intseg
;
;	Restore interrupt entries
;
	cli
	test	tsk_instflags,IFL_VIDEO
	jz	rem_novid2
	mov	ax,savvidoff
	mov	vidoff,ax
	mov	ax,savvidseg
	mov	vidseg,ax
;
rem_novid2:
	test	tsk_instflags,IFL_DISK
	jz	rem_nodsk2
	mov	ax,savdiskoff
	mov	diskoff,ax
	mov	ax,savdiskseg
	mov	diskseg,ax
	mov	ax,savfdiskoff
	mov	fdiskoff,ax
	mov	ax,savfdiskseg
	mov	fdiskseg,ax
;
rem_nodsk2:
	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
;
	IF	(DEBUG AND DEB_DOSTRBUF)
	mov	ax,savmuxoff
	mov	muxoff,ax
	mov	ax,savmuxseg
	mov	muxseg,ax
	ENDIF
;
	IF	DEBUG AND DEB_DOSTRBUF
	mov	ax,savdpmioff
	mov	dpmioff,ax
	mov	ax,savdpmiseg
	mov	dpmiseg,ax
	ENDIF
;
	sti
;
        pop     es
	IFDEF	LOAD_DS
	pop	ds
	ENDIF
	ret
;
	assume	es:nothing
;
tsk_remove_dos	endp
;
;
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
;
;
;	INT 10: Video BIOS interrupt
;
@videntry	proc	far
;
	call	tsk_switch_stack
	callp	request_cresource,<<ds,#video>,0,0>
	mov	ax,caller_flags[bp]
	mov	vid_flags,ax
	call	tsk_old_stack
	pushf
	cli
	call	savvid
	call	tsk_switch_stack
	mov	ax,vid_flags
	mov	caller_flags[bp],ax
	callp	release_resource,<<ds,#video>>
	iret
;
@videntry	endp
;
;---------------------------------------------------------------------------
;
;
;	INT 13 and INT 40: Disk I/O BIOS interrupt
;
@diskentry	proc	far
;
	call	tsk_switch_stack
	test	dl,80h			; fixed disk ?
	jz	disk_floppy		; jump if not
	callp	request_cresource,<<ds,#hdisk_io>,0,0>
	call	tsk_old_stack
	pushf
	cli
	call	savdisk
	call	tsk_switch_stack
	callp	release_resource,<<ds,#hdisk_io>>
	mov	ax,entry_flags[bp]
	mov	caller_flags[bp],ax
	iret
;
disk_floppy:
	callp	request_cresource,<<ds,#fdisk_io>,0,0>
	call	tsk_old_stack
	pushf
	cli
	call	savdisk
	call	tsk_switch_stack
	callp	release_resource,<<ds,#fdisk_io>>
	mov	ax,entry_flags[bp]
	mov	caller_flags[bp],ax
	iret
;
@diskentry	endp
;
@fdiskentry	proc	far
;
	call	tsk_switch_stack
	callp	request_cresource,<<ds,#fdisk_io>,0,0>
	call	tsk_old_stack
	pushf
	cli
	call	savfdisk
	call	tsk_switch_stack
	callp	release_resource,<<ds,#fdisk_io>>
	mov	ax,entry_flags[bp]
	mov	caller_flags[bp],ax
	iret
;
@fdiskentry	endp
;
;---------------------------------------------------------------------------
;
;	Stack-Offsets relative to BP
;
d_func	=	-2
;
;---------------------------------------------------------------------------
;
;	INT 25: Absolute Disk Read 
;
;	This interrupt is channeled through the normal DOS-function
;	processing, with function = 0x25 and special flag set.
;	It is re-translated later after the necessary resources
;	have been requested. INT 25 is handled like a function > 0C.
;	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.
;
absread_int:
	sti
	push	bp			; reserve space
	push	bp			; save BP
	mov	bp,sp
	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
	pop	bp
	call	tsk_switch_stack
	mov	ax,2501h
	mov	cx,ax
	jmp	dosentry_2
;
;
;---------------------------------------------------------------------------
;
;	INT 26: Absolute Disk Write
;
;	This interrupt is channeled through the normal DOS-function
;	processing, with function = 0x26 and special flag set.
;	It is re-translated later after the necessary resources
;	have been requested. INT 26 is handled like a function > 0C.
;	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.
;
abswrite_int:
	sti
	push	bp			; reserve space
	push	bp			; save BP
	mov	bp,sp
	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
	pop	bp
	call	tsk_switch_stack
	mov	ax,2601h
	mov	cx,ax
	jmp	short dosentry_2
;
;---------------------------------------------------------------------------
;
;	INT 27: Terminate But Stay Resident Interrupt
;
;	This interrupt is translated to INT 21, function 31.
;
keep_int:
	call	tsk_switch_stack
;
	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
	mov	save_ax[bp],ax
	mov	cx,ax
	jmp	short dosentry_2
;
;---------------------------------------------------------------------------
;
;	INT 20: Terminate Program interrupt
;
;	This interrupt is translated to INT 21, function 4c.
;
terminate_int:
	call	tsk_switch_stack
	mov	ax,4c00h
	mov	save_ax[bp],ax
	mov	cx,ax
	jmp	short dosentry_2
;
;---------------------------------------------------------------------------
;
;	INT 21: DOS-Interrupt
;
@dosentry        proc    far
;
;	First, check for those special DOS functions that may be called
;	even if DOS is busy. We don't want to block anyone from making
;	those calls, lest we might kill the system.
;
	cmp	ah,33h		; set/get break flag
	je	non_block
	cmp	ah,50h		; set PSP
	je	non_block
	cmp	ah,51h		; get PSP
	je	non_block
	cmp	ah,62h
	je	non_block
	cmp	ah,64h
	jne	blocking
non_block:
	jmp	savdos
;
blocking:
	call	tsk_switch_stack
	xor	cl,cl
	mov	ch,ah
;
dosentry_2:
	IF	DEBUG AND (DEB_DOSTRACE OR DEB_DOSTRBUF)
	push	ax
	push	bx
	push	es
	push	si
	cli
	mov	bx,tr_ptr
	mov	tr_buffer.tr_ax[bx],ax
	mov	ax,save_bx[bp]
	mov	tr_buffer.tr_bx[bx],ax
	mov	ax,save_ds[bp]
	mov	tr_buffer.tr_ds[bx],ax
	les	si,tsk_glob_rec.current_task
	mov	tr_buffer.tr_tcb_o[bx],si
	mov	tr_buffer.tr_tcb_s[bx],es
	mov	al,es:t_indos[si]
	mov	tr_buffer.tr_tindos[bx],al
	les	si,tsk_glob_rec.dos_vars
	mov	ax,es:[si+psp_offset]		; current PSP
	mov	tr_buffer.tr_psp[bx],ax
	les	si,in_error
	mov	al,byte ptr es:[si]
	mov	tr_buffer.tr_inerr[bx],al
	les	si,tsk_glob_rec.dos_in_use
	mov	al,byte ptr es:[si]
	mov	tr_buffer.tr_indos[bx],al
	mov	al,idle_active
	mov	tr_buffer.tr_idle[bx],al
	xor	al,al	
	mov	tr_buffer.tr_flags[bx],al
	cmp	lower_dos.rcount,0
	je	trw_nolo
	or	tr_buffer.tr_flags[bx],1
	mov	ax,word ptr lower_dos.rowner
	cmp	tr_buffer.tr_tcb_o[bx],ax
	jne	trw_nolo
	mov	ax,word ptr lower_dos.rowner + 2
	cmp	tr_buffer.tr_tcb_s[bx],ax
	jne	trw_nolo
	or	tr_buffer.tr_flags[bx],2
trw_nolo:
	cmp	upper_dos.rcount,0
	je	trw_noup
	or	tr_buffer.tr_flags[bx],4
	mov	ax,word ptr upper_dos.rowner
	cmp	tr_buffer.tr_tcb_o[bx],ax
	jne	trw_noup
	mov	ax,word ptr upper_dos.rowner + 2
	cmp	tr_buffer.tr_tcb_s[bx],ax
	jne	trw_noup
	or	tr_buffer.tr_flags[bx],8
trw_noup:
	IF	DEBUG AND DEB_DOSTRBUF
	add	bx,TYPE trrec
	cmp	bx,TR_ENTRIES * TYPE trrec
	jb	trw_nowrap
	xor	bx,bx
trw_nowrap:
	mov	tr_ptr,bx
	inc	tr_count
	ENDIF
	pop	si
	IF	DEBUG AND DEB_DOSTRACE
	push	cx
	push	dx
	callp	tsk_vcprintf,<<ds,#tr_string>,<ds,/tr_buffer[bx]>>
	pop	dx
	pop	cx
	ENDIF
	sti
	pop	es
	pop	bx
	pop	ax
	ENDIF
;
	push	cx		; BP-2: func in CH, special flag in CL
	or	cl,cl
	jnz	dosent_x	; no function check if special
;
;	Check if this is a special 'get dos version' call to determine
;	if CTask is resident.
;
;	A special call has
;
;		AX = 3000h
;
;		BX = 1234h - Get global variable block address
;	    then
;		DS:DX = pointer to version string
;	    or
;		BX = 1235h - CTask internal function
;	    then
;		CX = function code
;
;	Function codes for internal functions:
;
;		2300h	Schedule
;		2301h	Yield
;
	cmp	ax,3000h
	jne	no_spdos
	cmp	bx,1234h
	jb	no_spdos
	je	get_globvars
	cmp	bx,1235h
	ja	no_spdos
	cmp	save_cx[bp],MIN_SPFUNC
	jb	no_spdos
	cmp	save_cx[bp],MAX_SPFUNC
	ja	no_spdos
	call	@special_function
	jmp	short spec_ret
;
get_globvars:
	cmp	dx,0fff0h
	jae	no_spdos
	push	ds
	mov	si,dx
	mov	ds,save_ds[bp]
	mov	di,offset tsk_glob_rec
	mov	cx,8
	repe cmpsb
	pop	ds
	jz	is_spdos
	jmp	short no_spdos
;
;	Special version call returns global variable block address
;	in BX (offset) and CX (segment).
;
is_spdos:
	mov	save_bx[bp],offset tsk_glob_rec
	mov	save_cx[bp],@CTASK_DATA
;
spec_ret:
	add	sp,2
	call	tsk_old_stack
	mov	ax,cs:dos_version
	clc
	iret
;
;---------------------------------------------------------------------------
;
;
no_spdos:
	mov	ax,d_func[bp]
        or	ah,ah			; terminate?
        jne     dosent_x
        mov     save_ax[bp],4c00h	; translate to fn 4c, retcode 0
        mov     d_func[bp],4c00h
;
;	Now the real fun begins.
;
dosent_x:
	sti				; Interrupts allowed now
;
;	DL is used as an "emergency" marker. If nonzero, no resources
;	are to be requested, and the in-dos flag is not to be checked.
;	There is an "emergency" if the task is marked as owning
;	DOS resources, but re-enters INT 21.
;
	xor	dl,dl
	les	bx,tsk_glob_rec.current_task
	test	es:t_indos[bx],OWN_UPPER OR OWN_LOWER
	jz	no_reenter		; no trouble if task doesn't own DOS
;
	call	@dosbusy		; this sets DL nonzero if busy
	jnz	no_reenter		; Don't release resources if busy
;
;	If the task owns DOS resources, but DOS is not busy, something
;	strange is going on (this case should have been handled by the
;	'schedent' routine). Anyway, we assume that DOS is right about
;	not being busy, and release the resources. Although the resources
;	will be requested again a few instructions later, this is sensible
;	to give other tasks that might be waiting on the resource a chance
;	to execute.
;
	call	@relres
	xor	dl,dl
;
;	The preliminaries are done with, we now have to distinguish
;	between functions 00-0C and 0D-FF.
;
no_reenter:
	mov	ax,d_func[bp]
	cmp	ah,0ch
	jbe	lower_funcs
	jmp	upper_funcs
;
;
;	Functions 00-0C
;
lower_funcs:
;
;	first, request the "lower_dos" resource unless this is an emergency.
;
	or	dl,dl
	jnz	lower_emergency
	callp	request_resource,<<ds,#lower_dos>,0,0>
;
;	we have it, now let's get the upper_dos resource, too
;
	callp	request_resource,<<ds,#upper_dos>,0,0>
;
	les	bx,tsk_glob_rec.current_task
	mov	es:t_indos[bx],OWN_UPPER or OWN_LOWER
;
;	both resources gained, now we may execute the function if dos is free
;
	call	@wait_dos_free
;
;	Set the scheduler entry function
;
	cli
	mov	word ptr es:sched_ent_func[bx],offset @schedent
	mov	word ptr es:sched_ent_func+2[bx],cs
	sti
;
lower_emergency:
	add	sp,2
	push	caller_flags[bp]
	popf
	call	tsk_old_stack
;
	calldos				; execute function
;
;	Now we have to release the resources, unless DOS still indicates
;	that it is busy. This would indicate that a critical error has
;	occurred, and DOS processing is not really complete.
;
	call	tsk_switch_stack
;
	call	@dosbusy
	jnz	no_relc			; return if DOS still busy
;
;	Clear the flags in the TCB, and the scheduler entry function.
;
	les	bx,tsk_glob_rec.current_task
	cli
	mov	es:t_indos[bx],0
	mov	word ptr es:sched_ent_func[bx],0
	mov	word ptr es:sched_ent_func+2[bx],0
	sti
;
	callp	release_resource,<<ds,#upper_dos>>
	callp	release_resource,<<ds,#lower_dos>>
;
;	All done, restore registers and return.
;
no_relc:
	cli
	mov	ax,entry_flags[bp]
	mov	caller_flags[bp],ax
	iret
;
;--------------------------------------------------------------------------
;
;	Functions 0D and above
;
upper_funcs:
;
;	first, request the "upper_dos" resource unless this is an emergency.
;
	or	dl,dl
	jnz	upper_emergency
;
	callp	request_resource,<<ds,#upper_dos>,0,0>
;
	les	bx,tsk_glob_rec.current_task
	mov	es:t_indos[bx],OWN_UPPER
;
;	resource gained, now we may execute the function if dos is free
;
	call	@wait_dos_free
;
;	Set the scheduler entry function
;
	cli
	mov	word ptr es:sched_ent_func[bx],offset @schedent
	mov	word ptr es:sched_ent_func+2[bx],cs
	sti
;
upper_emergency:
	cmp	byte ptr d_func[bp],0
	jne	no_term
	mov	ax,save_ax[bp]
	cmp	ah,31h		; terminate resident?
	jne	ckfunc1
	jmp	term_resident
ckfunc1:
	cmp	ax,4b00h	; spawn new process?
	jne	ckfunc2
	jmp	terminate
ckfunc2:
	cmp	ah,4ch		; terminate program?
	jne	no_term
	jmp	terminate
;
no_term:
;
;	Filter special-functions 25/26 (Absolute Read/Write)
;
	pop	ax
	cmp	ax,2501h
	jne	uf_exec1
	push	caller_flags[bp]
	popf
	call	tsk_old_stack
	pushf
	cli
	call	cs:savabsread
	pop	cs:temp_1		; remove flags
	jmp	short uf_complete
;
uf_exec1:
	cmp	ax,2601h
	jne	uf_exec2
	push	caller_flags[bp]
	popf
	call	tsk_old_stack
	pushf
	cli
	call	cs:savabswrite
	pop	cs:temp_1		; remove flags
	jmp	short uf_complete
;
uf_exec2:
	push	caller_flags[bp]
	popf
	call	tsk_old_stack
;
	calldos				; execute function
;
;	Now we have to release the resources, unless DOS still indicates
;	that it is busy. This would indicate that a critical error has
;	occurred, and DOS processing is not really complete.
;	However, if we were called from INT 28, DOS must still be busy,
;	so we only check the in_error flag.
;
uf_complete:
	call	tsk_switch_stack
;
	cmp	idle_active,0
	jnz	uf_nobsychk		; don't check busy if INT 28 call
	les	bx,tsk_glob_rec.dos_in_use
	cmp	es:byte ptr [bx],0
	jne	no_relc_uf		; don't release if busy
;

⌨️ 快捷键说明

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