内联汇编:约束修饰符的说明

时间:2016-11-16 17:17:51

标签: c assembly arm constraints inline-assembly

两个问题:

(1)如果我正确理解ARM内联汇编,则“r”的约束表明指令操作数只能是核心寄存器,默认情况下是只读操作数。但是,我注意到如果相同的指令具有带有约束“= r”的输出操作数,则编译器可以重用相同的寄存器。这似乎违反了“只读”属性。所以我的问题是:“只读”是指寄存器,还是它所连接的C变量?

(2)说出“&”的存在是否正确在“=& r”的约束下,只需要为输出操作数选择的寄存器不能与输入操作数寄存器之一相同?我的问题涉及下面用于计算整数幂函数的代码:即,“&”约束修饰符必要/适当吗?

asm (
"    MOV   %[power],1                \n\t"
"loop%=:                             \n\t"
"    CBZ   %[exp],done%=             \n\t"
"    LSRS  %[exp],%[exp],1           \n\t"
"    IT    CS                        \n\t"
"    MULCS %[power],%[power],%[base] \n\t"
"    MUL   %[base],%[base],%[base]   \n\t"
"    B     loop%=                    \n\t"
"done%=:                                 "
: [power] "+&r" (power)
  [base]  "+&r" (base)
  [exp]   "+&r" (exp)
:
: "cc"
) ;

谢谢! 丹

1 个答案:

答案 0 :(得分:2)

只读是指在汇编代码中使用操作数。汇编代码只能从操作数读取,并且必须在写入任何正常输出操作数(不是早期的clobber或读/写操作数)之前执行此操作。这是因为,正如您所见,可以将相同的寄存器分配给输入和输出操作数。假设输入在写入任何输出之前被完全消耗,这通常是汇编指令的情况。

我不认为使用带有读/写修饰符&的早期修饰符+会产生任何影响,因为分配给读/写操作数的寄存器不能用于任何事情其他

以下是我编写代码的方法:

unsigned power = 1;
asm (
    "    CBZ   %[exp],done%=             \n\t"
    "loop%=:                             \n\t"
    "    LSRS  %[exp],%[exp],1           \n\t"
    "    IT    CS                        \n\t"
    "    MULCS %[power],%[power],%[base] \n\t"
    "    MUL   %[base],%[base],%[base]   \n\t"
    "    BNE   loop%=                    \n\t"
    "done%=:                                 "
    : [power] "+r" (power),
      [base]  "+r" (base),
      [exp]   "+r" (exp)
    :
    : "cc"
    ) ;

注意将循环测试放在循环结束时的转换,保存一条指令。没有它,代码对编译器可以生成的内容没有任何明显的改进。我还让编译器对用于power操作数的寄存器进行初始化。它有可能分配一个已经有值为1的寄存器。