|
楼主 |
发表于 2009-4-16 11:31:57
|
显示全部楼层
连载五、
;*********************************************************************************************************
; START MULTITASKING
; void OSStartHighRdy(void)
;
; The stack frame is assumed to look as follows:(堆栈的生长方向见下面:)
;
; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory)
; ES (内存低端)
; DI
; SI
; BP
; SP
; BX
; DX
; CX
; AX
; OFFSET of task code address (任务起始地址偏移地址=IP)
; SEGMENT of task code address (任务起始地址段地址=CS)
; Flags to load in PSW (CPU状态寄存器)
; OFFSET of task code address (任务起始地址偏移地址=IP)
; SEGMENT of task code address (任务起始地址段地址=CS)
; OFFSET of 'pdata'
; SEGMENT of 'pdata' (High memory)
; (内存高端)
; Note : OSStartHighRdy() MUST:
; a) Call OSTaskSwHook() then,
; b) Set OSRunning to TRUE,
; c) Switch to the highest priority task.
;*********************************************************************************************************
//--------------------------------------------------------------------------------------------------------
//存储路径=C:\SOFTWARE\uCOS-II\Ix86L\BC45\OS_CPU_C.ASM
//--------------------------------------------------------------------------------------------------------
//OSStartHighRdy()由函数OSStart()函数调用,功能是让进入就绪态的优先级最高的任务运行。
//函数OSStartHighRdy()默认指针OSTCBHighRdy指向优先级最高的就绪态任务的任务控制块(OS_TCB)。
//下图是由函数OSTaskCreate()建立的任务的堆栈结构,在OSStart()函数调用OSStartHighRdy()函数
//之前,任务堆栈结构就是这个样子。其中:OSTCBHighRdy->OSTCBStkPtr指向任务堆栈的项端。
//
// | |
// | 存储器地址低端 |
// ----------------------------
// | DS | <---- OSTCBHighRdy->OSTCBStkPtr
// ----------------------------
// | ES=0x4444 |
// ----------------------------
// | DI=0x3333 |
// ----------------------------
// | SI=0x2222 |
// ----------------------------
// | BP=0x1111 | ^
// ----------------------------
// | SP=0x0000 |
// ----------------------------
// | BX=0xBBBB |
// ----------------------------
// | DX=0xDDDD |
// ----------------------------
// | CX=0xCCCC |
// ----------------------------
// | AX=0xAAAA |
// ----------------------------
// | OFF task | -------
// -------------------- | |
// | SEG task | |----> 模仿中断
// -------------------- | |
// | PSW=0x0202 | -------
// --------------------
// | OFF task | <---- 执行IRET后SS:SP指向此处
// -------------------- |
// | SEG task |
// ----------------------------
// | OFF pdata |
// ----------------------------
// | SEG pdata |
// --------------------
// | 存储器地址低端 |
//
//
// 图1 任务创建时的8086堆栈结构
//--------------------------------------------------------------------------------------------------------
_OSStartHighRdy PROC FAR
MOV AX, SEG _OSTCBHighRdy ; 获取多任务操作系统最高优先级任务控制块OSTCBHighRdy的数据段段地址 ---> DS
MOV DS, AX ;
;
CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook
;
MOV AL, 1 ; 设置 OSRunning = TRUE;
MOV BYTE PTR DS:_OSRunning, AL ; 说明:由于MSDOS要求访问变量时,必须指出变量所在段的段地址,
; ; 而变量OSRunning和OSTCBHighRdy在同一段,因此只需得到OSTCBHighRdy的数据段段地址(DS)即可。
//--------------------------------------------------------------------------------------
//说明:在MSDOS操作系统,指令LES reg , src 执行的动作如下:
// (1)(reg) <--- src
// (2)(ES) <--- (src+2)
//例如:LES BX, DWORD PTR DS:_OSTCBHighRdy
// (1)(BX)<--- OSTCBHighRdy
// (2)(ES) <--- (OSTCBHighRdy+2)
//我们知道在任务控制块OS_TCB中,OSTCBStkPtr是指向任务堆栈栈顶的指针,为了汇编语言方便访问成员OSTCBStkPtr,特意定义在结构体的开始位置。
//注解:
// OSStartHighRdy()从任务控制块OS_TCB中获得并恢复堆栈指针
//--------------------------------------------------------------------------------------
LES BX, DWORD PTR DS:_OSTCBHighRdy ; 获取最高优先级任务控制块OSTCBHighRdy的段地址和偏移地址 ---> ES:BX
MOV SS, ES:[BX+2] ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
MOV SP, ES:[BX+0] ; 从任务堆栈中获取SS:SP
;
POP DS ; 把任务堆栈中保存的DS值恢复到CPU的DS寄存器中
POP ES ; 把任务堆栈中保存的ES值恢复到CPU的ES寄存器中
POPA ; 把任务堆栈中保存的AX,BX,CX,DX,SI,DI,
;
//----------------------------------------------------------------------------------------
//执行IRET指令,从中断返回,这里建立了任务的堆栈结构,看起来好像刚刚发生了中断,所有的CPU
//寄存器都被推入堆栈中。IRET指令将任务的入口地址从堆栈中弹出,并把任务入口地址放到CS:IP
//寄存器中。地址后面跟着的值(叫做程序状态字)放在PSW寄存器中。
// 执行IRET指令时,堆栈指针(SS:SP)指向任务返回地址,这样看起来像是任务被一个普通
//函数调用了,SS:SP+4指向自变量pdada,pdata会给任务传递参数。换句话说,任务无须了解
//它是被OSStartHighRdy()调用的,还是被其它函数调用的。
//----------------------------------------------------------------------------------------
IRET ; 从任务私栈中弹出程序状态字--->PSW、任务起始地址的段地址--->CS、任务起始地址的偏移地址--->IP
; 然后跳转到CS:IP位置,开始运行当前最高优先级任务。
_OSStartHighRdy ENDP
;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From task level)
; void OSCtxSw(void)
;
; Note(s): 1) Upon entry,
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdy points to the OS_TCB of the task to resume
;
; 2) The stack frame of the task to suspend looks as follows:
;
; SP -> OFFSET of task to suspend (Low memory)
; SEGMENT of task to suspend
; PSW of task to suspend (High memory)
;
; 3) The stack frame of the task to resume looks as follows:
;
; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory)
; ES
; DI
; SI
; BP
; SP
; BX
; DX
; CX
; AX
; OFFSET of task code address
; SEGMENT of task code address
; Flags to load in PSW (High memory)
;*********************************************************************************************************
//-----------------------------------------------------
//存储路径=C:\SOFTWARE\uCOS-II\Ix86L\BC45\OS_CPU_C.ASM
//-----------------------------------------------------
// OSCtxSW()是一个任务级的任务切换函数,在任务调用时,区别在于中断服务程序中调用的是OSIntCtxSW()。
// 在80x86系统上,它是通过执行一条软中断指令实现任务切换,软中断向量指向OSCtxSW()。
// 在uC/OS-II中,如果任务调用了某函数,而该函数的执行结果可能造成系统任务重新调度,例如唤醒了一个
// 优先级更高的任务,使当前运行着的任务已经不是最重要的任务了,则uC/OS-II会在函数的未尾调用OSSched()。
// 如果OSSched()判断需要进行任务调度,则会找到该任务控制块OS_TCB的地址,并将该地址复制给OSTCBHighRdy,
// 然后通过宏OS_TASK_SW()执行软中断,进行任务切换。
_OSCtxSw PROC FAR
//---------------------------------------------------------------------------------------------
//说明,由于任务调度函数OSSched()执行宏定义OS_TASK_SW()实际上是通过执行软中断INT80,因此首先把
//程序状态字PSW推入堆栈、然后把执行软中断指令的任务(调用OS_TASK_SW()的任务)的中断返回地址
//(段地址和偏移地址)。
//
// | |
// | 存储器地址低端 |
// --------------------
// | OFF task | <---- SP(说明:执行OS_TASK_SW()后,当前任务私栈的堆栈指针SP位置)
// --------------------
// | SEG task |
// --------------------
// | PSW | <---- SP'(说明:当前任务调用OSSched()进行任务切换,执行OS_TASK_SW()前,当前任务私栈的堆栈指针SP位置)
// --------------------
// | 存储器地址低端 |
// | |
//
// 图2 执行OS_TASK_SW()跳转到OSCtxSW()时,堆栈结构示意图
//---------------------------------------------------------------------------------------------
;
PUSHA ; 将挂起任务的其它寄存器保存到当前任务堆栈中
PUSH ES ;
PUSH DS ;
//
// | |
// | 存储器地址低端 |
// --------------------
// | DS | <---- 【SP】(说明:执行PUSHA/PUSH ES/PUSH DS后,当前任务私栈的堆栈指针SP位置)
// --------------------
// | ES |
// --------------------
// | DI |
// --------------------
// | SI |
// --------------------
// | BP |
// --------------------
// | SP |
// --------------------
// | BX |
// --------------------
// | DX |
// --------------------
// | CX |
// --------------------
// | AX |
// --------------------
// | OFF task | <---- SP(说明:调用宏定义OS_TASK_SW(),进入OSCtxSW()函数后,当前任务私栈的堆栈指针SP位置)
// --------------------
// | SEG task |
// --------------------
// | PSW | <---- SP'(说明:执行OS_TASK_SW()前,当前任务私栈的堆栈指针SP位置)
// --------------------
// | 存储器地址低端 |
// | |
//
// 图3 执行PUSA
// PUSH ES
// PUSH DS后,堆栈结构示意图
//---------------------------------------------------------------------------------------------
;
MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered
MOV DS, AX ;
;
LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP
MOV ES:[BX+2], SS ; 把指向新的堆栈指针位置保存在任务控制块OS_TCB的OSTCBStkPtr成员中
MOV ES:[BX+0], SP ; 即图3中【SP】的位置。
;
CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook
;
MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy
MOV DX, WORD PTR DS:_OSTCBHighRdy ; OSTCBHighRdy复制给OSTCBCur,这样,高优先级任务就成为当前任务。
MOV WORD PTR DS:_OSTCBCur+2, AX ;
MOV WORD PTR DS:_OSTCBCur, DX ;
;
MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy
MOV BYTE PTR DS:_OSPrioCur, AL ; OSPrioHighRdy复制给OSPrioCur,高优先级任务的优先级号就成为当前任务的优先级号
;
LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
MOV SS, ES:[BX+2] ;
MOV SP, ES:[BX] ; 从高优先级任务的私栈中弹出高优先级任务的堆栈指针SS:SP
;
POP DS ; Load new task's context(装载新任务的上下文内容)
POP ES ; 从高优先级任务的私栈中弹出“DS”值到CPU的DS寄存器中
POPA ; 从高优先级任务的私栈中弹出“ES”值到CPU的ES寄存器中
; ; 从高优先级任务的私栈中弹出“AX”、“CX”,“DX”、“BX”值到CPU的AX、CX、DX、BX寄存器中
//---------------------------------------------------------------------------------------------------
//执行IRET(中断返回指令),则高优先级任务的私栈中弹出:
//(1)“PSW”程序状态字值到CPU的PSW寄存器中
//(2)高优先级任务断点地址的偏移地址到CPU的IP寄存器中
//(3)高优先级任务断点地址的段地址到CPU的CS寄存器中
//(4)处理器开始从上次断点位置,继续运行高优先级任务
//---------------------------------------------------------------------------------------------------
IRET ; Return to new task(跳转到高优先级任务的断点处开始运行)
;
_OSCtxSw ENDP
;*********************************************************************************************************
; HANDLE TICK ISR
;
; Description: This function is called 199.99 times per second or, 11 times faster than the normal DOS
; tick rate of 18.20648 Hz. Thus every 11th time, the normal DOS tick handler is called.
; This is called chaining. 10 times out of 11, however, the interrupt controller on the PC
; must be cleared to allow for the next interrupt.
;
; Arguments : none
;
; Returns : none
;
; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below.
;
; Save all registers on the current task's stack;
; OSIntNesting++;
; if (OSIntNesting == 1) {
; OSTCBCur->OSTCBStkPtr = SS:SP
; }
; OSTickDOSCtr--;
; if (OSTickDOSCtr == 0) {
; OSTickDOSCtr = 11;
; INT 81H; Chain into DOS every 54.925 mS
; (Interrupt will be cleared by DOS)
; } else {
; Send EOI to PIC; Clear tick interrupt by sending an End-Of-Interrupt to the 8259
; PIC (Priority Interrupt Controller)
; }
; OSTimeTick(); Notify uC/OS-II that a tick has occured
; OSIntExit(); Notify uC/OS-II about end of ISR
; Restore all registers that were save on the current task's stack;
; Return from Interrupt;
;*********************************************************************************************************
;
//-----------------------------------------------------
//存储路径=C:\SOFTWARE\uCOS-II\Ix86L\BC45\OS_CPU_C.ASM
//-----------------------------------------------------
//
//说明:在PC中,时钟节拍由硬件定时器产生,硬件定时器会中断CPU,间隙是54.93ms(18.20648HZ)。uC/OS-II将时钟
//节拍频率设置为200HZ。PC机时钟节拍的中断向量为0x08,uC/OS-II将此向量截取,使之指向uC/OS-II的时钟节拍中断
//服务程序子程序OSTickISR(),而原先的0x08中断向量保存在中断向量129(0x81)中。
//为满足DOS的需要,原先的中断服务程序还必须每隔54.93ms调用1次。
//
//////////////////////////////////////////////////////////////////////////
// 在什么时候启动时钟节拍中断
//////////////////////////////////////////////////////////////////////////
//(1)、在OSStart()运行之后,uC/OS-II启动运行的第1个任务中初始化节拍中断。
//这个任务是调用OSStart()之前建立的任务中优先级最高的任务
//////////////////////////////////////////////////////////////////////////
// 错误的时候启动时钟节拍中断
//////////////////////////////////////////////////////////////////////////
//(1)、在OSInit()和OSStart()之间打开了时钟节拍中断。
_OSTickISR PROC FAR
;
//-------------------------------------------------------------------------------
//同所有uC/OS-II的中断服务程序一样,所有的寄存器必须保存在当前任务的堆栈中
//-------------------------------------------------------------------------------
PUSHA ; Save interrupted task's context
PUSH ES
PUSH DS
;
//-------------------------------------------------------------------------------
//OSIntNesting++; if (OSIntNesting == 1)
//当进入中断服务子程序ISR时,必须告诉uC/OS-II,进入中断服务子程序了。可通过调用
//OSIntEnter()实现,或者直接给中断嵌套层数OSIntNesting加1的方式实现。
//(1)、直接给中断嵌套层数OSIntNesting加1会更快一些。
//(2)、OSIntEnter()会检查OSIntNesting是否超过了255,这样,中断嵌套更安全。
//-------------------------------------------------------------------------------
MOV AX, SEG(_OSIntNesting) ; Reload DS
MOV DS, AX
INC BYTE PTR DS:_OSIntNesting ; Notify uC/OS-II of ISR
;
//-------------------------------------------------------------------------------
//如果中断嵌套层数OSIntNesting=1,则没有中断嵌套,必须把堆栈指针SS:SP保存到当前任务
//的任务控制块OS_TCB的OSTCBStkPtr成员中。
//-------------------------------------------------------------------------------
CMP BYTE PTR DS:_OSIntNesting, 1 ; if (OSIntNesting == 1)
JNE SHORT _OSTickISR1
MOV AX, SEG(_OSTCBCur) ; Reload DS
MOV DS, AX
LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP
MOV ES:[BX+2], SS ; CPU堆栈指针SS:SP保存到当前任务的
MOV ES:[BX+0], SP ; 任务控制块OS_TCB的OSTCBStkPtr成员中
//-------------------------------------------------------------------------------
//计数器OSTickDOSCtr减1,当OSTickDOSCtr为0时,调用DOS的时钟节拍处理函数(DOS系统
//原中断服务程序),同时初始化计数器OSTickDOSCtr为11。
//-------------------------------------------------------------------------------
_OSTickISR1:
MOV AX, SEG(_OSTickDOSCtr) ; Reload DS
MOV DS, AX
DEC BYTE PTR DS:_OSTickDOSCtr
CMP BYTE PTR DS:_OSTickDOSCtr, 0
JNE SHORT _OSTickISR2 ; Every 11 ticks (~199.99 Hz), chain into DOS
;
MOV BYTE PTR DS:_OSTickDOSCtr, 11
INT 081H ; 调用DOS的时钟节拍处理函数
JMP SHORT _OSTickISR3
//-------------------------------------------------------------------------------
//发送中断结束命令(EOI)。MSDOS操作系统相关知识背景:
// 当某一个中断源的服务程序完成时,必须给8259A一个中断结束指令,使这个源在ISR中
//的相应位复位。在不同的工作情况下,8259A可以有几种不同的给出中断结束命令的方法:
//(1)、自动中断结束模式(AEOI)
// 这种方式只能用于不要求中断嵌套的情况
//(2)、非自动中断结束模式(EOI)
// 在这种工作方式下,当中断服务程序完成从中断服务程序返回前,必须输送中断结束
//(EOI)命令。若是在8259A_级连的情况下,则必须送两个EOI命令,一个送从8259A,另一个
//送给主8259A。
//-------------------------------------------------------------------------------
// PC-DOS 8259A中断控制器口地址
//(1)、20H口
// 中断命令寄存器在每次外部中断结束以后,要给该口发送中断结束信号,其指令为
// MOV AL,20H
// OUT 20H,AL
//(2)、21H口 ---> 中断屏蔽寄存器
// 8259A芯片可以接收8个外部可屏蔽中断。这些中断有两种状态,即允许和屏蔽状态。
//21H口的8位分别对应于8个外部中断源,某位为0,则允许接收相应的中断,否则不接收相
//应的中断。其对应关系如下图:
// ------------------------------------------------------------------
// 7 6 5 4 3 2 1 0
// ------------------------------------------------------------------
// | | | | | | | |
// | | | | | | | ---> 定时器中断
// | | | | | | --->键盘中断
// | | | | | --->保留
// | | | | --->异步通讯口2
// | | | --->异步通讯口1
// | | --->硬盘中断
// | --->软盘中断
// --->并行打印机
//
// 图1 中断屏蔽寄存器位定义
//-------------------------------------------------------------------------------
_OSTickISR2:
MOV AL, 20H ; Move EOI code into AL.
MOV DX, 20H ; Address of 8259 PIC in DX.
OUT DX, AL ; Send EOI to PIC if not processing DOS timer.
//-------------------------------------------------------------------------------
//OSTickISR()【uC/OS-II的时钟节拍】调用OSTimeTick()函数,这样uC/OS-II就给所有延迟
//任务的等待时间以及有限等待某事件发生的任务的等待时间的节拍参数减1。
//-------------------------------------------------------------------------------
_OSTickISR3:
CALL FAR PTR _OSTimeTick ; Process system tick
//-------------------------------------------------------------------------------
//当前面代码全部执行完毕,调用OSIntExit()函数。如果uC/OS-II的时钟节拍OSTickISR()
//或者其它嵌套的中断服务子程序使一个更高优先级的任务进入了就绪态,并且当前中断服
//务子程序已经脱离了中断嵌套(即OSIntNesting=0),那么OSIntExit()不再返回时钟节
//拍OSTickISR()。此时OSIntCtxSW()恢复新任务的所有寄存器,并执行一条IRET指令。
// 如果中断服务子程序没有脱离中断嵌套,或者中断服务子程序没有使更高优先级的任务
//进入就绪态,OSIntExit()就返回OSTickISR(),即返回uC/OS-II的时钟节拍中断服务子程
//序。
//-------------------------------------------------------------------------------
CALL FAR PTR _OSIntExit ; Notify uC/OS-II of end of ISR
//-------------------------------------------------------------------------------
// 如果OSIntExit()返回到这里,则是因为OSIntExit()没有发现更高优先级的任务。这样
//被中断任务的寄存器会被恢复。当执行IRET指令时,中断服务子程序返回,让被中断了的
//任务继续运行。
//-------------------------------------------------------------------------------
POP DS ; Restore interrupted task's context
POP ES
POPA
;
IRET ; Return to interrupted task
;
_OSTickISR ENDP
;
;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From an ISR)
; void OSIntCtxSw(void)
;
; Note(s): 1) Upon entry,
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdy points to the OS_TCB of the task to resume
;
; 2) The stack frame of the task to suspend looks as follows:
;
; OSTCBCur->OSTCBStkPtr ------> DS (Low memory)
; ES
; DI
; SI
; BP
; SP
; BX
; DX
; CX
; AX
; OFFSET of task code address
; SEGMENT of task code address
; Flags to load in PSW (High memory)
;
;
; 3) The stack frame of the task to resume looks as follows:
;
; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory)
; ES
; DI
; SI
; BP
; SP
; BX
; DX
; CX
; AX
; OFFSET of task code address
; SEGMENT of task code address
; Flags to load in PSW (High memory)
;*********************************************************************************************************
//-----------------------------------------------------
//存储路径=C:\SOFTWARE\uCOS-II\Ix86L\BC45\OS_CPU_C.ASM
//-----------------------------------------------------
//由于中断可能会使更高优先级的任务进入就绪态,为了让更高优先级的任务能立即运行,需要
//进行任务切换。在中断服务子程序的最后,OSIntExit()函数会调用 OSIntCtxSW()函数做任务
//切换,故OSIntCtxSW()又称为中断级的任务切换函数。由于调用OSIntCtxSW()之前已经发生了
//中断,中断服务子程序会执行PUSHA/PUSH ES/PUSH DS将被挂起任务的现场保存到该挂起任务
//的私栈中。因此OSIntCtxSW()不会再次保存被中断了的任务的现场到该任务的堆栈中。
// OSIntCtxSW()大部分代码和OSCtxSW()的代码相同,不同之处是,由于中断已经发生,此处
//无需再保存CPU寄存器(没有PUSHA,PUSH ES,PUSH DS指令)。
// 特别需要指出的是,当中断嵌套=1时,时钟节拍中断服务子程序已经将被中断了的任务的
//堆栈指针保存在该任务的任务控制块OS_TCB。
//-----------------------------------------------------------------------------------
_OSIntCtxSw PROC FAR
;
CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook
;
MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered
MOV DS, AX ;
;
//---------------------------------------------------------------------------
//OSTCBHighRdy复制给OSTCBCur(高优先级任务的任务控制块复制给正运行任务的任务控制块指针变量中)
//---------------------------------------------------------------------------
MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy
MOV DX, WORD PTR DS:_OSTCBHighRdy ;
MOV WORD PTR DS:_OSTCBCur+2, AX ;
MOV WORD PTR DS:_OSTCBCur, DX ;
//---------------------------------------------------------------------------
//OSPrioHighRdy复制给OSPrioCur(高优先级任务的优先级号复制给正运行任务的优先级号变量中)
//---------------------------------------------------------------------------
MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy
MOV BYTE PTR DS:_OSPrioCur, AL
;
//---------------------------------------------------------------------------
//得到高优先级任务的堆栈指针SS:SP
//---------------------------------------------------------------------------
LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
MOV SS, ES:[BX+2] ;
MOV SP, ES:[BX] ;
//---------------------------------------------------------------------------
//高优先级任务的现场恢复到CPU
//---------------------------------------------------------------------------
POP DS ; Load new task's context
POP ES ;
POPA ;
//---------------------------------------------------------------------------
//跳转到高优先级任务的断点地址,继续运行高优先级任务。
//---------------------------------------------------------------------------
IRET ; Return to new task
;
_OSIntCtxSw ENDP |
|