"i"(CurrentTaskStackPtr)
要求将C变量的value作为立即数.只有当C变量是编译时常量(如uint32_t *const CurrentTaskStackPtr = ...
)时,这才能起作用.但是您的变量是volatile
(不同于指向volatile
),所以即使启用了优化,您也禁止编译器通过赋值进行常量传播来生成"i"(0x20000001)
.
If you want the address, take the address, 100.
或者更好的做法是,让编译器为您提供R8中的地址,而不是将ldr
伪指令放入ASM模板中,除非您需要控制它如何实现地址或其他什么.
register void *tmp_r8 asm("r8"); // forces "r" constraints to pick R8.
tmp_r8 = &CurrentTaskStackPtr;
asm("..."
: // outputs
: "r"(tmp_r8)
: "memory" // presumably you're going to deref that pointer
);
另请参见https://stackoverflow.com/tags/inline-assembly/info和ARM inline asm: exit system call with value read from memory以获取如何编译的示例.
GCC手册(https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html)明确指出,寄存器ASM局部变量的only保证行为是为内联asm
语句挑选指定的寄存器;not保证在任何其他时间使用该寄存器.
另请参见How can I indicate that the memory *pointed* to by an inline ASM argument may be used?,以了解为什么需要"memory"
撞击机.也许最好使用它而不是伪输入/输出操作数;无论如何,您都不希望编译器试图围绕上下文切换进行优化.
正在try 进行上下文切换
您可能更适合将上下文切换函数编写为__attribute__((naked))
,因此您不必担心编译器何时访问相对于堆栈指针的本地变量.官方不支持更改asm
语句内的堆栈指针.(https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#index-asm-clobbers-拦截器列表不应包含堆栈指针.)
除了在naked
函数中,您在一个基本的ASM语句中编写整个函数的ASM,它不能内联到任何调用方,因为它类似于__attribute__((noinline,noipa))
,或者像是在单独的.s
文件中编写它并只是定义一个原型.