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

📄 kernel.inc

📁 MMURTL(tm) Computer Operating System Ver x0.8, source code.
💻 INC
📖 第 1 页 / 共 4 页
字号:
;=============================================================================
;================= BEGIN PUBLIC KERNEL PRIMITIVES ============================
;=============================================================================
;
; Request - The kernel request primitive sends a message like the Send
; primitive except this function requires several more parameters.
; A system structure called a request block is allocated and some of these
; parameters are placed in it.  A request block is the basic
; structure used for Client-Server communications.  The exchange where a
; request should be queued is determined by searching the system service
; array for a matching request service name specified in the request block.
; The procedural interface to Request looks like this:
;
;    Request(  pSvcName     [EBP+56]
;              wSvcCode     [EBP+52]
;              dRespExch    [EBP+48]
;              pRqHndlRet   [EBP+44]
;              dnpSend      [EBP+40]
;              pData1       [EBP+36]
;              dcbData1     [EBP+32]
;              pData2       [EBP+28]
;              dcbData2     [EBP+24]
;              dData0       [EBP+20]
;              dData1       [EBP+16]
;              dData2       [EBP+12]  ) : dError


_Request PROC FAR				;
		PUSH EBP				; Save the Previous FramePtr
		MOV EBP,ESP				; Set up New FramePtr

		;Validate service name from registry and get exchange
		MOV EAX, [EBP+56]		;pServiceName
		CALL GetExchange		;Leaves Service Exch in ESI if no errors
		CMP EAX, ercOk			;Any errors?
		JE SHORT Req02			;No
		JMP ReqEnd				;Yes, return error
Req02:
		;Validate exchange
		MOV EDX, [EBP+48]		; Get Resp Exchange in EDX
		CMP EDX,nExch           ; Is the exchange out of range?
		JB Req03	            ; No, continue
		MOV EAX,ercOutOfRange   ; Yes, Error in EAX register
		JMP ReqEnd				;
Req03:
		;Get them a request block
		CLI
		CALL NewRQB				;EAX has ptr to new RqBlk (or 0 if none)
		STI
		CMP EAX, NIL			;Did we get one? (NIL (0) means we didn't)
		JNE Req04				;Yes. EAX ptr to new RqBlk
		MOV EAX, ErcNoMoreRqBlks ;No, Sorry...
		JMP ReqEnd				;
Req04:
		;ESI still has the exchange for the service
		;EDX still has the response exchange
		;EAX has pRqBlk (Handle)

		MOV EBX, EAX				;EBX now pts to RqBlk
		MOV [EBX.ServiceExch], ESI	;Put Svc Exch into RqBlk
		MOV EAX, [EBP+52]			;Get Svc Code
		MOV [EBX.ServiceCode], AX	;Put Svc Code into RqBlk
		MOV [EBX.RespExch], EDX		;Put Resp Exch into RqBlk
		CALL GetCrntJobNum			;Get crnt JCB (Job Num of owner)
		MOV [EBX.RqOwnerJob], EAX	;put in RqBlk
		MOV EAX, [EBP+20]			;Get dData0
		MOV [EBX.dData0], EAX		;put in RqBlk
		MOV EAX, [EBP+16]			;Get dData1
		MOV [EBX.dData1], EAX		;put in RqBlk
		MOV EAX, [EBP+20]			;Get dData2
		MOV [EBX.dData2], EAX		;put in RqBlk
		MOV EAX, [EBP+36]			;Get pData1
		MOV [EBX.pData1], EAX		;put in RqBlk
		MOV EAX, [EBP+32]			;Get cbData1
		MOV [EBX.cbData1], EAX		;put in RqBlk
		MOV EAX, [EBP+28]			;Get pData2
		MOV [EBX.pData2], EAX		;put in RqBlk
		MOV EAX, [EBP+24]			;Get cbData2
		MOV [EBX.cbData2], EAX		;put in RqBlk
		MOV EAX, [EBP+40]			;Number of Send PbCbs
		CMP EAX, 3					;Must be 2 or less
		JB Req06					;
		MOV EAX, 2
Req06:
		MOV [EBX.npSend], AL		;Put nSend PbCbs into RqBlk
		MOV CL, 2					;Caculate nRecv (2-nSend)
		SUB CL, AL					;Leave in CL
		MOV [EBX.npRecv], CL		;Put npRecv in RqBlk

		;At this point the RqBlk is all filled in.
		;Now we will return the RqBlkHandle to the user.
		;The handle is actually a ptr to the RqBlk but they can't use
		;it as one anyway (so no problem)

        MOV EDI, [EBP+44]			;Ptr to return handle to
        MOV [EDI], EBX				;Give it to them
        MOV EDX, EBX				;Save RqBlk in EDX

		CLI							; No interruptions from here on
		;Now we allocate a Link block to use

		MOV EAX,pFreeLB         	; EAX <= pFreeLB;
		OR EAX,EAX	             	; Is pFreeLB NIL? (out of LBs)
		JNZ Req08   	         	;
		CALL DisposeRQB				; NO... free up RqBlk
		MOV EAX,ercNoMoreLBs    	; Move error in the EAX register
		JMP ReqEnd					; Go home with bad news
Req08:
		MOV EBX,[EAX.NextLB]    	; pFreeLB <= pFreeLB^.Next
		MOV pFreeLB,EBX         	;
		DEC _nLBLeft				;

        MOV [EAX.LBType],REQLB 		; This is a Request Link Block
		MOV [EAX.NextLB],NIL    	; pLB^.Next <= NIL;
		MOV [EAX.DataLo],EDX    	; RqHandle into Lower 1/2 of Msg
		MOV [EAX.DataHi], 0 	   	; Store zero in upper half of pLB^.Data
		PUSH EAX                	; Save pLB on the stack

		;ESI still has the exchange Number for the service.
		;The ptr to the exch is required for deQueueTSS so we get it.

        MOV EAX,ESI             ; Exch => EAX
		MOV EDX, sEXCH          ; Compute offset of Exch in rgExch
		MUL EDX                 ;
		MOV EDX,prgExch         ; Add offset of rgExch => EAX
		ADD EAX,EDX             ;
		MOV ESI,EAX             ; MAKE ESI <= pExch

		;ESI now points to the exchange

		CALL deQueueTSS         	; DeQueue a TSS on that Exch
		CMP EAX,NIL             	; Did we get one?
		JNE Req10	              	; Yes, give up the message
		POP EAX                 	; No, Get the pLB just saved
		CALL enQueueMsg         	; EnQueue the Message on Exch
		XOR EAX,EAX					; No Error
		JMP SHORT ReqEnd           	; And get out!
Req10:
        POP EBX         	        ; Get the pLB just saved into EBX
		MOV [EAX.pLBRet],EBX	    ; and put it in the TSS
		CALL enQueueRdy         	; EnQueue the TSS on the RdyQ
		MOV EAX,pRunTSS    			; Get the Ptr To the Running TSS
		CALL enQueueRdy         	; and put him on the RdyQ
		CALL deQueueRdy         	; Get high priority TSS off the RdyQ
		CMP EAX,pRunTSS         	; If the high priority TSS is the
		JNE Req12	            	; same as the Running TSS then return
        XOR EAX,EAX             	; Return to Caller with erc ok.
		JMP SHORT ReqEnd
Req12:
        MOV pRunTSS,EAX         ; Make the TSS in EAX the Running TSS
		MOV BX,[EAX.Tid]        ; Get the task Id (TR)
		MOV TSS_Sel,BX          ; Put it in the JumpAddr for Task Swtich
		INC _nSwitches			; Keep track of how many swtiches for stats
		JMP FWORD PTR [TSS]     ; JMP TSS (This is the task swtich)
        XOR EAX,EAX             ; Return to Caller with erc ok.
ReqEnd:
		STI                     ;
		MOV ESP,EBP				;
		POP EBP					;
		RETF 48					; Rtn to Caller & Remove Params from stack
_Request ENDP					;

;=============================================================================
; The response primitive is used by system services to respond to a
; Request received at their service exchange.  The RqBlk handle must be
; supplied along with the error/status code to be returned to the
; caller.  This is very similar to Send except is dealiases addresses
; in the RqBlk and then deallocates it.  The exchange to respond to
; is located inside the RqBlk.
;
;     Respond(dRqHndl, dStatRet): dError
;
;
dRqHndl	 EQU DWORD PTR [EBP+16]
dStatRet EQU DWORD PTR [EBP+12]

_Respond PROC FAR				;
		PUSH EBP				; Save Callers Frame
		MOV EBP,ESP				; Setup Local Frame
		MOV EAX, dRqHndl		; pRqBlk into EAX
		MOV ESI, [EAX.RespExch] ; Response Exchange into ESI
		CMP ESI,nExch           ; Is the exchange out of range?
		JNAE Resp02             ; No, continue
		MOV EAX,ercOutOfRange   ; Error into the EAX register.
		JMP RespEnd				; Get out
Resp02:
        MOV EAX,ESI             ; Exch => EAX
		MOV EDX,sEXCH           ; Compute offset of Exch in rgExch
		MUL EDX                 ;
		MOV EDX,prgExch         ; Add offset of rgExch => EAX
		ADD EAX,EDX             ;
		MOV ESI,EAX             ; MAKE ESI <= pExch
		CMP [EAX.Owner],NIL     ; If the exchange is not allocated
		JNE Resp04              ; return to the caller with error
		MOV EAX,ercNotAlloc     ; in the EAX register.
		JMP RespEnd				;
Resp04:
		MOV EAX, dRqHndl        ; Get Request handle into EBX (pRqBlk)
		MOV EBX, [EAX.RqOwnerJob]
		CALL GetCrntJobNum
		CMP EAX, EBX
		JE Resp06				;Same job - no DeAlias needed

		MOV EAX, dRqHndl        ; Get Request handle into EBX (pRqBlk)
		MOV EBX, [EAX.cbData1]	;
		OR EBX, EBX
		JZ Resp05				;No need to dealias (zero bytes)
		MOV EDX, [EAX.pData1]
		OR EDX, EDX
		JZ Resp05				;Null pointer!
		PUSH ESI				;Save pExch across call
		PUSH EDX				;pMem
		PUSH EBX				;cbMem
		CALL GetCrntJobNum
		PUSH EAX
		CALL FAR PTR _DeAliasMem	;DO it and ignore errors
		POP ESI					;get pExch back
Resp05:
		MOV EAX, dRqHndl        ; Get Request handle into EBX (pRqBlk)
		MOV EBX, [EAX.cbData2]	;
		OR EBX, EBX
		JZ Resp06				;No need to dealias (zero bytes)
		MOV EDX, [EAX.pData2]
		OR EDX, EDX
		JZ Resp06				;Null pointer!
		PUSH ESI				;Save pExch across call
		PUSH EDX				;pMem
		PUSH EBX				;cbMem
		CALL GetCrntJobNum		;
		PUSH EAX
		CALL FAR PTR _DeAliasMem	;DO it and ignore errors
		POP ESI					;get pExch back
Resp06:
		MOV EAX, dRqHndl        ; Get Request handle into EBX (pRqBlk)
		CLI						; No interruptions
		CALL DisposeRQB			; Return Rqb to pool. Not needed anymore

		; Allocate a link block
		MOV EAX,pFreeLB         ; NewLB <= pFreeLB;
		OR EAX,EAX              ; IF pFreeLB=NIL THEN No LBs;
		JNZ Resp07              ;
		MOV EAX,ercNoMoreLBs    ; caller with error in the EAX register
		JMP RespEnd
Resp07:
		MOV EBX,[EAX.NextLB]    ; pFreeLB <= pFreeLB^.Next
		MOV pFreeLB,EBX         ;
		DEC _nLBLeft			;

        MOV [EAX.LBType],RESPLB ; This is a Response Link Block
		MOV [EAX.NextLB],NIL    ; pLB^.Next <= NIL;
		MOV EBX, dRqHndl        ; Get Request handle into EBX
		MOV [EAX.DataLo],EBX    ; Store in lower half of pLB^.Data
		MOV EBX, dStatRet       ; Get Status/Error into EBX
		MOV [EAX.DataHi],EBX    ; Store in upper half of pLB^.Data
		PUSH EAX                ; Save pLB on the stack
		CALL deQueueTSS         ; DeQueue a TSS on that Exch
		CMP EAX,NIL             ; Did we get one?
		JNE Resp08              ; Yes, give up the message
		POP EAX                 ; Get the pLB just saved
		CALL enQueueMsg         ; EnQueue the Message on Exch
		XOR EAX, EAX			; No Error
		JMP SHORT RespEnd       ; And get out!
Resp08:
        POP EBX                 ; Get the pLB just saved into EBX
		MOV [EAX.pLBRet],EBX    ; and put it in the TSS
		CALL enQueueRdy         ; EnQueue the TSS on the RdyQ
		MOV EAX,pRunTSS         ; Get the Ptr To the Running TSS
		CALL enQueueRdy         ; and put him on the RdyQ
		CALL deQueueRdy         ; Get high priority TSS off the RdyQ

		CMP EAX,pRunTSS         ; If the high priority TSS is the
		JNE Resp10              ; same as the Running TSS then return
		XOR EAX,EAX             ; Return to Caller with erc ok.
		JMP SHORT RespEnd		;
Resp10:
        MOV pRunTSS,EAX         ; Make the TSS in EAX the Running TSS
		MOV BX,[EAX.Tid]        ; Get the task Id (TR)
		MOV TSS_Sel,BX          ; Put it in the JumpAddr
		INC _nSwitches
		JMP FWORD PTR [TSS]     ; JMP TSS
        MOV EAX,ercOk           ; Return to Caller with erc ok.
RespEnd:
		STI
		MOV ESP,EBP				;
		POP EBP					;
		RETF 8					; Rtn to Caller & Remove Params
_Respond ENDP					;

;=============================================================================
;
; MoveRequest - The kernel Move Request primitive.
; This allows a service to move a request to another exchange it owns.
; This can not be used to forward a request to another service or Job.
; It is very similar to send except it checks to ensure the destination
; Exchange is owned by the sender.
;
; Procedural Interface :
;
;      MoveRequest(dRqBlkHndl, DestExch):ercType
;
;           dqMsg is the handle of the RqBlk to forward.
;           DestExch the exchange to where the Request should be sent.
;
;
;dRqBlkHndl     EQU [EBP+16]
;DestExch		EQU [EBP+12]

_MoveRequest PROC FAR           ;
		PUSH EBP                ;
		MOV EBP,ESP             ;
		MOV ESI, [EBP+12]       ; Get Exchange Parameter in ESI
		CMP ESI,nExch           ; Is the exchange is out of range
		JNAE MReq02             ; No, continue
		MOV EAX,ercOutOfRange   ; in the EAX register.
		JMP MReqEnd				; Get out
MReq02:
        MOV EAX,ESI             ; Exch => EAX
		MOV EDX,sEXCH           ; Compute offset of Exch in rgExch
		MUL EDX                 ;
		MOV EDX,prgExch         ; Add offset of rgExch => EAX
		ADD EAX,EDX             ;
		MOV ESI,EAX             ; MAKE ESI <= pExch
		MOV EDX, [EAX.Owner]	; Put exch owner into EDX (pJCB)
		CALL GetpCrntJCB		; Leaves it in EAX (uses only EAX)
		CMP EDX, EAX		    ; If the exchange is not owned by sender
		JE  MReq04              ; return to the caller with error
		MOV EAX, ErcNotOwner    ; in the EAX register.
		JMP MReqEnd				; Get out
MReq04:
		CLI						; No interruptions from here on
		; Allocate a link block
		MOV EAX,pFreeLB         ; NewLB <= pFreeLB;
		OR EAX,EAX              ; IF pFreeLB=NIL THEN No LBs;
		JNZ MReq08              ;
		MOV EAX,ercNoMoreLBs    ; caller with error in the EAX register
		JMP MReqEnd				; Go home with bad news
MReq08:
		MOV EBX,[EAX.NextLB]    ; pFreeLB <= pFreeLB^.Next
		MOV pFreeLB,EBX         ;
		DEC _nLBLeft			;

        MOV [EAX.LBType],REQLB 		; This is a Request Link Block
		MOV [EAX.NextLB],NIL    	; pLB^.Next <= NIL;
		MOV EBX, [EBP+16]			; RqHandle
		MOV [EAX.DataLo],EBX    	; RqHandle into Lower 1/2 of Msg
		MOV [EAX.DataHi], 0 	   	; Store zero in upper half of pLB^.Data
		PUSH EAX                	; Save pLB on the stack
		CALL deQueueTSS         	; DeQueue a TSS on that Exch
		CMP EAX,NIL             	; Did we get one?
		JNE MReq10	              	; Yes, give up the message
		POP EAX                 	; Get the pLB just saved
		CALL enQueueMsg         	; EnQueue the Message on Exch
		JMP SHORT MReqEnd          	; And get out!
MReq10:
        POP EBX         	        ; Get the pLB just saved into EBX
		MOV [EAX.pLBRet],EBX	    ; and put it in the TSS
		CALL enQueueRdy         	; EnQueue the TSS on the RdyQ
		MOV EAX,pRunTSS    			; Get the Ptr To the Running TSS
		CALL enQueueRdy         	; and put him on the RdyQ
		CALL deQueueRdy         	; Get high priority TSS off the RdyQ
		CMP EAX,pRunTSS         	; If the high priority TSS is the
		JNE MReq12	            	; same as the Running TSS then return
		MOV EAX,ercOk           	; Return to Caller with erc ok.
		JMP SHORT MReqEnd
MReq12:
        MOV pRunTSS,EAX         ; Make the TSS in EAX the Running TSS
		MOV BX,[EAX.Tid]        ; Get the task Id (TR)
		MOV TSS_Sel,BX          ; Put it in the JumpAddr for Task Swtich
		INC _nSwitches			; Keep track of how many swtiches for stats
		JMP FWORD PTR [TSS]     ; JMP TSS (This is the task swtich)
        MOV EAX,ercOk           ; Return to Caller with erc ok.
MReqEnd:
		STI                     ;
		MOV ESP,EBP             ;
		POP EBP                 ;
		RETF 8                  ;
_MoveRequest	ENDP

;=============================================================================
;
; SendMsg - The kernel send primitive. This	sends a non-specific message
; from a running task to an exchange. This may cause a task swtich if
; a task is waiting at the exchange and it is of equal or higher priority
; that the task that sent the message.
;
; Procedural Interface :
;
;       SendMsg(exch, dMsg1, dMsg2):ercType
;
;           exch is a DWORD (4 BYTES) containing the exchange to where the
;           message should be sent.
;
;           dMsg1 & dMsg2 are DWord values defined and understood
;			only by the sending and receiving tasks.
;
SendExchange   EQU [EBP+14h]
MessageHi      EQU DWORD PTR [EBP+10h]
MessageLo      EQU DWORD PTR [EBP+0Ch]

_SendMsg  PROC FAR              ;
		PUSH EBP                ;
		MOV EBP,ESP             ;
		MOV ESI,SendExchange    ; Get Exchange Parameter in ESI
		CMP ESI,nExch           ; If the exchange is out of range
		JNAE Send00             ; the return to caller with error
		MOV EAX,ercOutOfRange   ; in the EAX register.
		JMP SendEnd
Send00:
        MOV EAX,ESI             ; Exch => EAX
		MOV EDX,sEXCH           ; Compute offset of Exch in rgExch
		MUL EDX                 ;
		MOV EDX,prgExch         ; Add offset of rgExch => EAX
		ADD EAX,EDX             ;
		MOV ESI,EAX             ; MAKE ESI <= pExch
		CMP [EAX.Owner],NIL     ; If the exchange is not allocated
		JNE Send01              ; return to the caller with error
		MOV EAX,ercNotAlloc     ; in the EAX register.
		JMP SendEnd				;
Send01:

⌨️ 快捷键说明

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