2011-08-26 84 views
2

我尝试使用下面的宏:宏汇编联错误

#define M_MA(out, L_v, var1, var2)({ \ 
    asm volatile( \ 
    "movswl %2, %%edi\n\t" \ 
    "movswl %3, %%ebx\n\t" \ 
    "imull %%edi, %%ebx\n\t" \ 
    "sall $1,%%ebx\n\t" \ 
    "cmpl %4,%%ebx\n\t" \ 
    "cmove %5,%%ebx\n\t" \ 
    "addl %1, %%ebx\n\t" \ 
    "jno out%=\n\t" \ 
    "cmovg %5, %%ebx\n\t" \ 
    "cmovl %4, %%ebx\n\t" \ 
    "out%=: nop\n\t" \ 
    "movl %%ebx, %0\n\t" : "=r"(out) : "r"(L_v), "m"(var1), "m"(var2), "r"(-2147483648), "r"(+2147483647) : "%ebx","%edi"); }) 

当使用优化编译我得到一个文件中使用:

error: ‘asm’ operand has impossible constraints 

VAR1VAR2是16位字。 L_V都是32个字。

一些阅读后,我认为这个问题是,编译器需要比可用的更多的寄存器,但我不知道这件事。如果这是问题,我不知道如何使用比现在少的寄存器或如何修补错误。

我在32位平台上使用gcc而不是Linux。

任何人都可以澄清一些事?

问候

+1

有为什么要加载'%ebx'与'var1'和'var2'手动'%edi'什么特别的原因?不会删除'movswl'指令+ clobber列表并将约束更改为'[...]“D”((int32_t)var1),“b”((int32_t)var2)'工作吗? – user786653

+1

为什么'out'和'L_v'需要在寄存器中,并且'var1'和'var2'在内存中?如果没关系,可以使用'“r,m”'的限制来允许内存或寄存器。 (甚至更好的做法是使用''g''作为'L_v',因为它也可以是一个立即值。) – ughoavgfhw

回答

3

“我不知道怎么用更少的寄存器比现在” - 怎么样使用的立即,而不是寄存器的两个MAXINT /内政部常数? (啊,cmov不需要立即数,但是你可以自己存储常量到%edi,而不需要编译器事先在不同的寄存器中设置它)。

而且,你为什么要在%ebx构建的一切,然后在复制到不同的寄存器非常结束?这些操作都不是%ebx具有特殊含义的操作,因此只需简单地将%%ebx全部替换为%0并且声明它为"&=r"而不是"=r"将是胜利或至少不是损失。

+0

+1如果OP想要保留它们作为参数,它们是“m”约束的好选择尽管*他们当然需要手动加载到免费注册表中)。 – user786653

+0

我会用“&= r”得到什么? – LooPer

+0

早期的clobber输出寄存器,即保证与任何输入寄存器不同的寄存器。见[这里](http://gcc.gnu.org/onlinedocs/gcc/Modifiers.html)。 –