在C中使用内联汇编的错误

时间:2014-02-24 18:25:31

标签: c gcc assembly mmx

我正在尝试组装以便使用向量操作,这是我以前从未真正使用过的,而且我很难理解一些语法。

相关代码如下。

unit16_t asdf[4];
asdf[0] = 1;
asdf[1] = 2;
asdf[2] = 3;
asdf[3] = 4;
uint16_t other = 3;

__asm__("movq %0, %%mm0"
        :
        : "m" (asdf));
__asm__("pcmpeqw %0, %%mm0"
        :
        : "r" (other));
__asm__("movq %%mm0, %0" : "=m" (asdf));

printf("%u %u %u %u\n", asdf[0], asdf[1], asdf[2], asdf[3]);

在这个简单的例子中,我试图对数组中的每个元素进行16位比较“3”。我希望输出为“0 0 65535 0”。但它甚至不会聚集。

第一个汇编指令给出了以下错误:

错误:内存输入0无法直接寻址

第二条指令给了我一个不同的错误:

错误:对于`pcmpeqw'

,后缀或操作数无效

任何帮助都将不胜感激。

4 个答案:

答案 0 :(得分:3)

来自intel参考手册:

PCMPEQW mm, mm/m64        Compare packed words in mm/m64 and mm for equality.
PCMPEQW xmm1, xmm2/m128   Compare packed words in xmm2/m128 and xmm1 for equality.

您的pcmpeqw使用" r"注册哪个错了。只有" mm"和" m64"寄存器

瓦尔特

答案 1 :(得分:1)

上面的代码在扩展asm()时失败了,它从未试图组装任何东西。在这种情况下,您尝试使用第0个参数(%0),但您没有给出任何参数。

查看GCC Inline assembler HOWTO,或阅读本地GCC文档的相关章节。

答案 2 :(得分:1)

你不能直接在gcc asm语句中使用寄存器,并期望它们与其他asm语句中的任何东西匹配 - 优化器会移动它。相反,您需要声明相应类型的变量并使用约束来强制这些变量进入您正在使用的指令的正确类型的寄存器。

对于xmm寄存器,MMX / SSE的相关约束为x,对于mmx寄存器,y#include <stdint.h> #include <stdio.h> typedef union xmmreg { uint8_t b[16]; uint16_t w[8]; uint32_t d[4]; uint64_t q[2]; } xmmreg; int main() { xmmreg v1, v2; v1.w[0] = 1; v1.w[1] = 2; v1.w[2] = 3; v1.w[3] = 4; v2.w[0] = v2.w[1] = v2.w[2] = v2.w[3] = 3; asm("pcmpeqw %1,%0" : "+x"(v1) : "x"(v2)); printf("%u %u %u %u\n", v1.w[0], v1.w[1], v1.w[2], v1.w[3]); } 。例如,你可以这样做:

3

请注意,您需要在第二个向量的所有相关元素中明确复制{{1}}。

答案 3 :(得分:0)

他是对的,优化器正在改变寄存器内容。切换到内在函数并使用volatile来使事情更加合理可能会有所帮助。