📄 os_cpu_a.asm
字号:
;
; 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)
;*********************************************************************************************************
_OSCtxSw PROC FAR ;在80x86处理器上,软中断指令把状态寄存器SW的值推入当前的任务栈中,接着
;入栈的是执行软中断指令的任务(调用OS_TASK_SW()的任务)的中断返回地址(段地址和偏移量地址)。
;
PUSHA ; Save current task's context把挂起任务的其他CPU寄存器保存到当前任务堆
;栈中
; pusha等价于
; push ax
; push bx
; push cx
; push dx
; push si
; push di
; push bp
; push sp
; pushf
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;指向新的堆栈结构的指针保存在任务控制块
;OS_TCB中。这个指针包括堆栈段寄存器SS和堆栈指针寄存器SP。UCOS将堆栈指针放在任务控制块OS_TCB结构的开头,这样用汇编语言可以
;很容易的保存和恢复堆栈指针。
; LES 指针送寄存器和ES指令
;
; 格式为 LES REG, SRC
; 执行的操作: (REG)<----(SRC)
; (ES)<-----(SRC + 2)
; 把源操作数指定的4个相继字节送到由指令指定的寄存器及ES寄存器中,该指令常指定DI寄存器。
;
; LES DI,[BX]
; 如指令执行前 (DS) = B000H, (BX) = 080AH, (0B080AH) = 05AEH,
; (0B080CH) = 4000H
; 则指令执行后 (DI) = 05AEH, (ES) = 4000H
MOV ES:[BX+2], SS ;
MOV ES:[BX+0], SP ;
;
CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook调用可有用户定义的应用程序接口函数
;OSTaskSwHook().注意:当调用 OSTaskSwHook()时,OSTCBCur指向当前任务的任务控制块OS_TCB,而OSTCBHighRdy指向新任务的任务控制
;块OS_TCB。这样可在借口函数OSTaskSwHook()中与上述2个任务控制块OS_TCB的任何一个打交道。
;如果不想使用OSTaskSwHook(),则可以注释掉这个调用。这样在任务切换时,可节省几个时钟周期。换句话说,若不打算使用
;OSTaskSwHook(),也就没有必要为调用这个函数和从这个函数和从这个函数返回支付额外的CPU负荷。一般情况下,在移植时都会调用这
;个函数。
;
MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy从OSTaskSwHook()返回后,OSTCBHighRdy被复制给
;OSTCBCur。这是因为新任务就是当前任务。
MOV DX, WORD PTR DS:_OSTCBHighRdy ;
MOV WORD PTR DS:_OSTCBCur+2, AX ;
MOV WORD PTR DS:_OSTCBCur, DX ;
;
MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy;OSPrioHighRdy被复制给OSPrioCur。这同样是因
;为新任务就是当前任务。
MOV BYTE PTR DS:_OSPrioCur, AL ;
;
LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr至此,OSCtxSw()把新任务栈中保存的栈
;指针内容传递给处理器的相应寄存器。这是通过从新任务的OS_TCB获得寄存器SS和寄存器SP的值完成的。
MOV SS, ES:[BX+2] ;
MOV SP, ES:[BX] ;
;
POP DS ; Load new task's context从新任务的堆栈中弹出相应值到CPU的其他寄存器。
;
POP ES ;
POPA ;
;
IRET ; Return to new task执行中断返回指令IRET,装入新任务的程序计数器值和
;状态字。执行了这一指令后,处理器使新任务恢复运行。
;注意:在执行OSCtxSw()时,中断是关掉的;执行用户定义的OSTaskSwHook()接口函数时,中断也是关掉的。
;
_OSCtxSw ENDP
PAGE ; /*$PAGE*/
;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From an ISR)
; void OSIntCtxSw(void)
;由于中断可能会使更高优先级的任务进入就绪态,为了让更高优先级的任务能够立即运行,需要进行任务切换。在中断服务子程序的最后
;,OSIntExit()函数会调用OSIntCtxSw()作任务切换,所以OSIntCtxSw()又称为中断级的任务切换函数。由于在调用OSIntCtxSw()之前已
;经发生了中断,OSIntCtxSw()已经默认CPU寄存器保存在被中断了的任务的堆栈中。
;程序清单给出了的代码的大部分与OSCtxSw()的代码相同;不同之处是,由于中断已经发生,此处无需再保存CPU寄存器(没有PUSHA,PUSH
; ES或PUSH DS等指令)。同样,堆栈指针也被中断服务子程序保存在任务控制块OS_TCB中。书上有此过程的图解:
;为了理解他们之间的区别,假设处理器接收到一个中断,并且中断是开着的。处理器完成当前的指令并开始响应中断,进入中断处理程序
;。80X86自动把处理器的SW寄存器推入堆栈,然后把中断任务的返回地址也推入堆栈。接下来CPU从中断向量处找到中断服务子程序的入口
;地址,运行中断服务子程序。在UCOS中,要求在中断服务子程序的开头保存CPU其他寄存器的内容。保存了寄存器的内容后,UCOS还要求
;把堆栈指针保存在任务控制块OS_TCB中。
;此后,必须调用OSIntEnter(),或者直接给全局变量OSIntNesting加一。至此可以任务任务已被挂起,如果需要,则可以切换到另个任务
;现在,中断服务子程序可服务与生产中断的子设备中了。该服务有可能调用了OSMboxPost(),OSQPostFront(),OSQPost(),或
;OSQPostOpt()等函数给其他任务发了消息,从而使一个优先级更高的任务进入了就绪态,需要做任务切换。也可能唤醒了一个更高优先级
;的任务,例如调用了OSTaskResume(),OSTimeTick()以及OSTimeDlyResume()等等,需要任务切换。如果中断服务子程序使一个更高优先
;级的任务进入了就绪态,那么UCOS要求在中断服务子程序完成对中断设备的服务以后,调用OSIntExit()。OSIntExit()主要是告诉UCOS,
;所有嵌套中断都已经退出,可以返回到任务级代码了。换句话说,当中断嵌套层数OSIntNesting减为0时,OSIntExit()就可以返回到
;任务级代码了。当OSInitExit()开始执行时,该函数得知被中断的任务不再是应该继续运行的任务,有更高优先级的任务要运行。这种情
;况下,指针OSTCBHighRdy应该指向新任务的控制块OS_TCB,OSIntExit()会调用OSIntCtxSw()进行任务切换
;
; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -