【问题标题】:ARM syscall as c++ templateARM 系统调用作为 c++ 模板
【发布时间】:2014-05-02 08:11:49
【问题描述】:

我需要在我的 newlib 存根中调用一些系统调用,而当前的实现使用 C 宏,随着时间的推移,这些宏变得不可读且看起来很糟糕。 (而且我讨厌宏……) 但是,我使用 C++ 模板的实现只适用于一个参数:

template <int nr, typename RETTYPE, typename PARAM1> 
    inline RETTYPE syscall(PARAM1 p1)
{
  register PARAM1 r0 asm("r0") = p1;
  asm volatile("svc %[nr]\n"
    : "=r" (r0)
    : [nr] "i" (nr), "r" (r0)
    : "memory", "r1", "r2", "r3", "r12", "lr");
  return (RETTYPE) r0;
}

现在我可以打电话给例如使用 malloc

void *ptr = syscall<SYS_MALLOC, void*>(0x1000);

分配 0x1000 字节。

我对四个参数的实现:

template <int nr, typename RETTYPE, typename PARAM1, typename PARAM2, typename PARAM3, typename PARAM4> 
    inline RETTYPE syscall(PARAM1 p1, PARAM2 p2, PARAM3 p3, PARAM4 p4)
{
  register PARAM1 r0 asm("r0") = p1;
  register PARAM2 r1 asm("r1") = p2;
  register PARAM3 r2 asm("r2") = p3;
  register PARAM4 r3 asm("r3") = p4;

  asm volatile("svc %[nr]\n"
    : "=r" (r0)
    : [nr] "i" (nr), "r" (r0), "r" (r1), "r" (r2), "r" (r3)
    : "memory", "r12", "lr");

  return (RETTYPE) r0;
}

不起作用,“swi”指令的寄存器内容是任意的。 不知何故,GCC 不再尊重“注册”变量。 示例:我在svc指令处设置断点并执行

syscall<FWRITE, int>(ptr, 1, len, f)

但不知何故 r0 设置为 1 和 r1 设置为 ptr... 我也尝试过不优化编译,只是寄存器的顺序发生了一点变化,但仍然是错误的顺序。我知道我可以执行 "mov r0, %[param1]" 等,但这会妨碍优化,因此会导致代码变慢。

这是 GCC (4.8.2) 中的错误还是我忽略了什么?

【问题讨论】:

  • 这看起来很笨拙:-/ ...我会避免在 C++ 代码中使用 asm 来做任何努力!!
  • 另请注意,register 关键字已经被弃用了一段时间...
  • 相信我,如果可以的话,我会的 ;-)
  • 你可以通过在第二个例子中设置相同的clobbers来得到你想要的,但是仅仅通过阅读代码并不清楚你想要做什么。
  • 它是 ndless/TI-Nspire/Nucleus RTOS。如果我将参数添加为clobbers,您能解释一下为什么它应该起作用吗?我已经尝试过了,但它没有用。不过,我会再试一次。

标签: c++ templates arm inline-assembly system-calls


【解决方案1】:

这是bug 33661,相当旧。几年前我自己也遇到过。

【讨论】:

  • 并非每天我都单击随机 SO 链接并最终阅读有关支持内联汇编的编译器错误...向您致敬,先生。
  • 太棒了 :-( 在模板中内联全局非模板函数的解决方法有效。它很丑,但有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-09
  • 2020-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-25
  • 2020-03-13
相关资源
最近更新 更多