我有以下函数可以进行主管调用。
inline uint32_t os_SVC(uint32_t n, uint32_t pid, void* ptr1, void (*ptr2)()){
__asm("svc #0");
return;
}
通过在 SVC ISR 期间更改堆栈,我知道 R0 将包含来自 SVC ISR 的返回参数。据我了解,这就是 AAPCS 从函数返回值的方式。但是如何从 os_SVC 返回 R0 寄存器呢?目前它给了我一个警告,因为我从函数返回时没有提供返回值。
最佳答案
您的编译器可能有进一步的扩展,允许您将数据传入和传出程序集插入。您没有告诉我们您正在使用哪个编译器,因此我将向您展示如何使用 GCC 来完成此操作,我无需查找即可记住它的扩展名:
uint32_t os_SVC(uint32_t n, uint32_t pid, void *p1, void (*p2)(void))
{
register uint32_t rv asm ("r0");
asm ("svc #0" : "=r" (rv))
return rv;
}
rv
声明上的register ... asm("r0")
注解要求编译器将其放入r0中,: "=r"(rv)
asm 语句上的注释告诉它汇编指令写入该变量。然后你可以正常返回rv
。
另外,请注意我是如何删除内联
的?那是故意的。如果您内联此函数,参数将不会整齐地排列在系统调用期望找到它们的堆栈上。如果您的操作系统期望寄存器中的系统调用参数,您可以进一步注释程序集插入并进行内联工作,但如果它期望它们在堆栈上,则最好的方法是让函数处于外联状态。 (在生产代码中,我会将 __attribute__((noinline))
放在函数本身上,并将 __attribute__((used))
放在它的每个参数上,但这太多了以困惑为例。)
我正在使用的扩展的文档位于 "Using Assembly Language with C" GCC 手册的部分。仔细阅读整篇文章。
如果您没有使用 GCC,请查阅编译器手册以查看它是否具有等效扩展。如果它没有等效的扩展名,您唯一的选择可能是完全用汇编语言在单独的 .S
文件中编写此函数。
关于C:返回通用寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57327039/