process.asm

来自「汇编编程艺术」· 汇编 代码 · 共 1,414 行 · 第 1/3 页

ASM
1,414
字号
		mov	es:[di].pcb.regbx, bx
		mov	es:[di].pcb.regcx, cx
		mov	es:[di].pcb.regdx, dx
		mov	es:[di].pcb.regsi, si
		pop	es:[di].pcb.regdi
		pop	es:[di].pcb.reges
		pop	es:[di].pcb.regds
		pop	es:[di].pcb.regflags
		pop	es:[di].pcb.regbp
		pop	es:[di].pcb.regip
		pop	es:[di].pcb.regcs
		mov	es:[di].pcb.regsp, sp
		mov	es:[di].pcb.regss, ss

		mov	dx, es:[di].pcb.regip	;Get return address (ptr to
		mov	cx, es:[di].pcb.regcs	; PCB address.
		add	es:[di].pcb.regip, 4	;Skip ptr on return.
		mov	es, cx			;Get the ptr to the new pcb
		mov	di, dx			; address, then fetch the
		les	di, es:[di]		; pcb val.
		mov	wp StdGrp:CurCoroutine, di
		mov	wp StdGrp:CurCoroutine+2, es

; Okay, switch to the new process:

		mov	ss, es:[di].pcb.regss
		mov	sp, es:[di].pcb.regsp
		mov	ax, es:[di].pcb.regax
		mov	bx, es:[di].pcb.regbx
		mov	cx, es:[di].pcb.regcx
		mov	dx, es:[di].pcb.regdx
		mov	si, es:[di].pcb.regsi
		mov	bp, es:[di].pcb.regbp
		mov	ds, es:[di].pcb.regds

		push	es:[di].pcb.regflags
		push	es:[di].pcb.regcs
		push	es:[di].pcb.regip
		push	es:[di].pcb.regdi
		mov	es, es:[di].pcb.reges
		pop	di
		iret


		else

		les	di, StdGrp:CurCoroutine
		pop	es:[di].regax
		mov	es:[di].regbx, bx
		mov	es:[di].regcx, cx
		mov	es:[di].regdx, dx
		mov	es:[di].regsi, si
		pop	es:[di].regdi
		pop	es:[di].reges
		pop	es:[di].regds
		pop	es:[di].regflags
		pop	es:[di].regbp
		pop	es:[di].regip
		pop	es:[di].regcs
		mov	es:[di].regsp, sp
		mov	es:[di].regss, ss
		mov	dx, es:[di].regip
		mov	cx, es:[di].regcs
		add	es:[di].regip, 4
		mov	es, cx
		mov	di, dx
		les	di, es:[di]
		mov	wp StdGrp:CurCoroutine, di
		mov	wp StdGrp:CurCoroutine+2, es
		mov	ss, es:[di].regss
		mov	sp, es:[di].regsp
		mov	ax, es:[di].regax
		mov	bx, es:[di].regbx
		mov	cx, es:[di].regcx
		mov	dx, es:[di].regdx
		mov	si, es:[di].regsi
		mov	bp, es:[di].regbp
		mov	ds, es:[di].regds
		push	es:[di].regflags
		push	es:[di].regcs
		push	es:[di].regip
		push	es:[di].regdi
		mov	es, es:[di].reges
		pop	di
		iret

		endif

sl_cocalll	endp




;****************************************************************************
;
; WaitSemaph- Waits on a given semaphore.  If there is only one process in
;	      the ready queue, this will cause a deadlock!  But that's the
;	      programmer's fault, not ours.
;
; sl_WaitSemaph- ES:DI points at the semaphore.

		public	sl_WaitSemaph
sl_WaitSemaph	proc	far
		assume	ds:StdGrp

		if	@version ge 600

		dec	es:[di].semaphore.SemaCnt
		jns	NoWait



		pushf
		push	ds
		push	si
		cli

; Save the state of the current process so we can remove it from the
; Ready Queue:

		mov	si, StdGrp
		mov	ds, si
		lds	si, StdGrp:ReadyQ	;Get ptr to current PCB.
		mov	[si].pcb.regax, ax
		mov	[si].pcb.regbx, bx
		mov	[si].pcb.regcx, cx
		mov	[si].pcb.regdx, dx
		mov	[si].pcb.regbp, bp
		mov	[si].pcb.regdi, di
		mov	[si].pcb.reges, es
		pop	[si].pcb.regsi
		pop	[si].pcb.regds
		pop	[si].pcb.regflags
		pop	[si].pcb.regip
		pop	[si].pcb.regcs
		mov	[si].pcb.regsp, sp
		mov	[si].pcb.regss, ss

; Adjust the CPU time for the process we've just stopped.

		inc	wp [si].pcb.CPUTime
		jne	NoHOTime
		inc	wp [si+2].pcb.CPUTime

NoHOTime:

; Okay, now that we've saved away the info for this process, let's move
; it off the ready queue and onto the semaphore queue.  Start by checking
; to see if there is anything currently on the semaphore queue:

		mov	ax, StdGrp
		mov	ds, ax
		cmp	wp es:[di+2].semaphore.smaphrlst, 0	;Empty list?
		jne	JustSetEnd

; If the semaphore list is empty, move the current process from the ready
; queue to the semaphore list and make it the beginning and ending entry.

		mov	ax, wp StdGrp:ReadyQ			;Point both
		mov	wp es:[di].semaphore.smaphrlst, ax	; the head
		mov	wp es:[di].semaphore.endsmaphrlst, ax	; and tail
		mov	ax, wp StdGrp:ReadyQ+2			; pointers at
		mov	wp es:[di+2].semaphore.smaphrlst, ax	; this PCB.
		mov	wp es:[di+2].semaphore.endsmaphrlst, ax
		jmp	RmvFromRdy


; If there are other items in this semaphore list, just place the current
; process at the end of the queue.

JustSetEnd:	push	es
		push	di
		les	di, es:[di].semaphore.endsmaphrlst	;Link in the
		mov	ax, wp StdGrp:ReadyQ			; current
		mov	wp es:[di].pcb.NextProc, ax		; process to
		mov	ax, wp StdGrp:ReadyQ+2			; the sema-
		mov	wp es:[di+2].pcb.NextProc, ax		; phore chain.
		pop	di
		pop	es
		mov	ax, wp StdGrp:ReadyQ			;Point sema-
		mov	wp es:[di].semaphore.endsmaphrlst, ax	; phore end
		mov	ax, wp StdGrp:ReadyQ+2			; ptr to cur
		mov	wp es:[di+2].semaphore.endsmaphrlst, ax	; process.

; Now, remove this process from the ready queue.  Note there is no test to
; see if this is the last item on the ready queue.  It is the programmer's
; responsibility to prevent this (It could only happen if the programmer is
; playing with the private fields of the semaphore data structure or if
; s/he makes two successive calls to WaitSemaph).

RmvFromRdy:	les	di, StdGrp:ReadyQ
		mov	ax, wp es:[di+2].pcb.NextProc
		mov	wp StdGrp:ReadyQ+2, ax
		mov	ax, wp es:[di].pcb.NextProc
		mov	wp StdGrp:ReadyQ, ax
		xor	ax, ax				;Store NULL into the
		mov	wp es:[di].pcb.NextProc, ax	; link address to end
		mov	wp es:[di+2].pcb.NextProc, ax	; the semaphore list.


; Okay, transfer control to the (possibly new) procedure at the front of the
; ready queue:

		lds	si, StdGrp:ReadyQ
		mov	ss, [si].pcb.regss
		mov	sp, [si].pcb.regsp
		push	[si].pcb.regflags
		push	[si].pcb.regcs
		push	[si].pcb.regip
		push	[si].pcb.regsi
		mov	ax, [si].pcb.regax
		mov	bx, [si].pcb.regbx
		mov	cx, [si].pcb.regcx
		mov	dx, [si].pcb.regdx
		mov	bp, [si].pcb.regbp
		mov	di, [si].pcb.regdi
		mov	es, [si].pcb.reges
		mov	ds, [si].pcb.regds
		pop	si
		iret





		else




		dec	es:[di].SemaCnt
		js	DoWait
		jmp	NoWait
DoWait:		pushf
		push	ds
		push	si
		cli
		mov	si, StdGrp
		mov	ds, si
		lds	si, StdGrp:ReadyQ
		mov	[si].regax, ax
		mov	[si].regbx, bx
		mov	[si].regcx, cx
		mov	[si].regdx, dx
		mov	[si].regbp, bp
		mov	[si].regdi, di
		mov	[si].reges, es
		pop	[si].regsi
		pop	[si].regds
		pop	[si].regflags
		pop	[si].regip
		pop	[si].regcs
		mov	[si].regsp, sp
		mov	[si].regss, ss
		inc	wp [si].CPUTime
		jne	NoHOTime
		inc	wp [si+2].CPUTime
NoHOTime:
		mov	ax, StdGrp
		mov	ds, ax
		cmp	wp es:[di+2].smaphrlst, 0
		jne	JustSetEnd
		mov	ax, wp StdGrp:ReadyQ
		mov	wp es:[di].smaphrlst, ax
		mov	wp es:[di].endsmaphrlst, ax
		mov	ax, wp StdGrp:ReadyQ+2
		mov	wp es:[di+2].smaphrlst, ax
		mov	wp es:[di+2].endsmaphrlst, ax
		jmp	RmvFromRdy
JustSetEnd:	push	es
		push	di
		les	di, es:[di].endsmaphrlst
		mov	ax, wp StdGrp:ReadyQ
		mov	wp es:[di].NextProc, ax
		mov	ax, wp StdGrp:ReadyQ+2
		mov	wp es:[di+2].NextProc, ax
		pop	di
		pop	es
		mov	ax, wp StdGrp:ReadyQ
		mov	wp es:[di].endsmaphrlst, ax
		mov	ax, wp StdGrp:ReadyQ+2
		mov	wp es:[di+2].endsmaphrlst, ax
RmvFromRdy:	les	di, StdGrp:ReadyQ
		mov	ax, wp es:[di+2].NextProc
		mov	wp StdGrp:ReadyQ+2, ax
		mov	ax, wp es:[di].NextProc
		mov	wp StdGrp:ReadyQ, ax
		xor	ax, ax
		mov	wp es:[di].NextProc, ax
		mov	wp es:[di+2].NextProc, ax
		lds	si, StdGrp:ReadyQ
		mov	ss, [si].regss
		mov	sp, [si].regsp
		push	[si].regflags
		push	[si].regcs
		push	[si].regip
		push	[si].regsi
		mov	ax, [si].regax
		mov	bx, [si].regbx
		mov	cx, [si].regcx
		mov	dx, [si].regdx
		mov	bp, [si].regbp
		mov	di, [si].regdi
		mov	es, [si].reges
		mov	ds, [si].regds
		pop	si
		iret

		endif					;Version 6.00

NoWait:		ret
sl_WaitSemaph	endp




; sl_RlsSemaph-	Releases a semaphore.  If there are any items on the semaphore
;		list waiting for the semaphore, this guy moves the first such
;		item to the ready queue, immediately behind the current
;		process so that it will run next.
;
; sl_RlsSemaph-	Address of semaphore to release is passed in ES:DI

		public	sl_RlsSemaph
sl_RlsSemaph	proc	far

		if	@version ge 600

		inc	es:[di].semaphore.SemaCnt
		cmp	es:[di].semaphore.SemaCnt, 0
		jg	SmphIsFree

; If the semaphore count is less than or equal to zero, then there are some
; processes still on this semaphore queue.  Move the first one onto the
; ready queue.

		pushf
		push	ds
		push	es
		push	ax
		push	bx
		push	di
		cli

; First, remove this guy from the semaphore list.

		lds	bx, es:[di].semaphore.smaphrlst
		mov	ax, wp ds:[bx].pcb.NextProc
		mov	wp es:[di].semaphore.smaphrlst, ax
		mov	ax, wp ds:[bx+2].pcb.NextProc
		mov	wp es:[di+2].semaphore.smaphrlst, ax

; If last item in semaphore list, clear the end pointer.

		or	ax, ax
		jnz	NotAtEnd
		mov	wp es:[di].semaphore.endsmaphrlst, ax
		mov	wp es:[di+2].semaphore.endsmaphrlst, ax
NotAtEnd:

; Now add it to the ready queue

		mov	ax, ds		;Point ES:BX at current PCB
		mov	es, ax

		assume	ds:StdGrp
		mov	ax, StdGrp
		mov	ds, ax
		lds	di, StdGrp:LastRdyQ
		assume	ds:nothing

; Point the new pcb's NextProc field to the same place the current pcb's
; next field points:

		mov	wp es:[bx].pcb.NextProc, 0
		mov	wp es:[bx+2].pcb.NextProc, 0

; Point the last PCB's NextProc field at the new process.

		mov	wp ds:[di].pcb.NextProc, bx
		mov	wp ds:[di+2].pcb.NextProc, es

; Point LastRdyQ at the process we just added to the ready queue:

		mov	ax, StdGrp
		mov	ds, ax
		assume	ds:StdGrp
		mov	wp StdGrp:LastRdyQ, bx
		mov	wp StdGrp:LastRdyQ+2, es
QuitRls:
		pop	di
		pop	bx
		pop	ax
		pop	es
		pop	ds
		popf

SmphIsFree:	ret

		else

		inc	es:[di].SemaCnt
		cmp	es:[di].SemaCnt, 0
		jg	SmphIsFree
		pushf
		push	ds
		push	es
		push	ax
		push	bx
		push	di
		cli
		lds	bx, es:[di].smaphrlst
		mov	ax, wp ds:[bx].NextProc
		mov	wp es:[di].smaphrlst, ax
		mov	ax, wp ds:[bx+2].NextProc
		mov	wp es:[di+2].smaphrlst, ax
		or	ax, ax
		jnz	NotAtEnd
		mov	wp es:[di].endsmaphrlst, ax
		mov	wp es:[di+2].endsmaphrlst, ax
NotAtEnd:
		mov	ax, ds
		mov	es, ax
		assume	ds:StdGrp
		mov	ax, StdGrp
		mov	ds, ax
		lds	di, StdGrp:LastRdyQ
		assume	ds:nothing
		mov	wp es:[bx].NextProc, 0
		mov	wp es:[bx+2].NextProc, 0
		mov	wp ds:[di].NextProc, bx
		mov	wp ds:[di+2].NextProc, es
		mov	ax, StdGrp
		mov	ds, ax
		assume	ds:StdGrp
		mov	wp StdGrp:LastRdyQ, bx
		mov	wp StdGrp:LastRdyQ+2, es
QuitRls:
		pop	di
		pop	bx
		pop	ax
		pop	es
		pop	ds
		popf

SmphIsFree:	ret

		endif

sl_RlsSemaph	endp


;============================================================================


; ISRs for interrupts that the process manager patches into:

TimerISR	proc
		assume	ds:nothing
		pushf 				;Call the previous timer ISR
		call	stdgrp:TimerIntVect
		call	far ptr sl_Yield
		iret
TimerISR	endp



stdlib		ends
		end

⌨️ 快捷键说明

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