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

inside naked function - how to do simple assignment

这是一个已经存在并且有效的函数的开始;注释行是我添加的,其目的是切换引脚。

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. 如何在这个函数中执行这个赋值?

幸运的是你以前版本的功能碰巧没有崩溃。

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

While using extended asm or a mixture of basic asm and C code may appear to work, they cannot be depended upon to work reliably and are not supported.

如果您想 运行 来自裸函数的 C++ 代码,您可以 call 常规函数(或者 bl 在 ARM 上,jal 在 MIPS 等.), 遵循标准调用约定。


请问本案的具体原因是什么?也许在寄存器中创建该地址会踩到函数参数,导致分支出错?如果需要,请检查生成的 asm,但它 100% 不受支持。

或者它可能最终使用了更多的寄存器,并且由于它 naked 没有正确地 save/restore 调用保留寄存器?我自己还没有查看代码生成的裸函数。

你确定这个函数需要naked吗?我想那是因为你将 lr 操纵到 return 到新的上下文。

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