📄 mpx88.s
字号:
mov es,dx
mov ss,dx ! interrupt handlers may not make system calls
mov sp,#k_stktop ! so stack is not already switched
! end of inline save
! now set up parameters for C routine sys_call
push bx ! pointer to user message
push ax ! src/dest
push cx ! SEND/RECEIVE/BOTH
sti ! allow SWITCHER to be interrupted
call _sys_call ! sys_call(function, src_dest, m_ptr)
! caller is now explicitly in proc_ptr
mov AXREG(si),ax ! sys_call MUST PRESERVE si
cli
! Fall into code to restart proc/task running.
!*===========================================================================*
!* restart *
!*===========================================================================*
_restart:
! Flush any held-up interrupts.
! This reenables interrupts, so the current interrupt handler may reenter.
! This does not matter, because the current handler is about to exit and no
! other handlers can reenter since flushing is only done when k_reenter == 0.
! In protected mode a jump to p_restart is patched over the following
! code during initialization.
cmp _held_head,#0 ! do fast test to usually avoid function call
jz over_call_unhold
call _unhold ! this is rare so overhead is acceptable
over_call_unhold:
mov si,_proc_ptr
decb _k_reenter
mov ax,AXREG(si) ! start restoring registers from proc table
! could make AXREG == 0 to use lodw here
mov bx,BXREG(si)
mov cx,CXREG(si)
mov dx,DXREG(si)
mov di,DIREG(si)
mov bp,BPREG(si)
mov es,ESREG(si)
mov ss,SSREG(si)
mov sp,SPREG(si)
push PSWREG(si) ! fake interrupt stack frame
push CSREG(si)
push PCREG(si)
! could put si:ds together to use
! lds si,SIREG(si)
push DSREG(si)
mov si,SIREG(si)
pop ds
iret
restart1:
decb _k_reenter
pop ax
pop bx
pop cx
pop dx
pop di
pop bp
pop es
pop si
pop ds
add sp,#2 ! skip return adr
iret
!*===========================================================================*
!* int00-07 *
!*===========================================================================*
! These are entry points for exceptions (processor generated interrupts,
! usually caused by error conditions such as an attempt to divide by zero)
_int00: ! interrupt through vector 0
push ax
movb al,#0
jmp exception
_int01: ! interrupt through vector 1, etc
push ax
movb al,#1
jmp exception
_int02:
push ax
movb al,#2
jmp exception
_int03:
push ax
movb al,#3
jmp exception
_int04:
push ax
movb al,#4
jmp exception
_int05:
push ax
movb al,#5
jmp exception
_int06:
push ax
movb al,#6
jmp exception
_int07:
push ax
movb al,#7
!jmp exception
exception:
cseg movb ex_number,al ! it is cumbersome to get this into dseg
pop ax
call save
cseg push ex_number ! high byte is constant 0
call _exception ! do whatever is necessary (sti only if safe)
add sp,#2
cli
ret
!*===========================================================================*
!* level0_call *
!*===========================================================================*
_level0_call:
call save
jmp @_level0_func
!*===========================================================================*
!* idle_task *
!*===========================================================================*
_idle_task: ! executed when there is no work
jmp _idle_task ! a "hlt" before this fails in protected mode
!*===========================================================================*
!* data *
!*===========================================================================*
! NB some variables are stored in code segment.
ex_number: ! exception number
.space 2
!*===========================================================================*
!* variants for 286 protected mode *
!*===========================================================================*
! Most routines are different in 286 protected mode.
! The only essential difference is that an interrupt in protected mode
! (usually) switches the stack, so there is less to do in software.
! These functions are reached along jumps patched in by klib_init_prot():
.define p_restart ! replaces _restart
.define p_save ! replaces save
! These exception and software-interrupt handlers are enabled by the new
! interrupt vector table set up in protect.c:
.define _divide_error ! _int00
.define _single_step_exception ! _int01
.define _nmi ! _int02
.define _breakpoint_exception ! _int03
.define _overflow ! _int04
.define _bounds_check ! _int05
.define _inval_opcode ! _int06
.define _copr_not_available ! _int07
.define _double_fault ! (286 trap)
.define _copr_seg_overrun ! (etc)
.define _inval_tss
.define _segment_not_present
.define _stack_exception
.define _general_protection
.define _p_s_call ! _s_call
.define _level0_call
! The hardware interrupt handlers need not be altered apart from putting
! them in the new table (save() handles the differences).
! Some of the intxx handlers (those for exceptions which do not push an
! error code) need not have been replaced, but the names here are better.
#include "protect.h"
/* Selected 286 tss offsets. */
#define TSS2_S_SP0 2
! imported variables
.extern _tss
.extern _level0_func
!*===========================================================================*
!* p_save *
!*===========================================================================*
! Save for 286 protected mode.
! This is much simpler than for 8086 mode, because the stack already points
! into process table, or has already been switched to the kernel stack.
p_save:
cld ! set direction flag to a known value
pusha ! save "general" registers
push ds ! save ds
push es ! save es
mov dx,ss ! ss is kernel data segment
mov ds,dx ! load rest of kernel segments
mov es,dx
mov bp,sp ! prepare to return
incb _k_reenter ! from -1 if not reentering
jnz set_p1_restart ! stack is already kernel stack
mov sp,#k_stktop
push #p_restart ! build return address for interrupt handler
jmp @RETADR-P_STACKBASE(bp)
set_p1_restart:
push #p1_restart
jmp @RETADR-P_STACKBASE(bp)
!*===========================================================================*
!* p_s_call *
!*===========================================================================*
_p_s_call:
cld ! set direction flag to a known value
sub sp,#6*2 ! skip RETADR, ax, cx, dx, bx, st
push bp ! stack already points into process table
push si
push di
push ds
push es
mov dx,ss
mov ds,dx
mov es,dx
incb _k_reenter
mov si,sp ! assumes P_STACKBASE == 0
mov sp,#k_stktop
! end of inline save
sti ! allow SWITCHER to be interrupted
! now set up parameters for C routine sys_call
push bx ! pointer to user message
push ax ! src/dest
push cx ! SEND/RECEIVE/BOTH
call _sys_call ! sys_call(function, src_dest, m_ptr)
! caller is now explicitly in proc_ptr
mov AXREG(si),ax ! sys_call MUST PRESERVE si
cli
! Fall into code to restart proc/task running.
p_restart:
! Flush any held-up interrupts.
! This reenables interrupts, so the current interrupt handler may reenter.
! This does not matter, because the current handler is about to exit and no
! other handlers can reenter since flushing is only done when k_reenter == 0.
cmp _held_head,#0 ! do fast test to usually avoid function call
jz p_over_call_unhold
call _unhold ! this is rare so overhead is acceptable
p_over_call_unhold:
mov si,_proc_ptr
lldt P_LDT_SEL(si) ! enable segment descriptors for task
lea ax,P_STACKTOP(si) ! arrange for next interrupt
mov _tss+TSS2_S_SP0,ax ! to save state in process table
mov sp,si ! assumes P_STACKBASE == 0
p1_restart:
decb _k_reenter
pop es
pop ds
popa
add sp,#2 ! skip return adr
iret ! continue process
!*===========================================================================*
!* exception handlers *
!*===========================================================================*
_divide_error:
push #DIVIDE_VECTOR
jmp p_exception
_single_step_exception:
push #DEBUG_VECTOR
jmp p_exception
_nmi:
push #NMI_VECTOR
jmp p_exception
_breakpoint_exception:
push #BREAKPOINT_VECTOR
jmp p_exception
_overflow:
push #OVERFLOW_VECTOR
jmp p_exception
_bounds_check:
push #BOUNDS_VECTOR
jmp p_exception
_inval_opcode:
push #INVAL_OP_VECTOR
jmp p_exception
_copr_not_available:
push #COPROC_NOT_VECTOR
jmp p_exception
_double_fault:
push #DOUBLE_FAULT_VECTOR
jmp errexception
_copr_seg_overrun:
push #COPROC_SEG_VECTOR
jmp p_exception
_inval_tss:
push #INVAL_TSS_VECTOR
jmp errexception
_segment_not_present:
push #SEG_NOT_VECTOR
jmp errexception
_stack_exception:
push #STACK_FAULT_VECTOR
jmp errexception
_general_protection:
push #PROTECTION_VECTOR
jmp errexception
!*===========================================================================*
!* p_exception *
!*===========================================================================*
! This is called for all exceptions which do not push an error code.
p_exception:
sseg pop ds_ex_number
call p_save
jmp p1_exception
!*===========================================================================*
!* errexception *
!*===========================================================================*
! This is called for all exceptions which push an error code.
errexception:
sseg pop ds_ex_number
sseg pop trap_errno
call p_save
p1_exception: ! Common for all exceptions.
push ds_ex_number
call _exception
add sp,#2
cli
ret
!*===========================================================================*
!* data *
!*===========================================================================*
! These declarations assure that storage will be allocated at the very
! beginning of the kernel data section, so the boot monitor can be easily
! told how to patch these locations. Note that the magic number is put
! here by the compiler, but will be read by, and then overwritten by,
! the boot monitor. When the kernel starts the sizes array will be
! found here, as if it had been initialized by the compiler.
.data
begdata:
_sizes: ! sizes of kernel, mm, fs filled in by boot
.data2 0x526F ! this must be the first data entry (magic #)
.space 16*2*2-2 ! monitor uses previous 2 words and this space
! extra space allows for additional servers
.bss
begbss:
k_stack:
.space K_STACK_BYTES ! kernel stack
k_stktop: ! top of kernel stack
ds_ex_number:
.space 2
trap_errno:
.space 2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -