搜索
bottom↓
回复: 8

请教:嵌入式实时操作系统μC/OS-Ⅱ (美) Jean J. Labrosse著 随书光盘 例子1:OSCtxSW

[复制链接]

出0入0汤圆

发表于 2009-4-13 09:14:02 | 显示全部楼层 |阅读模式
;*********************************************************************************************************
;                                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)
;*********************************************************************************************************


_OSCtxSw    PROC   FAR
;
            PUSHA                                  ; Save current task's context
            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                   ;
            MOV    ES:[BX+0], 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   ;
            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      ;
;
            LES    BX, DWORD PTR DS:_OSTCBHighRdy  ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
            MOV    SS, ES:[BX+2]                   ;
            MOV    SP, ES:[BX]                     ;
;
            POP    DS                              ; Load new task's context
            POP    ES                              ;
            POPA                                   ;
;
            IRET                                   ; Return to new task


 问题:
  1、
            LES    BX, DWORD PTR DS:_OSTCBHighRdy  ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
            MOV    SS, ES:[BX+2]                   ;
            MOV    SP, ES:[BX]                     ;
        执行上面3条语句,得到高优先级任务(准备运行任务)私栈的栈项指针SS:SP
  2、     POP    DS                              ; Load new task's context
            POP    ES                              ;
            POPA                                   ;
    执行上面3条语句,将高优先级任务私栈中上次保存的现场恢复到CPU相关寄存器中
  3、现在主要问题集中在POPA 这条语句上
     由于POPA是80386指令,是
;              POP   DI
;              POP   SI
;              POP   BP
;              POP  SP
;              POP   BX
;              POP  DX
;              POP   CX
;              POP   AX
          的简写。
    既然前面SS:SP已经指向高优先级任务(准备运行任务)私栈的栈项,那么当执行POP SP时,又将SP指向了另外一个位置,
 又怎么能继续从高优先级任务私栈中弹出其余的BX、DX、CX、AX寄存器呢?  

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2009-4-13 09:14:24 | 显示全部楼层

(原文件名:未命名.JPG)

出0入0汤圆

 楼主| 发表于 2009-4-13 10:42:41 | 显示全部楼层
我先自己分析一下详细过程:假定高优先级任务为任务A


  (1)、当高优先级任务A正在运行时,此时由于“中断服务程序”或者“等待信号量”或者“时钟节拍”或者调用“延时函数”,使任务A挂起,进行任务切换,此时堆栈示意图如下:

           任务A的私栈   
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |   <--------- SP
   -----------------------------------
        图1

 (2)、执行OS_TASK_SW(),也就是说执行了一条软件中断指令(INT80H)
     ,此时任务A堆栈示意图如下:

           任务A的私栈   
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |      OFF task A (断点位置)      |  <--------- SP
   -----------------------------------
      |      SEG task A(断点位置)     |
   -----------------------------------
      |       PSW                       |   
   -----------------------------------
        图2

  (3)、进入OSCtxSW()函数后,执行PUSHA/PUSH ES/PUSH DS

           任务A的私栈   
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |      BX                         |  <-------------- SP
   -----------------------------------
      |      DX                         |
   -----------------------------------
      |      CX                         |
   -----------------------------------
      |      AX                         |
   -----------------------------------
      |      OFF task A (断点位置)      |
   -----------------------------------
      |      SEG task A(断点位置)     |
   -----------------------------------
      |       PSW                       |   
   -----------------------------------
        图3

(4)当执行PUSH SP时,把此时堆栈指针SP的位置记录下来,堆栈中记录的是SP_BX(此时SP指向BX存储单元)


           任务A的私栈   
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |                                 |
   -----------------------------------
      |      SP = SP_BX                 |  <-------------- SP
   -----------------------------------
      |      BX                         |  <-------------- SP_BX
   -----------------------------------
      |      DX                         |
   -----------------------------------
      |      CX                         |
   -----------------------------------
      |      AX                         |
   -----------------------------------
      |      OFF task A (断点位置)      |
   -----------------------------------
      |      SEG task A(断点位置)     |
   -----------------------------------
      |       PSW                       |   
   -----------------------------------
        图4

  (5)继续执行PUSHA/PUSH ES/PUSH DS

            任务A的私栈   
   -----------------------------------
      |      DS                         |  <-------------- SP
   -----------------------------------
      |      ES                         |
   -----------------------------------
      |      DI                         |
   -----------------------------------
      |      SI                         |
   -----------------------------------
      |      BP                         |
   -----------------------------------
      |      SP = SP_BX                 |  
   -----------------------------------
      |      BX                         |  <-------------- SP_BX
   -----------------------------------
      |      DX                         |
   -----------------------------------
      |      CX                         |
   -----------------------------------
      |      AX                         |
   -----------------------------------
      |      OFF task A (断点位置)      |
   -----------------------------------
      |      SEG task A(断点位置)     |
   -----------------------------------
      |       PSW                       |   
   -----------------------------------
        图5

  (6)、执行 LES    BX, DWORD PTR DS:_OSTCBCur      ; OSTCBCur->OSTCBStkPtr = SS:SP
            MOV    ES:[BX+2], SS                   ;
            MOV    ES:[BX+0], SP                   ;
      将堆栈指针位置SP(见上图5中的SP)保存到任务A的任务控制块OS_TCB的OSTCBStkPtr成员中。


(7)当任务A再次得到CPU的控制权后,进入OSCtxSW()函数,执行
            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       ;
;
            MOV    AL, BYTE PTR DS:_OSPrioHighRdy  ; OSPrioCur = OSPrioHighRdy
            MOV    BYTE PTR DS:_OSPrioCur, AL      ;
;
            LES    BX, DWORD PTR DS:_OSTCBHighRdy  ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
            MOV    SS, ES:[BX+2]                   ;
            MOV    SP, ES:[BX]               
       将任务A的私栈的堆栈指针从任务A的任务控制块OS_TCB的在成员OSTCBStkPtr中取出来,指针位置SP参见图5中的SP。

出0入0汤圆

 楼主| 发表于 2009-4-13 10:48:47 | 显示全部楼层
任务A的私栈   
   -----------------------------------
      |      DS                         |  <-------------- SP
   -----------------------------------
      |      ES                         |
   -----------------------------------
      |      DI                         |
   -----------------------------------
      |      SI                         |
   -----------------------------------
      |      BP                         |
   -----------------------------------
      |      SP = SP_BX                 |   
   -----------------------------------
      |      BX                         |  <-------------- SP_BX
   -----------------------------------
      |      DX                         |
   -----------------------------------
      |      CX                         |
   -----------------------------------
      |      AX                         |
   -----------------------------------
      |      OFF task A (断点位置)      |  
   -----------------------------------
      |      SEG task A(断点位置)     |
   -----------------------------------
      |       PSW                       |   
   -----------------------------------
        图6 当任务A再次获得CPU ,执行
          LES    BX, DWORD PTR DS:_OSTCBHighRdy  ; SS:SP = OSTCBHighRdy->OSTCBStkPtr  
                MOV    SS, ES:[BX+2]                   ;  
                MOV    SP, ES:[BX]           
         从高优先级任务控制块OSTCBHighRdy的OSTCBStkPtr成员中取出任务A私栈的堆栈指针,见图6中的SP


(原文件名:未命名1.JPG)

出0入0汤圆

 楼主| 发表于 2009-4-13 10:53:26 | 显示全部楼层
(8)依次执行POP DS/POP ES/POPA,从任务A的私栈中恢复相关寄存器的内容到CPU的相关寄存器中。
   当执行完(POPA)的POP BP时的堆栈示意图如下:

          任务A的私栈     
   -----------------------------------  
      |                                 |  
   -----------------------------------  
      |                                 |  
   -----------------------------------  
      |                                 |  
   -----------------------------------  
      |                                 |  
   -----------------------------------  
      |                                 |  
   -----------------------------------  
      |      SP = SP_BX                 |    <-------------- SP  
   -----------------------------------  
      |      BX                         |
   -----------------------------------  
      |      DX                         |  
   -----------------------------------  
      |      CX                         |  
   -----------------------------------  
      |      AX                         |  
   -----------------------------------  
      |      OFF task A (断点位置)      |   
   -----------------------------------  
      |      SEG task A(断点位置)     |  
   -----------------------------------  
      |       PSW                       |     
   -----------------------------------

出0入0汤圆

 楼主| 发表于 2009-4-13 10:57:42 | 显示全部楼层
(9)由于任务A的私栈中,堆栈指针SP指向单元的内容(SP=SP_BX)为BX存储单元,因此执行POP SP后,堆栈指针位置如下:

        任务A的私栈      
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                            |   
   -----------------------------------   
      |      BX                         |  <-------------- SP   
   -----------------------------------   
      |      DX                         |   
   -----------------------------------   
      |      CX                         |   
   -----------------------------------   
      |      AX                         |   
   -----------------------------------   
      |      OFF task A (断点位置)      |   
   -----------------------------------   
      |      SEG task A(断点位置)     |   
   -----------------------------------   
      |       PSW                       |      
   -----------------------------------   


(10)继续执行完POPA指令其余的弹栈指令后,堆栈指针位置如下:

        任务A的私栈      
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                            |   
   -----------------------------------   
      |                                 |  
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |      OFF task A (断点位置)      |    <-------------- SP   
   -----------------------------------   
      |      SEG task A(断点位置)     |   
   -----------------------------------   
      |       PSW                       |      
   -----------------------------------

出0入0汤圆

 楼主| 发表于 2009-4-13 11:03:25 | 显示全部楼层
(11)执行IRET中断返回指令,依次从任务A的私栈中弹出:
   (a)、任务A上次断点地址的偏移地址到IP寄存器
   (b)、任务A上次断点地址的段移地址到CS寄存器
   (c)、程序状态字PSW(中断是开放的)
      然后跳转到CS:IP位置处(上次断点位置)继续执行任务A的代码。

        任务A的私栈      
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                            |     
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                                 |   
   -----------------------------------   
      |                               |   
   -----------------------------------   
      |                     |   
   -----------------------------------   
      |                                 |    <-------------- SP        
   -----------------------------------

出0入0汤圆

 楼主| 发表于 2009-4-14 08:52:47 | 显示全部楼层
没有人吗?

出0入0汤圆

 楼主| 发表于 2009-4-15 16:06:56 | 显示全部楼层
我顶!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-20 18:42

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表