程序可以从主函数返回吗?为什么链接寄存器具有与程序计数器相同的值?

问题描述 投票:0回答:1

update: dnmmanager_getName函数的原型,codo询问。 Screenshot4

char* DNMManager_GetName(DNM_s* element) { //program stops here. //link register : 0x805afed0 //program counter: 0x805cda64 return &element->Name[0]; } DNMManager_GetName(): 805cda64: E24DD008 sub sp, sp, #8 805cda68: E58D0000 str r0, [sp]

我通过使用IDE调试器提供的断点。
在屏幕截图1中,我注意到在函数的输入点冻结程序时,链接寄存器包含0x805DCDA0,这是
main

的地址。

while(1)

不是
函数的呼叫者,而是链接寄存器包含
while(1)
的地址。

为什么?

谁说的?
Screenshot1
main
ScreenShot2下面是一个示例,显示链接寄存器的值已更改为正确的值,在这种情况下,在程序输入函数IntaintCinit()。
Screenshot2

while(1)

秒问题

执行程序,我发现程序计数器的值等于在某些时间点链接寄存器的值。

这让我感到困惑,因为我认为这两个登记册永远都不会具有相同的价值。 下面的screenshot 3是两个寄存器的值相同的情况。
如何发生?在什么情况下?

Screenshot3

int main(void)
{                     //program stops at here. link register: 0x805dcda0

    OS_ERR  err = OS_ERR_NONE;

    IntAINTCInit();   //once program enters this function,
                      //the value of link register is changed
    OS_Init();        //initialize OS
    OSStart(&err);    //start OS

    if (err != OS_ERR_NONE)
    {
        printf("OS fails");
    }
    /*no return statement*/
}


          start_boot():
805dcd94:   E92D4008            push       {r3, lr}
138           CopyVectorTable();
805dcd98:   EB000001            bl         CopyVectorTable
141           main();
805dcd9c:   EB00001D            bl         main
143           while(1);
          $C$L1:
805dcda0:   EAFFFFFE            b          $C$L1

您只显示一些屏幕截图,而不是完整的代码,我只能推测...

Screenshot1:入口点

比Windows或Linux上的MicroController的程序不应从

main()

返回。无处可去。为了防止进一步的损害,

lr

指向无尽的循环。如果您意外地从

main()

.

Screenshot2:intaintcinit()


assembly arm cpu-registers rtos
1个回答
2
投票

Screenshot3:PC =lr

输入函数时,lr

包含返回地址。如果函数调用其他功能,则必须保存

lr(通常在堆栈上)并为其分配一个新值。屏幕截图在语句之后显示状态: OS_Init() 如果您查看汇编代码,则可以看到memset

被调用以初始化40个字节至0。因此,确实调用了另一个函数,并且屏幕截图从

memset返回后立即显示状态。每次函数刚刚返回时,PC

都必须等于

lr

,因为这是返回的工作方式。所以这里一切都还好。

Screenshot4:dnmmanager_getname

输入DNMMANAGER_GEGNAME()时,屏幕截图显示了正确的状态。该功能的呼吁是由该声明进行的: void IntAINTCInit(void) { //program stops here. link register: 0x805dce28 /*pseudo code*/ !!Reset the ARM interrupt controller !!Wait for the reset to complete !!Enable any interrupt generation by setting priority threshold !!Register the default handler for all interrupts } 44 OS_Init(); //initialize OS 805dce28: EBFF30EA bl CPU_Init

通话后的语句(需要返回的地方)为0x805AFED0,Exacytly
lr

在屏幕截图上包含的内容。 注意C代码中的单行会导致两个函数调用,一个函数为DNMMANAGER_GEGNAME(),一条to totomemcpy。 0x805afee4将是第二个功能调用的返回地址。但是屏幕截图4显示了第一个功能调用的状态。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.