C51恢复功能实际上是如何工作的?

发布于 2025-02-12 08:29:39 字数 2069 浏览 1 评论 0原文

C51编译器生成以下子程序以操纵模拟堆栈指针:

                    C?ADDXBP:
        C:0x000F    E509     MOV      A,0x09
        C:0x0011    2582     ADD      A,DPL(0x82)
        C:0x0013    F582     MOV      DPL(0x82),A
        C:0x0015    E508     MOV      A,0x08
        C:0x0017    3583     ADDC     A,DPH(0x83)
        C:0x0019    F583     MOV      DPH(0x83),A
        C:0x001B    B50804   CJNE     A,0x08,C:0022
        C:0x001E    858209   MOV      0x09,DPL(0x82)
        C:0x0021    22       RET      
        C:0x0022    10AF06   JBC      EA(0xA8.7),C:002B
        C:0x0025    858209   MOV      0x09,DPL(0x82)
        C:0x0028    F508     MOV      0x08,A
        C:0x002A    22       RET      
        C:0x002B    858209   MOV      0x09,DPL(0x82)
        C:0x002E    F508     MOV      0x08,A
        C:0x0030    D2AF     SETB     EA(0xA8.7)
        C:0x0032    22       RET      

我知道这意味着这一点:

        C?ADDXBP: (add DPTR to XBP)
        {
            DPTR = DPTR + XBP    (temporarily store new XBP)                                
            if (only the low byte is changed)
            {
                XBPL = DPL
                return
            }
            else (both bytes changes, the write action has to be done atomically)
            {
                EA = 0
                XBPL= DPL
                XBPH= DPH

                EA = 1, if EA previously was 1.
                return
            }
        }

当呼叫重新进入函数时,C51会引起对C?addxbp的调用,首先分配模拟堆栈空间这种机制。

  1. process P1调用一些重新输入函数,它首先调用c?addxbp,p1-c?addxbp的返回地址被推到硬件堆栈上。

  2. 假设p1-c?addxbp没有达到禁用中断的代码,并且发生了上下文开关,现在Process P2正在运行。

  3. Process P2还想调用一些重新输入函数,并调用c?addxbp,p2-c?addxbp的返回地址。

  4. 假设上下文在p2-c?addxbp pack disction intrupts之前再次切换到p1

  5. p1-c?addxbp简历并一直运行到ret,并试图返回到p2-c?addxbp应该返回的位置,那是错误。

CX51文档说:“可以递归地调用重进入功能,并且可以通过两个或多个过程同时调用。在实时应用程序或中断代码和非中断代码必须共享功能的情况下,经常需要重新进入功能。”根据我的分析,它行不通。

我认为可能有一些我缺少的东西,或者C51可能会做更多的事情,并生成更多的代码来解决我发现的问题。这真的让我感到困惑。

C51 compiler generates following subroutine for manipulating the simulated stack pointer:

                    C?ADDXBP:
        C:0x000F    E509     MOV      A,0x09
        C:0x0011    2582     ADD      A,DPL(0x82)
        C:0x0013    F582     MOV      DPL(0x82),A
        C:0x0015    E508     MOV      A,0x08
        C:0x0017    3583     ADDC     A,DPH(0x83)
        C:0x0019    F583     MOV      DPH(0x83),A
        C:0x001B    B50804   CJNE     A,0x08,C:0022
        C:0x001E    858209   MOV      0x09,DPL(0x82)
        C:0x0021    22       RET      
        C:0x0022    10AF06   JBC      EA(0xA8.7),C:002B
        C:0x0025    858209   MOV      0x09,DPL(0x82)
        C:0x0028    F508     MOV      0x08,A
        C:0x002A    22       RET      
        C:0x002B    858209   MOV      0x09,DPL(0x82)
        C:0x002E    F508     MOV      0x08,A
        C:0x0030    D2AF     SETB     EA(0xA8.7)
        C:0x0032    22       RET      

I know it means this:

        C?ADDXBP: (add DPTR to XBP)
        {
            DPTR = DPTR + XBP    (temporarily store new XBP)                                
            if (only the low byte is changed)
            {
                XBPL = DPL
                return
            }
            else (both bytes changes, the write action has to be done atomically)
            {
                EA = 0
                XBPL= DPL
                XBPH= DPH

                EA = 1, if EA previously was 1.
                return
            }
        }

When a call to reentrant function happens, C51 generates a call to C?ADDXBP first to allocate simulated stack space, but we can simply construct a situation that breaks this mechanism.

  1. Process P1 calls some reentrant function, it first calls C?ADDXBP, return address of P1-C?ADDXBP is pushed onto hardware stack.

  2. assume that P1-C?ADDXBP didn't reach the code where it disables interrupts, and a context switch happens, now Process P2 is running.

  3. Process P2 also wants to call some reentrant function and calls C?ADDXBP, return address of P2-C?ADDXBP is pushed onto hardware stack.

  4. assume that context switched to P1 again, before P2-C?ADDXBP disables interrupts

  5. P1-C?ADDXBP resumes and run all the way to RET, and tries to return to where P2-C?ADDXBP should return to, and that's an error.

Cx51 documentation says "Reentrant functions can be called recursively and can be called simultaneously by two or more processes. Reentrant functions are often required in real-time applications or in situations where interrupt code and non-interrupt code must share a function.", but according to my analysis it doesn't work.

I think there might be something I'm missing, or maybe C51 will do more than that and generate more code to solve the problem I found. It really confused me a lot.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文