C语言 将指针的地址加载到寄存器内联thumb程序集中

t1qtbnec  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(140)

我尝试使用内联thumb汇编从我的c指针读取寄存器的地址。
这里有一个可复制:

  1. static uint32_t volatile * volatile CurrentTaskStackPtr;
  2. CurrentTaskStackPtr = (uint32_t *) 0x20000001;
  3. __asm volatile("LDR R8, =%0" : : "i"(CurrentTaskStackPtr) );

此外,我试图避免改变任何“上下文”寄存器的状态,这就是为什么我使用立即读取。
我不断得到这个错误:

  1. warning: 'asm' operand 0 probably does not match constraints
  2. 187 | __asm volatile("LDR R8, =%0" : : "i"(CurrentTaskStackPtr) );

我已经尝试使用不同的约束字符,但我不熟悉的汇编取得任何进展,任何帮助将不胜感激。
谢谢.

vsikbqxv

vsikbqxv1#

"i"(CurrentTaskStackPtr)请求C变量的 value 作为立即数。只有当C变量是编译时常量时才能工作,如uint32_t *const CurrentTaskStackPtr = ...。但是你的变量是volatile(与指向volatile分开),所以即使启用了优化,你也禁止编译器通过赋值进行常量传播来生成"i"(0x20000001)

如果您想要地址,请使用地址"i"(&CurrentTaskStackPtr)

或者更好的方法是,让编译器在R8中为您提供地址,而不是将ldr伪指令放入asm模板中,除非您需要控制它如何实现地址或其他内容。

  1. register void *tmp_r8 asm("r8"); // forces "r" constraints to pick R8.
  2. tmp_r8 = &CurrentTaskStackPtr;
  3. asm("..."
  4. : // outputs
  5. : "r"(tmp_r8)
  6. : "memory" // presumably you're going to deref that pointer
  7. );

另请参阅https://stackoverflow.com/tags/inline-assembly/info和ARM内联asm:exit system call with value read from memory for an example of how this compiles.
GCC手册(https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html)明确指出,寄存器asm局部变量的 * 唯一 * 保证行为是为内联asm语句选择指定的寄存器;它 * 不 * 保证在任何其他时间使用该寄存器。
另请参阅How can I indicate that the memory pointed to by an inline ASM argument may be used?了解更多关于为什么"memory" clobber是必要的。可能最好使用它来代替虚拟输入/输出操作数;你也不希望编译器试图围绕上下文切换进行优化。
尝试进行上下文切换
您可能更适合将上下文切换函数编写为__attribute__((naked)),这样就不必担心编译器何时访问相对于堆栈指针的局部变量。官方不支持在asm语句中更改堆栈指针。(https:gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#index-asm-clobbers-clobber列表不应包含堆栈指针。)
除了在naked函数中,你在Basic Asm语句中编写整个函数的asm,它不能内联到任何调用者中,因为它就像__attribute__((noinline,noipa)),或者像在单独的.s文件中编写它,只是定义一个原型。

展开查看全部

相关问题