代码之家  ›  专栏  ›  技术社区  ›  Bob

内裸函数-如何做简单的赋值

  •  0
  • Bob  · 技术社区  · 6 年前

    这是一个已经存在并可以工作的函数的开头;注释行是我添加的,其目的是切换一个pin。

    inline __attribute__((naked)) 
    void CScheduler::SwapToThread(void* pNew, void* pPrev)
    {   
        //*(volatile DWORD*)0x400FF08C = (1 << 14);
        if (pPrev != NULL)
        {
            if (pPrev == this) // Special case to save scheduler stack on startup
            {
                asm("mov lr,%0"::"p"(&CScheduler_Run_Exit));     // load r1 with schedulers End thread
                asm("orr lr, 1");
    

    当我取消添加的注释时,将执行硬错误处理程序。我知道这和 naked 函数,但我不明白为什么简单的赋值会导致问题。

    两个问题:

    1. 为什么这条线会触发硬故障?
    2. 如何在此函数内执行此分配?
    1 回复  |  直到 6 年前
        1
  •  3
  •   Peter Cordes    6 年前

    幸运的是,您以前版本的函数运行时没有崩溃。

    唯一可以安全放入 naked 函数是一个纯粹的基本asm语句。 https://gcc.gnu.org/onlinedocs/gcc/ARM-Function-Attributes.html . 您可以将其拆分为多个基本ASM语句,而不是 asm("insn \n\t" / "insn2 \n\t" / ...); 但是您必须自己用asm编写整个函数。

    虽然使用扩展的ASM或基本ASM和C代码的混合可能看起来可以工作,但它们不能可靠地工作,也不受支持。

    如果您想从裸函数运行C++代码,您可以 call 常规功能(或 bl 在手臂上, jal 在MIP等上),遵循标准呼叫约定。


    这件事的具体原因是什么?也许在寄存器中创建该地址会导致函数args出错?如果需要,请检查生成的ASM,但它100%不受支持。

    或者它最终使用了更多的寄存器, 裸体的 没有正确保存/恢复呼叫保留寄存器?我还没有亲自研究过裸函数的代码生成。

    你确定这个功能需要 裸体的 ?我想那是因为你操纵 lr 返回到新上下文。

    如果您不想在asm中编写更多的逻辑,可以让这个函数的调用者做更多的工作(并且可能传递指针和/或布尔参数,更简单地告诉它它需要做什么,所以您的输入已经在寄存器中,您不需要访问全局变量)。