我试图让内联汇编程序将一些值复制到特定的寄存器中,但它只是抱怨。这是将触发错误的代码的简短版本:
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
。
有了GCC,有一条捷径:
register long r0 asm ("r0");
然后r0
“别名”注册。
将它与statement expression相结合,你甚至可以将r0
作为“返回值”。
#define SYSCALL1(NUMBER,A) ({\
register long r0 asm("r0") = (long) (A); \
asm("swi #" STRINGIFY(NUMBER) : "=r"(r0) : "r"(r0) : "memory"); \
r0; })
(我不知道clobber是否合法,但uClibc系统调用实现有这个。)