错误:未知"%" SPARC上的符号

时间:2016-09-19 22:09:10

标签: gcc assembly inline-assembly sparc

我的程序在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上运行?

1 个答案:

答案 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添加了输入寄存器i0i1,将结果存储在输出寄存器o0中。 (在函数arg中输入,并在函数结果中输出。SPARC uses a sliding window onto a large virtual register file可能会或可能不会溢出到内存,具体取决于save指令运行时CPU微体系结构是否超出寄存器。)

请记住,这些错误来自Solaris汇编程序,而不是来自gcc。您正在使用gcc,但它使用系统汇编程序而不是GNU汇编程序。

无论如何,我建议将代码重写为纯可移植C,而不是使用#ifdef __x86__继续使用内联asm,或者编写它的SPARC端口。

顺便说一下,你的asm声明看起来很糟糕。不同版本的gcc可能会在.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,即使 知道如何正确使用它,它也适用。