无效'asm':操作数不是条件码,无效的操作数代码'c'
Invalid 'asm': operand is not a condition code, invalid operand code 'c'
我正尝试从这里 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 0, %c[fp]+1(,1)\n"
"orb %%al, %c[fp]+1(,1)\n"
"fldcww %c[fp]\n"
:
: "a" (a), [fp] "p" (fpuasm)
: "cc"
);
}
编译器错误指向这部分
: "cc"
如果能帮助破译错误消息或实际问题,我们将不胜感激,谢谢
正如 Michael Petch 所解释的,问题的直接原因可能是因为 Ubuntu 现在附带了一个默认创建位置独立可执行文件 (PIE) 的 GCC 版本。当编译器生成位置无关代码 (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
. (来源 + 编译器为两种方式生成的 asm on the Godbolt compiler explorer)。这仍然有关于严格别名的警告,但至少我们告诉编译器这个函数写入 fpuasm
,而不是读取它。
这取代了笨拙的 "p"
"pointer" 约束和 c
"constant" 操作数修饰符,它需要使用简单的 "m"
"memory"约束。这样做的好处是无论它是否被编译为 PIC 都可以工作。它还适用于 32 位和 64 位目标。
我还利用 FNINIT 指令将 FPU 控制字设置为已知状态 (0x037F) 的事实来优化代码,因此无需使用 FSTCW 指令来读取它。
使用两条内存目标 AND/OR 指令而不是在寄存器中准备值也很愚蠢。
我正尝试从这里 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 0, %c[fp]+1(,1)\n"
"orb %%al, %c[fp]+1(,1)\n"
"fldcww %c[fp]\n"
:
: "a" (a), [fp] "p" (fpuasm)
: "cc"
);
}
编译器错误指向这部分
: "cc"
如果能帮助破译错误消息或实际问题,我们将不胜感激,谢谢
正如 Michael Petch 所解释的,问题的直接原因可能是因为 Ubuntu 现在附带了一个默认创建位置独立可执行文件 (PIE) 的 GCC 版本。当编译器生成位置无关代码 (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
. (来源 + 编译器为两种方式生成的 asm on the Godbolt compiler explorer)。这仍然有关于严格别名的警告,但至少我们告诉编译器这个函数写入 fpuasm
,而不是读取它。
这取代了笨拙的 "p"
"pointer" 约束和 c
"constant" 操作数修饰符,它需要使用简单的 "m"
"memory"约束。这样做的好处是无论它是否被编译为 PIC 都可以工作。它还适用于 32 位和 64 位目标。
我还利用 FNINIT 指令将 FPU 控制字设置为已知状态 (0x037F) 的事实来优化代码,因此无需使用 FSTCW 指令来读取它。
使用两条内存目标 AND/OR 指令而不是在寄存器中准备值也很愚蠢。