'asm'无效:操作数不是条件代码,操作数代码无效'c'

时间:2017-03-13 04:41:59

标签: assembly x86 g++ inline-assembly

我正在尝试从这里https://github.com/Ericson2314/Voxlap在linux上构建Voxlap,当我尝试这样做时,我收到有关内联汇编的错误消息:

source/sdlmain.cpp: In function ‘void fpuinit(long int)’:
source/sdlmain.cpp:1814:3: error: invalid 'asm': operand is not a condition code, invalid operand code 'c'
);
^

source/sdlmain.cpp:1814:3: error: invalid 'asm': operand is not a condition code, invalid operand code 'c'
source/sdlmain.cpp:1814:3: error: invalid 'asm': operand is not a condition code, invalid operand code 'c'
source/sdlmain.cpp:1814:3: error: invalid 'asm': operand is not a condition code, invalid operand code 'c'

违规代码在这里:

static long fpuasm[2];
static inline void fpuinit (long a)
{
    __asm__ __volatile__
    (
        "fninit\n"
        "fstcww %c[fp]\n"
        "andb   $240, %c[fp]+1(,1)\n"
        "orb    %%al, %c[fp]+1(,1)\n"
        "fldcww %c[fp]\n"
        :
        : "a" (a), [fp] "p" (fpuasm)
        : "cc"
    );
}

编译器错误指向此部分

 : "cc"

非常感谢任何解密错误消息或实际问题的帮助,谢谢

1 个答案:

答案 0 :(得分:4)

正如Michael Petch解释问题的直接原因可能是因为Ubuntu现在附带了一个GCC版本,默认情况下会创建位置无关的可执行文件(PIE)。当编译器生成位置无关代码(PIC)时,asm语句不起作用。您可以使用以下代码替换代码,因为它应该是等效的:

// set up the x87 FPU, ignoring the SSE MXCSR used for normal FP operations in x86-64 or 32-bit with -mfpmath=sse
static inline void fpuinit (long a)
{
    asm volatile (
        "mov %1, %0\n\t"
        "fninit\n\t"
        "fldcw %0\n"
        : "=m" (*(short *)fpuasm)    // *OUTPUT* operand, not input
        : "ir" ((short) (0x037F & 0xF0FF | (a & 0xFF) << 8)));
}

或者更好的是,在asm之外分配fpuasm(如果您只想设置前2个字节,则分配memcpy),或者根本不分配,只使用本地tmp。 (两种方式on the Godbolt compiler explorer)的源+编译器生成的asm。这仍然有关于严格别名的警告,但至少我们告诉编译器这个函数写fpuasm,而不是读它。

这取代了尴尬的"p"“指针”约束和c“常量”操作数修饰符,它需要使其与简单的"m"“内存”约束一起使用。无论是否将其编译为PIC,这都具有优势。它也适用于32位和64位目标。

我还利用FNINIT指令将FPU控制字设置为已知状态(0x037F)这一事实来优化代码,因此不需要使用FSTCW指令来读取它。

使用两个内存目的地AND / OR指令而不是在寄存器中准备值也是愚蠢的。