2016-11-16 73 views
3

两个问题:内联汇编:澄清约束修饰符

(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" 
) ; 

谢谢! Dan

+1

号, “R” 并不意味着只读的,它只是意味着 “通用寄存器”。您在输入列表中指定的参数是只读的,无论您使用何种约束。 – Jester

+0

查看[this](https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands)了解关于输入参数和[this]的详细信息(https://gcc.gnu.org/onlinedocs/ gcc/Simple-Constraints.html#Simple-Constraints)来获得简单约束的细节(比如''r“')。您可能还想看看[这里](https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html)中关于“ARM系列”特定的约束。 –

回答

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的寄存器。

+0

早期的clobber和读写的结合非常重要,就好像2个输入具有相同的值,它们可以是相同的寄存器。 –

0

感谢大家的澄清。只是为了确定我是否正确,说输出操作数的“= r”和“+ r”之间的选择取决于如何在组件中使用对应的寄存器第一个模板?即,

“= r”:该寄存器的第一次使用是作为指令的只写输出。

该寄存器稍后可能被其他指令重新用作输入或输出。添加一个早期的clobber约束(例如,“= & r”)会阻止编译器分配先前用作输入操作数的寄存器。

“+ r”:寄存器的第一次使用是作为指令的输入,但寄存器稍后再次用作输出。

最佳,

+1

我想我更喜欢“'”= r“(x)':输入到asm时,这个寄存器的内容是未定义的(除非与匹配的输入约束相结合),并且在输出上,寄存器将包含变量'x'和''“+ r”(x)':'x'的现有值作为输入传递,可以通过asm指令进行更新。“和”另请参阅'&'修饰符防止来自共享寄存器的输入和输出限制。“ –

+0

大卫,我很困惑”(除非与一个匹配的输入约束相结合)“。我认为任何被列为输入操作数的东西都被定义为”只读“,因此会与输出操作数列表相同,或者我误解了你的意思? –

+0

正如[here](https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands)所述, ,输入约束可以是数字,所以'asm(“”:“= r”(x):“0”(y));''意味着'y'是一个输入,参数#0。或者换句话说:在输入时,寄存器将包含'y',并在输出中包含'x'。这也意味着'asm(“”:“= r”(x):“0”(x));'是asm(“”:“+ r”(x));'的同义词。 –