#define SVC_ARG2(call, arg1, arg2) ({ \
uint32_t ret = 0; \
asm volatile ("mov r0, %[ar1] \n" \
"mov r1, %[ar2] \n" \
"svc %[code] \n" \
"mov %[ret], r0 \n" \
:[ret] "+r" (ret) \
:[code] "I" (call), [ar1] "r" (arg1), [ar2] "r" (arg2) \
:"r0", "r1"); \
ret; \
})
我无法理解
"mov %[ret], r0 \n" \
:[ret] "+r" (ret) \
:[code] "I" (call), [ar1] "r" (arg1), [ar2] "r" (arg2) \
:"r0", "r1");
这部分代码。特别是:
[ret] "+r" (ret) \
答案 0 :(得分:3)
这是gcc内联汇编语法。最后3行分别列出了输出,输入和clobbers。对于输出和输入,方括号中的部分是一个符号名称,可用于引用asm块内的特定参数。引号中的部分是约束,告诉编译器它是什么类型的参数:r
表示注册,I
表示立即。 +
修饰符通常告诉编译器该参数是读写的,所以我没有注意到为返回值指定该参数。最后,圆括号中的部分是参数的值。因此[ret] "+r" (ret)
定义了一个名为[ret]
的输出参数,该参数将位于寄存器中,并应分配给变量ret
。
答案 1 :(得分:1)
#define SVC_ARG2(call, arg1, arg2) ({ \
定义此宏“功能”。
uint32_t ret = 0; \
设置ret = 0,因此它存在于堆栈中。
asm volatile ("mov r0, %[ar1] \n" \
将ar ar1移入寄存器0
"mov r1, %[ar2] \n" \
将寄存器1移入
"svc %[code] \n" \
主管电话通过了电话。
"mov %[ret], r0 \n" \
将r0的内容移动到%[ret](后面我们看到的是在asm调用之上定义的ret int。
:[ret] "+r" (ret) \
%[ret]是包含ret值的通用寄存器,ret作为输入/输出值传入。
:[code] "I" (call), [ar1] "r" (arg1), [ar2] "r" (arg2) \
[code]扩展为代码片段,它作为调用传递给函数,带有两个参数,即通用寄存器,我们传递ar1(持有arg1)和ar2(持有arg2)作为参数。
:"r0", "r1"); \
注册0并注册1
ret; \
“返回”ret
})
关闭定义。
“r”表示通用寄存器 “+”表示输入/输出变量(sorta类似于通过引用传递) “I”是特定于机器的,但鉴于上下文看起来是一段可调用的代码,它返回一个int。
以格式串在一起: :[thing_to_replace]“如何传递东西”(thing_to_pass)
Sorta就像旧的printf替换,或sql准备语句中的替换。
答案 2 :(得分:0)
http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
代码将arg1加载到r0,将arg2加载到r1,然后调用“svc call”,其中call是SVC编号。然后它将寄存器r0的值(由于svc指令而设置)移入C变量ret。