C:返回通用寄存器

标签 c arm embedded

我有以下函数可以进行主管调用。

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/

相关文章:

c - 带有 malloc() 错误的二维数组

c - 为什么不增加 z?

c - 为什么在用 gcc 编译后一个值消失了?

iphone - 如何使用 NEON 在 ARM 汇编中实现 16 位->32 位查找表?

c - 链表从闪存过渡到 Ram

c - 这段代码是如何工作的?

c - gcc tracker/make/fork/exec/wait 的问题

assembly - ARM NEON 代码中冒号的含义是什么

c - 有没有办法让我的补充代码更加高效并允许一次多个输出?

linux - 为基于 ARM 的嵌入式 Linux 系统选择紧凑的 c/c++ 编译器