📄 kernel.inc
字号:
;This will involve aliasing the pointers in the RqBlk
;This must done before we start building and using user PDs
Chk04:
MOV EBX,[EAX.DataLo] ; Get pLB^.Data into ECX:EBX
MOV ECX,[EAX.DataHi] ;
MOV EDX,pCkMessage ; Get Storage Addr in EDX
MOV [EDX],EBX ; Put pLB^.Data in specified
MOV [EDX+4],ECX ; memory space (EDX)
;Return the LB to the pool
MOV EBX,pFreeLB ; pLBin^.Next <= pFreeLB;
MOV [EAX.NextLB],EBX ;
MOV pFreeLB,EAX ; pFreeLB <= pLBin;
INC _nLBLeft ;
STI ;
MOV EAX,ercOk ;
MOV ESP,EBP ;
POP EBP ;
RETF 8 ;
_CheckMsg ENDP
;====================================================================
; NewTask --- OS PUBLIC - Creates a new task and schedules it for execution.
; used primarily to create a task for a job other than the one you are in.
; The OS uses this to create the initial task for a newly loaded job.
;
; The OS stacks are preallocated as part of the TSS. If this is an OS
; task (CodeSeg = 8) then we load the TSS Stack into TSS_ESP and
; TSS_ESP0, otherwise we take the ESP param and place it into TSS_ESP.
;
; Procedural interface:
;
; NewTask(JobNum, CodeSeg, Priority, fDebug, Exch, ESP, EIP): dErcRet
;
;
NTS_Job EQU [EBP+36] ;Job Num for this task
NTS_CS EQU [EBP+32] ;8 for OS, 18h for user task
NTS_Pri EQU [EBP+28] ;Priority of this task
NTS_fDbg EQU [EBP+24] ;TRUE for DEBUGing
NTS_Exch EQU [EBP+20] ;Exchange for TSS
NTS_ESP EQU [EBP+16] ;Initial stack pointer
NTS_EIP EQU [EBP+12] ;Task start address
_NewTask PROC FAR ;
PUSH EBP ;
MOV EBP,ESP ;
MOV EDX, NTS_Pri ;
CMP EDX, nPRI-1 ;Priority OK?
JBE NT0000
MOV EAX,ercBadPriority
JMP NTEnd
NT0000:
MOV ECX, NTS_Exch
CMP ECX, nExch ;Exch in range?
JBE NT0001
MOV EAX,ercOutOfRange
JMP NTEnd
NT0001:
CLI ;we can't be interrupted
MOV EAX,pFreeTSS ; NewTSS <= pFreeTSS;
OR EAX,EAX ; IF pFreeTSS=NIL THEN Return;
JNZ NT0002 ;
MOV EAX,ercNoMoreTSSs ;No...
JMP NTEnd
NT0002:
MOV EBX,[EAX.NextTSS] ; pFreeTSS <= pFreeTSS^.Next
MOV pFreeTSS,EBX ;
DEC _nTSSLeft ;
STI
;EAX now has pNewTSS
MOV [EAX.Priority],DL ;put Priority into TSS
MOV [EAX.TSS_EFlags],0202h ;Load the Flags Register
MOV [EAX.TSS_Exch], ECX ;Put new Exch in TSS (ECX is free)
MOV EBX, NTS_EIP ;mov EIP into TSS (Start Address)
MOV [EAX.TSS_EIP],EBX
MOV EBX, NTS_ESP ;mov ESP into TSS
MOV [EAX.TSS_ESP],EBX
MOV [EAX.TSS_ESP0],EBX ;
MOV ECX, NTS_CS ;mov CS into TSS
MOV [EAX.TSS_CS],CX
PUSH EAX ;Save pNewTSS
;Now we get pJCB from JobNum they passed in so we can
;get the PD from the JCB
MOV EAX, NTS_Job ;Set up to call GetpJCB
CALL GetpJCB ;EAX now has pJCB
MOV ECX, EAX ;ECX now has pJCB
POP EAX ;Restore pNewTSS to EAX
MOV [EAX.TSS_pJCB],ECX ;Put pJCB into TSS
MOV EBX, [ECX.JcbPD] ;Set up to call LinToPhy
PUSH EAX ;Save pNewTSS again
MOV EAX, NTS_Job ;
CALL LinToPhy ;Get Physical Address for PD into EAX
MOV EBX, EAX
POP EAX ;pNewTSS into EAX
MOV [EAX.TSS_CR3],EBX ;Put Physical Add for PD into TSS_CR3
CMP DWORD PTR NTS_fDbg, 0 ;Debug on entry?
JE NT0004 ;No
MOV [EAX.TSS_TrapBit],1h ;Yes
NT0004:
MOV EBX, NTS_Pri ;Get priority of new task
CLI ;We can't be interrupted
MOV EDX,pRunTSS ;Get who's running
CMP [EDX.Priority],BL ;Who got the highest Pri?
JA NT0005 ;New guy does (lowest num)
CALL enQueueRdy ;Just put new guy on the ReadyQue (EAX)
XOR EAX,EAX ;ercOk
JMP NTEnd ;Return to caller
NT0005:
XCHG EAX,EDX ;CrntTSS -> EAX, New TSS -> EDX
PUSH EDX ;Save New TSS
CALL enQueueRdy ;
POP EAX ;New TSS -> EAX
MOV pRunTSS,EAX ;Move new TSS into pRunTSS
MOV BX,[EAX.Tid] ;Put Selector/Offset in "TSS"
MOV TSS_Sel,BX ;
INC _nSwitches
JMP FWORD PTR [TSS] ;Jump to new TSS
XOR EAX,EAX ;ErcOk
NTEnd:
STI ;
MOV ESP,EBP ;
POP EBP ;
RETF 28 ;
_NewTask ENDP
;====================================================================
; SpawnTask --- OS PUBLIC - Creates a new task in the current job
; and schedules it for execution
;
; Procedural Interface:
; SpawnTask(pEntry, dPriority, fDebug, pStack, fOSCode);
;
;
pEntryST EQU DWORD PTR [EBP+28]
dPriST EQU DWORD PTR [EBP+24]
fDebugST EQU DWORD PTR [EBP+20]
pStackST EQU DWORD PTR [EBP+16]
fOSCodeST EQU DWORD PTR [EBP+12]
NewExchST EQU DWORD PTR [EBP-4]
NewTSSST EQU DWORD PTR [EBP-8]
_SpawnTask PROC FAR ;
PUSH EBP ;
MOV EBP,ESP ;
SUB ESP, 8 ;two local DWORD vars
CMP dPriST, nPRI-1 ;Priority OK?
JBE ST0001
MOV EAX,ercBadPriority
JMP STEnd
ST0001:
LEA EAX, NewExchST ;Allocate exchange
PUSH EAX
CALL FAR PTR _AllocExch
OR EAX, EAX ;see if we got an error
JNZ STEnd ;Yup, bad news
;Allocate a new TSS
CLI ;we can't be interrupted
MOV EAX,pFreeTSS ; NewTSS <= pFreeTSS;
OR EAX,EAX ; IF pFreeTSS=NIL THEN Return;
JNZ ST0002 ;
STI
;Dealloc Exch if we didn't get a TSS
PUSH NewExchST
CALL FAR PTR _DeAllocExch
MOV EAX,ercNoMoreTSSs ;No...
JMP NTEnd
ST0002:
MOV EBX,[EAX.NextTSS] ; pFreeTSS <= pFreeTSS^.Next
MOV pFreeTSS,EBX ;
DEC _nTSSLeft ;
STI
MOV NewTSSST, EAX ;Save new TSS
MOV EBX, NewExchST ;mov exch into TSS
MOV [EAX.TSS_Exch],EBX
MOV [EAX.TSS_CS], OSCodeSel ;Defaults to OS code selector
CMP fOSCodeST, 0
JNE ST0003
MOV [EAX.TSS_CS], JobCodeSel ;Make OS code selector
ST0003:
MOV EBX,pEntryST ;mov EIP into TSS
MOV [EAX.TSS_EIP],EBX
MOV EBX, pStackST ;mov ESP into TSS
MOV [EAX.TSS_ESP],EBX
MOV [EAX.TSS_ESP0],EBX
MOV EBX, pRunTSS
MOV EDX, [EBX.TSS_pJCB] ;Get pJCB from Crnt Task
MOV [EAX.TSS_pJCB],EDX
MOV EDX, [EBX.TSS_CR3] ;Get CR3 from crnt task
MOV [EAX.TSS_CR3],EDX ; move into new TSS
MOV [EAX.TSS_EFlags],0202h ;Load the Flags Register
CMP fDebugST, 0 ;Debug on entry?
JE ST0004 ;No
MOV [EAX.TSS_TrapBit],1h ;Yes
ST0004:
MOV EBX, dPriST ;mov priority into BL
MOV [EAX.Priority],BL ;put in TSS
CLI ;we can't be interrupted
MOV EDX,pRunTSS ;Get who's running
CMP [EDX.Priority],BL ;Who got the highest Pri?
JA ST0005 ;If crnt >, New guy does (lowest num)
CALL enQueueRdy ;Old guy does, just put new guy on Q.
XOR EAX,EAX ;ercOk
JMP STEnd ;Return to caller
ST0005:
XCHG EAX,EDX ;CrntTSS -> EAX, New TSS -> EDX
PUSH EDX ;New TSS -> Stack
CALL enQueueRdy ;Place crnt TSS on Q
POP EAX ;New TSS -> EAX
MOV pRunTSS,EAX ;Move new TSS into pRunTSS
MOV BX,[EAX.Tid] ;Put Selector/Offset in "TSS"
MOV TSS_Sel,BX ;
INC _nSwitches
JMP FWORD PTR [TSS] ;Jump to new TSS
XOR EAX,EAX ;ErcOk
STEnd:
STI ;
MOV ESP,EBP ;
POP EBP ;
RETF 20 ;
_SpawnTask ENDP
;=============================================================================
;
; AllocExch - The kernel Allocate Exchange primitive. This procedure
; provides access to the operating system by allowing a TASK to
; allocate a message port for the transmission and reception of messages from
; another process.
;
; Procedural Interface :
;
; AllocExch(pExchRet):dError
;
; pExchRet is a pointer to where you want the Exchange Handle
; returned. The Exchange Handle is a DWORD (4 BYTES).
;
;=============================================================================
_AllocExch PROC FAR ;
PUSH EBP ;
MOV EBP,ESP ;
XOR ESI,ESI ; Zero the Exch Index
MOV EBX,prgExch ; EBX <= ADR rgExch
MOV ECX,nExch ; Get number of exchanges in ECX
AE000:
CLI ;
CMP [EBX.Owner],NIL ; Is this exchange free to use
JE AE001 ; If we found a Free Exch, JUMP
ADD EBX,sEXCH ; Point to the next Exchange
INC ESI ; Increment the Exchange Index
LOOP AE000 ; Keep looping until we are done
STI ;
MOV EAX,ercNoMoreExch ; There are no instances of the
MOV ESP,EBP ;
POP EBP ;
RETF 4 ;
AE001:
MOV EDX,[EBP+0CH] ; Get the pExchRet in EDX
MOV [EDX],ESI ; Put Index of Exch at pExchRet
MOV EDX,pRunTSS ; Get pRunTSS in EDX
MOV EAX,[EDX.TSS_pJCB] ; Get the pJCB in EAX
MOV [EBX.Owner],EAX ; Make the Exch owner the Job
STI ;
MOV [EBX.EHead],NIL ; Make the msg/TSS queue NIL
MOV [EBX.ETail],NIL ;
DEC _nEXCHLeft ; Stats
MOV EAX,ercOk ;
MOV ESP,EBP ;
POP EBP ;
RETF 4 ;
_AllocExch ENDP
;=============================================================================
;
; DeAllocExch - The kernel DeAllocate Exchange primitive. It allows a TASK
; to deallocate a "message port." It also deQueues any messages, and frees
; up any Link Blocks attached to the exchange.
;
; Procedural Interface :
;
; DeAllocExch(Exch):ercType
;
; Exch is the Exchange Handle the process is asking to be released.
;
;=============================================================================
;
; DeAllocExch - The kernel DeAllocate Exchange primitive. It allows a TASK
; to deallocate a "message port." It also deQueues any messages, and frees
; up any Link Blocks, TSSs, and RQBs, attached to the exchange
;
; Procedural Interface :
;
; DeAllocExch(Exch):ercType
;
; Exch is the Exchange Handle the process is asking to be released.
;
;=============================================================================
_DeAllocExch PROC FAR ;
PUSH EBP ;
MOV EBP,ESP ;
MOV ESI,[EBP+0CH] ; Load the Exchange Index in ESI
MOV EAX,ESI ; Get the Exchange Index in EAX
MOV EDX,sEXCH ; Compute offset of Exch in rgExch
MUL EDX ;
MOV EDX,prgExch ; Add offset of rgExch => EAX
ADD EAX,EDX ;
MOV ECX,EAX ; Make a copy in ECX (ECX = pExch)
MOV EDX,pRunTSS ; Get the pRunTSS in EDX
MOV EBX,[EDX.TSS_pJCB] ; Get pJCB in EBX
MOV EDX,[EAX.Owner] ; Get the Exchange Owner in EDX
CMP EBX,EDX ; If the CurrProc owns the Exchange,
JE DE000 ; yes
CMP EBX, OFFSET MonJCB ; if not owner, is this the OS???
JE DE000 ; yes
MOV EAX,ercNotOwner ;
MOV ESP,EBP ;
POP EBP ;
RETF 4 ;
DE000:
CLI ;
CMP [ECX.fEMsg],NIL ; Check to See if a message may be queued
JE DE001 ; No. Go check for Task (TSS)
MOV ESI, ECX ; ESI must point to Exch for deQueue
CALL deQueueMsg ; Yes, Get the message off of the Exchange
OR EAX, EAX
JZ DE002 ; Nothing there. Go free the Exch.
;Return the LB to the pool
MOV EBX,pFreeLB ; pLBin^.Next <= pFreeLB;
MOV [EAX.NextLB],EBX ;
MOV pFreeLB,EAX ; pFreeLB <= pLBin;
INC _nLBLeft ;
JMP DE000 ; Go And Check for more.
; If we find an RqBlk on the exchange we must respond
;with ErcInvalidExch before we continue! This will
;only happen if a system service writer doesn't follow
;instructions or a service crashes!
;
DE001:
CMP [ECX.EHead],NIL ; Check to See if TSS is queued
JE DE002 ; NIL = Empty, JUMP
MOV ESI, ECX ; ESI must point to Exch for deQueue
CALL deQueueTSS ; Get the TSS off of the Exchange
;Free up the TSS (add it to the free list)
MOV EBX,pFreeTSS ; pTSSin^.Next <= pFreeTSS;
MOV [EAX.NextTSS],EBX ;
MOV [EAX.TSS_pJCB], 0 ; Make TSS invalid
MOV pFreeTSS,EAX ; pFreeTSS <= pTSSin;
INC _nTSSLeft ;
JMP DE001 ; Go And Check for more.
DE002:
MOV [ECX.Owner],NIL ; Free up the exchange.
MOV [ECX.fEMsg],NIL ; Reset msg Flag.
INC _nEXCHLeft ; Stats
STI ;
MOV EAX,ercOk ;
MOV ESP,EBP ;
POP EBP ;
RETF 4 ;
_DeAllocExch ENDP
;=============================================================================
;
; GetTSSExch - This returns the Exchange of the current TSS to the
; caller. This is primarily provided for System Services that provide
; direct access blocking calls for customers.
;
; Procedural Interface :
;
; GetTSSExch(pExchRet):dError
;
; pExchRet is a pointer to where you want the Exchange Handle
; returned. The Exchange is a DWORD (4 BYTES).
;
_GetTSSExch PROC FAR ;
PUSH EBP ;
MOV EBP,ESP ;
MOV EAX,pRunTSS ; Get the Ptr To the Running TSS
MOV ESI,[EBP+0CH] ; Get the pExchRet in EDX
MOV EBX, [EAX.TSS_Exch] ; Get Exch in EBX
MOV [ESI],EBX ; Put Index of Exch at pExchRet
XOR EAX, EAX ; ErcOK
POP EBP ;
RETF 4 ;
_GetTSSExch ENDP
;======================== End of Module ======================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -