如何在ARM内联汇编中使用特定寄存器

4
我正在尝试让内联汇编将一些值复制到特定的寄存器中,但它只会报错。以下是触发错误的简短代码版本:
asm("" :: "r0" (value));
asm("" :: "a1" (value));

两行都会触发:

Error: matching constraint references invalid operand number

那么我如何直接指定寄存器呢? 我知道可以为值引入名称,然后自己复制它们,但我想避免这种情况,因为这会让代码更短,更易读。 我为什么要问 目前我正在处理一些系统调用。我想使用这样的系统调用宏:
#define SYSCALL0(NUMBER) asm("swi #" STRINGIFY(NUMBER));
#define SYSCALL1(NUMBER, A) asm("swi #" STRINGIFY(NUMBER) :: "r0"(A));
#define SYSCALL2(NUMBER, A, B) asm("swi #" STRINGIFY(NUMBER) :: "r0"(A), "r1"(B));
...

你可以看到,这个很好地适配在同一行上。 当然,我也可以做一些类似于:

#define SYSCALL1(NUMBER, A) register type R0 asm("r0") = A;
                            SYSCALL0(NUMBER)

但是这样我就必须将A转换为type,以避免类型错误,或者在每次在不同的函数中使用宏时正确地给出type


1个回答

2
使用GCC,有一个快捷方式:
register long r0 asm ("r0");

然后,r0 “别名”了该寄存器。
再与语句表达式结合使用,甚至可以将r0作为“返回值”。
#define SYSCALL1(NUMBER,A) ({\
  register long r0 asm("r0") = (long) (A); \
  asm("swi #" STRINGIFY(NUMBER) : "=r"(r0) : "r"(r0) : "memory"); \
  r0; })

“我不知道这个clobber是合法的还是不合法的,但uClibc系统调用实现中有它。”
“请参见扩展汇编本地寄存器变量。”

是的,我知道那个,但我不喜欢那么长的语法。我会更新我的问题以展示我的动机。 - Nobody moving away from SE
寄存器是这种类型,但输入的变量可以具有任意类型(例如int、char、void(fn)(void)等),因此我每次都必须进行转换。虽然这并非不可能,但确实很丑陋。 - Nobody moving away from SE
如果你真的想要这样做,可以在宏中进行转换。已更新。 - Mat
你也可以使用静态内联函数将参数放入正确的寄存器中。 - R.. GitHub STOP HELPING ICE
在这种情况下,内联函数相对于宏的优势(类型安全性)是过度的。我需要消除类型,因此使用内联函数将导致我必须编写更多的强制转换。 - Nobody moving away from SE
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接