UINT32 uwIntSave;
volatile TSK_CB_S *pstSwitchIn;
volatile TSK_CB_S *pstSwitchOut;
//extern VOID osTskSwitchEntry(TSK_CB_S *pstSwitchIn, TSK_CB_S *pstSwitchOut);
uwIntSave = uniIntDisable();
_asm{
lea eax, nextstart ;任务切换回来后从nextstart开始
push eax
pushfd ;标志寄存器的值
pushad ;保存EAX -- EDI
mov ebx, [g_pRunningTask]
mov [ebx], esp ;把堆栈入口的地址保存到当前TCB结构中
}
pstSwitchOut = g_pRunningTask;
pstSwitchIn = g_pHighestTask;
g_pRunningTask->usTaskStatus &= ~OS_TSK_RUNNING;
//OSTaskSwHook();
g_pRunningTask = g_pHighestTask;
g_pRunningTask->usTaskStatus |= OS_TSK_RUNNING;
if (pstSwitchOut != pstSwitchIn)
{
//osTskSwitchEntry((TSK_CB_S *)pstSwitchIn, (TSK_CB_S *)pstSwitchOut);
}
uniIntRestore(1);
_asm{
mov ebx, [g_pRunningTask]
mov esp, [ebx] ;得到g_pHighestTask的esp
popad ;恢复所有通用寄存器,共8个
popfd ;恢复标志寄存器
ret ;跳转到指定任务运行 ;
nextstart:
}
//任务切换回来的运行地址
return;
------解决方案--------------------------------------------------------
如果不明白中断机制、任务切换机制,还是先不要看这些了。可用先找些更简单的看看,等熟悉到了一定程度之后可以再看它们。总在这种细节上纠缠,也只是浪费时间,没有什么实际的意义。
------解决方案--------------------------------------------------------
这类功能或实现,都是不可预料地打断当前程序的执行流程,然后再进行恢复以继续运行的,这样的情况之下,何来的 call,你觉得可以由谁来 call ?打断当前的执行,有相应的对当前程序现场的保存操作,其中就有恢复时继续运行的地址,要将执行流程交还给被打断的程序,最简单的就是在恢复了其它的状态之后,直接通过 ret 指令经由保存在堆栈里的返回地址切换过去了;其它方法也不是不可以,只是远不如这个简单。所以,这里的 ret 只是个执行流程切换的手段,不是通常意义上的子程/函数调用的返回,更无须纠结于其究竟和什么地方的哪个 call 指令配对,因为那个 call 指令根本就不存在。
------解决方案--------------------------------------------------------
当然有区别了。ret 将栈顶的内容作为新的目标地址进行转移的,并将该内存出栈。jmp 就是直接转移到所指定的目标地址,不对堆栈进行进行操作。
------解决方案--------------------------------------------------------
------解决方案--------------------------------------------------------
------解决方案--------------------------------------------------------
yes, you should