如何理解这个嵌入式汇编代码?

时间:2014-03-07 22:30:09

标签: assembly arm cortex-m3

#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) \

3 个答案:

答案 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。