📄 os_cpu_a.asm
字号:
[BITS 32]
%include 'c32.mac'
global OSTickISR, OSStartHighRdy, OSIntCtxSW, DefIntHandler
global DumpStackHandler, inportb, outportb
extern OSIntEnter, OSTimeTick, OSIntExit, OSTaskSwHook
extern OSRunning, OSTCBHighRdy, OSTCBCur, OSPrioHighRdy
extern OSPrioCur
; OSTickISR
proc OSTickISR
pushad
; Send an end-of-interrupt to the i8259.
mov al,20h
out 20h,al
; Standard uCOS processing.
call OSIntEnter
call OSTimeTick
call OSIntExit
popad
iretd
endproc
;-----------------------------------------------------------------------
; OSStartHighRdy
;-----------------------------------------------------------------------
proc OSStartHighRdy
; Call OSTaskSwHook();
call OSTaskSwHook
; Increment OSRunning by 1 (the documentation says to set it to 1,
; but the ix86l example increments it).
inc dword [OSRunning]
; Load the processor stack pointer with OSTCBHighRdy->OSTCBStkPtr
mov eax,[OSTCBHighRdy] ; Point to TCB of highest priority task ready to run
mov esp,[eax] ; ESP = OSTCBHighRdy->OSTCBStkPtr
; Pop all the processor registers from the stack
popad
; Execute a Return from interrupt intruction;
iretd
endproc
;-----------------------------------------------------------------------
; OSCtxSw
;-----------------------------------------------------------------------
proc OSCtxSw
; PUSH processor registers onto the current task's stack
pushad
; Save the stack pointer into OSTCBCur->OSTCBStkPtr
mov eax,[OSTCBCur]
mov [eax],esp ; Stack pointer is ESP
; Call OSTaskSwHook();
call OSTaskSwHook
; OSPrioCur = OSPrioHighRdy
mov al,[OSPrioHighRdy] ; AL is OSPrioHighRdy
mov [OSPrioCur],al
; OSTCBCur = OSTCBHighRdy
mov eax,[OSTCBHighRdy] ; EAX is OSTCBHighRdy
mov [OSTCBCur],eax
; Load the processor stack pointer with OSTCBHighRdy->OSTCBStkPtr
; Note that EAX is still OSTCBHighRdy.
mov esp,[eax] ; ESP = OSTCBHighRdy->OSTCBStkPtr
; Pop all the processor registers from the stack
popad
; Execute a Return from interrupt intruction;
iretd
endproc
;-----------------------------------------------------------------------
; OSIntCtxSw
;-----------------------------------------------------------------------
proc OSIntCtxSw
; Adjust the stack pointer to remove call to OsIntExit(), locals in
; OsIntExit() and the call to OSIntCtxSw();
;IFDEF _SAVE_INT_STATUS
add esp,12 ; Ignore calls to OSIntExit, PUSHFD and OSIntCtxSw
;ELSE
; add esp,8 ; Ignore calls to OSIntExit and OSIntCtxSw
;ENDIF
; Save the stack pointer into OSTCBCur->OSTCBStkPtr
mov eax,[OSTCBCur]
mov [eax],esp ; Stack pointer is ESP
; Call OSTaskSwHook();
call OSTaskSwHook
; OSPrioCur = OSPrioHighRdy
mov al,[OSPrioHighRdy] ; AL is OSPrioHighRdy
mov [OSPrioCur],al
; OSTCBCur = OSTCBHighRdy
mov eax,[OSTCBHighRdy] ; EAX is OSTCBHighRdy
mov [OSTCBCur],eax
; Load the processor stack pointer with OSTCBHighRdy->OSTCBStkPtr
; Note that EAX is still OSTCBHighRdy.
mov esp,[eax] ; ESP = OSTCBHighRdy->OSTCBStkPtr
; Pop all the processor registers from the stack
popad
; Execute a Return from interrupt intruction;
iretd
endproc
;=======================================================================
; x86 Helper Functions.
;=======================================================================
;-----------------------------------------------------------------------
; void DefIntHandler();
;
; Default interrupt handler. It simply performs an interrupt return.
; It is required to initialize all interrupt entries in the IDT.
;-----------------------------------------------------------------------
proc DefIntHandler
iretd ; Simply return from interrupt.
endproc
;-----------------------------------------------------------------------
; void DumpStackHandler();
;
; This is usefull handler that dumps the last three DWORDS pushed
; on the stack. This is convenient in a fault handler to determine the
; source of the fault. The function never returns.
;
; _DEBUG must be defined for this code to be effective.
;-----------------------------------------------------------------------
%ifdef _DEBUG
proc DumpStackHandler
mov eax,[esp] ; EAX: last pushed DWORD
push eax
call ShowRegister ; Show it
add esp,4
mov eax,[esp+4] ; EAX: previous pushed DWORD
push eax
call ShowRegister ; Show it
add esp,4
mov eax,[esp+8] ; EAX: 2nd previous pushed DWORD
push eax
call ShowRegister
add esp,4
; Enter an infinite loop. It is likely that things went wrong and
; continuing could reset the PC, losing whatever is on the screen.
Here:
jmp Here
endproc
%endif
;-----------------------------------------------------------------------
; UBYTE inportb(UWORD PortNo);
;
; Reads a byte from the specified port. The byte is returned in AL,
; since Microsoft CL uses EAX for returned values.
;-----------------------------------------------------------------------
proc inportb
push ebp
mov ebp,esp
push edx
mov edx,[ebp+8] ; EDX: Port No
in al,dx ; Input the value.
pop edx
pop ebp
ret ; AL contains the value to return.
endproc
;-----------------------------------------------------------------------
; void outportb(UWORD PortNo, UBYTE Value);
;
; Write a value to a specified port.
;-----------------------------------------------------------------------
proc outportb
push ebp
mov ebp,esp
push eax
push edx
mov dx,[ebp+8] ; Get the port.
mov al,[ebp+12] ; Get the value.
out dx,al ; Output the value to the port.
pop edx
pop eax
pop ebp
ret
endproc
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -