C51恢复功能实际上是如何工作的?
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的调用,首先分配模拟堆栈空间这种机制。
process P1调用一些重新输入函数,它首先调用c?addxbp,p1-c?addxbp的返回地址被推到硬件堆栈上。
假设p1-c?addxbp没有达到禁用中断的代码,并且发生了上下文开关,现在Process P2正在运行。
Process P2还想调用一些重新输入函数,并调用c?addxbp,p2-c?addxbp的返回地址。
假设上下文在p2-c?addxbp pack disction intrupts之前再次切换到p1
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.
Process P1 calls some reentrant function, it first calls C?ADDXBP, return address of P1-C?ADDXBP is pushed onto hardware stack.
assume that P1-C?ADDXBP didn't reach the code where it disables interrupts, and a context switch happens, now Process P2 is running.
Process P2 also wants to call some reentrant function and calls C?ADDXBP, return address of P2-C?ADDXBP is pushed onto hardware stack.
assume that context switched to P1 again, before P2-C?ADDXBP disables interrupts
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论