当前位置: 代码迷 >> 汇编语言 >> call和ret指令到底该不该配对使用,哪位高手深度剖析下面的代码?才几行而已,能重点分析下里面的ret吗?为何这里没call呢
  详细解决方案

call和ret指令到底该不该配对使用,哪位高手深度剖析下面的代码?才几行而已,能重点分析下里面的ret吗?为何这里没call呢

热度:10232   发布时间:2013-02-26 00:00:00.0
call和ret指令到底该不该配对使用,谁深度剖析下面的代码?才几行而已,能重点分析下里面的ret吗?为何这里没call呢?


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 就是直接转移到所指定的目标地址,不对堆栈进行进行操作。
------解决方案--------------------------------------------------------
引用代码:
lea eax, nextstart ;任务切换回来后从nextstart开始
push eax
pushfd ;标志寄存器的值
pushad ;保存EAX -- EDI


popad ;恢复所有通用寄存器,共8个
popfd ;恢复标志寄存器
ret ;跳转到指定任务运行 ;
nextstart:

------解决方案--------------------------------------------------------
探讨
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();

……

------解决方案--------------------------------------------------------
yes, you should
  相关解决方案