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 + -
显示快捷键?