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

📄 tskasm.asm

📁 这是一个关于C++编程开发的算法!
💻 ASM
字号:
;
;	CTask - Scheduler and miscellaneous utilities
;
;	Public Domain Software written by
;		Thomas Wagner
;		Patschkauer Weg 31
;		D-1000 Berlin 33
;		West Germany
;
 IFDEF at
.186
 ENDIF
	name	tskasm
	.model	large
;
        public  _asm_schedule
	public	_asm_c_schedule
        public  scheduler
	public	_sched_int
;
	public	_tsk_dis_int
	public	_tsk_ena_int
	public	_tsk_flags
	public	_tsk_nop
;
;
	include	tsk.mac
;
INT_FLAG	=	2h	; Int enable flag in upper byte of flag reg
r_flags		=	24	; Offset of flag register on task stack
;
	extrn	_tsk_current: dword
        extrn   _tsk_eligible: dword
	extrn	_tsk_preempt: byte
	extrn	_tsk_pretick: byte
	extrn	_tsk_var_prior: byte
;
	.data
;
in_sched	db	0
;
	.code
;				   
_dgroup		dw	seg dgroup
;
;------------------------------------------------------------------------
;
;	enq	Enqueue tcb in queue. For local use only.
;		entry:	es:di = tcb to enqueue
;		exit:	-
;		uses:	ax, cx, dx, bp, di
;
enq	macro
;
	lds	bx,es:queue[di]		; queue head pointer
	mov	ax,ds
	or	ax,bx	
	jz	enq_end			; nothing left to do if queue null
	mov	dx,es:prior[di]		; load priority of task
enq_l:
	mov	cx,bx			; save last ptr
	mov	bp,ds
	lds	bx,next[bx]		; load next
	mov	ax,ds
	or	ax,bx			; end of chain?
	jz	enq_found		; then insert
	cmp	dx,prior[bx]		; compare priority
	jbe	enq_l			; loop if tasks prior less or equal
;
enq_found:
        mov     word ptr es:next[di],bx    ; set tasks next pointer
        mov     word ptr es:next+2[di],ds
        mov     bx,cx                      ; last pointer
	mov	ds,bp
        mov     word ptr next[bx],di       ; last->next = task
	mov	word ptr next+2[bx],es
enq_end:
	mov	ds,_dgroup
;
	endm
;
;
;	upd_prior: Update priority of tasks in eligible queue.
;	           Only activated if tsk_var_prior is nonzero.
;
;	NOTE:	This loop is not protected by interrupt disable.
;		Since it does not modify the queue itself, there
;		is no danger of race conditions.
;
upd_prior	macro
;
    les     di,_tsk_eligible
pinc_loop:
	mov	ax,es
	or	ax,di			; end of chain?
	jz	updp_end
	inc	es:prior[di]
	jnz	pinc_nxt
	dec	es:prior[di]
pinc_nxt:
	les	di,es:next[di]
	jmp	pinc_loop
;
updp_end:
;
	endm
;
;
;	The scheduler. Note that this routine is entered with the stack
;	set up as for an interrupt handler.
;
scheduler	proc	far
;
	cli			; better safe than sorry
	push	ds
	mov	ds,_dgroup
	cmp	in_sched,0	; already in the scheduler?
	je	sched_ok	; continue if not
	pop	ds		; else return immediately
	iret
;
sched_ok:
	inc	in_sched
	pop	ds
;	sti			; we can now safely enable interrupts
 IFNDEF at
	push	ax
	push	cx
	push	dx
	push	bx
	push	sp
	push	bp
	push	si
	push	di
 ELSE
	pusha
 ENDIF
	push	ds
	push	es
;
        mov     ds,_dgroup             ; establish addressing of our vars
;
	cmp	_tsk_var_prior,0
	je	no_var_pri
        upd_prior                      ; update priority
;
no_var_pri:
        cli                            ; the following is critical
;
        les     di,_tsk_current        ; get current tcb
        mov     ax,es                  ; check if NULL (current task killed)
	or	ax,di
	jz	no_current
;
	mov	word ptr es:tcbstack[di],sp ; store stack pointer & seg
	mov	word ptr es:tcbstack+2[di],ss
;
	cmp	es:state[di],ST_RUNNING
	jne	not_eligible
	mov	es:state[di],ST_ELIGIBLE
not_eligible:
;
        enq                             ; Enqueue current task
;
no_current:
	mov	_tsk_pretick,0		; No preemption tick
	and	_tsk_preempt,1		; Turn off temp preempt flag
;
wait_elig:
	cli
        les     di,_tsk_eligible
;
;	If eligible queue empty, enter waiting loop
;
	mov	ax,es
	or	ax,di			; is the eligible queue empty?
	jnz	not_empty		; jump if not
	sti			       	; enable interrupts
	nop
	nop
	jmp	wait_elig
;
;	Eligible queue not empty, activate first eligible task.
;
not_empty:
        mov     ax,word ptr es:next[di]         ; load next pointer
        mov     word ptr _tsk_eligible,ax       ; remove from queue
	mov	ax,word ptr es:next+2[di]
        mov     word ptr _tsk_eligible+2,ax
;
        mov     word ptr _tsk_current,di        ; set tcb into current
	mov	word ptr _tsk_current+2,es
        mov     ax,es:iniprior[di]              ; reset current tasks priority
	mov	es:prior[di],ax
;
        mov     in_sched,0                      ; reset scheduler active flag
;
        lds     si,es:tcbstack[di]              ; load stack
	or	byte ptr r_flags+1[si],INT_FLAG	; enable interrupts
        mov     es:state[di],ST_RUNNING         ; set task state
        mov     cx,ds                           ; switch stack
	mov	ss,cx
	mov	sp,si
        pop     es                              ; restore all registers
	pop	ds
 IFNDEF at
	pop	di
	pop	si
	pop	bp
        pop     bx                              ; don't pop SP
	pop	bx
	pop	dx
	pop	cx
	pop	ax
 ELSE
	popa
 ENDIF
	iret
;
scheduler	endp
;
;
;--------------------------------------------------------------------------
;
;
;	_sched_int  
;
;	Is the scheduler entry for interrupt handlers.
;	It checks if preemption is allowed, returning if not.
;	The stack is assumed to be set up as on interrupt entry.
;	
_sched_int	proc	far
;
	push	ds
	push	bx
	mov	ds,_dgroup
	cmp	_tsk_preempt,0		; preempt flags 0?
	jne	no_sched		; no scheduling if set
	lds	bx,_tsk_current		; current running task
	test	flags[bx],F_CRIT	; preemption allowed for this task?
	jnz	no_sched		; no scheduling if flag set
	pop	bx			; else go schedule
	pop	ds
	jmp	scheduler
;
no_sched:
	mov	ds,_dgroup
	mov	_tsk_pretick,1		; Mark preemption pending
	pop	bx
	pop	ds
	iret
;
_sched_int	endp
;
;
;	void far asm_schedule (void)
;
;	Entry for calling the scheduler. Rearranges the stack to
;	contain flags.
;	NOTE: Uses ax,bx.
;
_asm_schedule	proc	far
;
	pop	ax
	pop	bx
	pushf
	push	bx
	push	ax
	cli
	jmp	scheduler
;
_asm_schedule	endp
;
;
;	void far asm_c_schedule (void)
;
;	Entry for conditionally calling the scheduler. Rearranges 
;	the stack to contain flags, then jumps to _sched_int.
;	NOTE: Uses ax,bx.
;
_asm_c_schedule	proc	far
;
	pop	ax
	pop	bx
	pushf
	push	bx
	push	ax
	cli
	jmp	_sched_int
;
_asm_c_schedule	endp
;
;	word tsk_flags (void)
;
;	Returns current contents of Flag register.
;
_tsk_flags	proc	far
	pushf
	pop	ax
	ret
_tsk_flags	endp
;
;
;	int tsk_dis_int (void)
;
;	Returns current state of the interrupt flag (1 if ints were 
;	enabled), then disables interrupts.
;
_tsk_dis_int	proc	far
;
	pushf
	pop	ax
	mov	cl,9
	shr	ax,cl
	and	ax,1
	cli
	ret
;
_tsk_dis_int	endp
;
;
;	void far tsk_ena_int (int state)
;
;	Enables interrupts if 'state' is nonzero.
;
_tsk_ena_int	proc	far
;
	push	bp
	mov	bp,sp
	mov	ax,6[bp]
	pop	bp
	or	ax,ax
	jz	teiend
	sti
teiend:
	ret
;
_tsk_ena_int	endp
;
;	void tsk_nop (void)
;
;	Do nothing. Used for very short delays.
;
_tsk_nop	proc	far
;
	jmp	short tnop1
tnop1:
	jmp	short tnop2
tnop2:
	ret
;
_tsk_nop	endp
;
	end


⌨️ 快捷键说明

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