我的程序在Ubuntu上运行良好。
在Solaris SPARC系统上使用gcc编译时遇到错误。
我有几段代码,如:
printf("endian_convert: %s\n", endian_convert);
asm("movl $8, %esi\n\t"
"movl $.LC0, %edi\n\t"
"movl $0, %eax");
这是我在SPARC上遇到的错误:
gcc -g -Wall -Werror -pedantic -Wextra src/utfconverter.c -o bin/utf
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 957: error: unknown "%"-symbol
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 957: error: statement syntax
.......
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 1058: error: unknown "%"-symbol
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 1058: error: statement syntax
*** Error code 1 make: Fatal error: Command failed for target `utf'
所以,"%" SPARC上的符号被认为是未知的?
如何解决此问题并使其在SPARC上运行?
答案 0 :(得分:4)
(问题的原始版本没有提到错误来自SPARC Solaris系统,只是称之为C90,因为安装在其上的旧版gcc默认为-std=c90
,导致关于在C90中非法的事情的错误消息。)
等一下,"在Ubuntu上工作正常但在C90"上没有。 /usr/ccs/bin/as
(在您的屏幕截图中)看起来像Solaris。那个+主机名是一个线索,这可能是SPARC机器,而不是x86。
显然x86程序集不是有效的SPARC程序集语法。它是一种不同的CPU架构。
如果您使用了gcc foo.c -S
并查看了生成的foo.s
asm输出文件,您会看到它已经满了SPARC asm,除了您的字面插入的文字asm
陈述。
SPARC语法在寄存器名称上使用%装饰器,但寄存器名称不同。例如add %i0, %i1, %o0
添加了输入寄存器i0
和i1
,将结果存储在输出寄存器o0
中。 (在函数arg中输入,并在函数结果中输出。SPARC uses a sliding window onto a large virtual register file可能会或可能不会溢出到内存,具体取决于save
指令运行时CPU微体系结构是否超出寄存器。)
请记住,这些错误来自Solaris汇编程序,而不是来自gcc。您正在使用gcc,但它使用系统汇编程序而不是GNU汇编程序。
无论如何,我建议将代码重写为纯可移植C,而不是使用#ifdef __x86__
继续使用内联asm,或者编写它的SPARC端口。
.LC0
处存储不同的常量,从而破坏您的代码。更重要的是,您没有使用输入/输出约束来告诉编译器哪个值在哪里。如果您认为可以在函数内部设置eax,那就不正确了。该函数可以并且将内联,然后你的asm只是在函数内联的任何地方浮动。有关一些GNU C内联asm教程的链接,请参阅the end of this answer。
此外,您不需要内联asm来进行endian-convert。使用像uint32_t le32toh(uint32_t little_endian_32bits);
这样的endian.h functions使用gcc builtins或inline asm让编译器自己制作最佳的汇编输出,你会得到更好的效果。
另请参阅https://gcc.gnu.org/wiki/DontUseInlineAsm,即使 知道如何正确使用它,它也适用。