【发布时间】:2020-04-07 13:57:28
【问题描述】:
目前我正在尝试从使用 NASM 转向在 c 中使用内联汇编,因为这将使将来的链接变得更加容易(尤其是内联)。但是,我无法让我的矢量指令播放得很好。在英特尔组装中,我能够做到以下几点:
vpcmpeqb ymm0, [rdi]
这将从rdi 读取32 个字节,与ymm0 比较并标记相等的字节。使用 AT&T,我尝试在 c inline asm 中执行以下操作,但它不起作用,它一直抱怨操作数大小不匹配(其中 %1 是输入 as"r"(s)):
vpcmpeqb %%ymm0, %%ymm0, (%1)
我正在编译 gcc 版本9.2.1。
【问题讨论】:
-
AT&T 语法将目的地放在最后。出于同样的原因,NASM
vcmpeqb [rdi], ymm0, ymm0不合法。您可以使用objdump -d来获取 AT&T 对您在 NASM 中编写的内容的反汇编,以帮助学习语法。 -
但是千万不要在 C 中使用内联 asm 进行手动矢量化;使用
__m256 v = _mm256_cmpeq_epi8内在函数。 gcc.gnu.org/wiki/DontUseInlineAsm 您通常可以让编译器生成与您可以手动编写的一样好的 asm,而且您不必担心 GNU C 内联 asm,这非常困难使用。例如除非您在该 asm 语句中有"memory"clobber 或虚拟"m"输入,否则在寄存器中请求指针是不安全的。 How can I indicate that the memory *pointed* to by an inline ASM argument may be used? -
@PeterCordes 谢谢你成功了!我也会注意内联汇编,但内在函数在 IMO 中是如此的考验,它们甚至比内联汇编更棘手。
-
@codam_hsmits 这应该是查看software.intel.com/sites/landingpage/IntrinsicsGuide 的第一页。您可以搜索 asm-mnemonics,也可以“浏览”不同指令的类别。您还可以查看“英特尔® 64 和 IA-32 架构软件开发人员手册”,此处提供了不错的(非官方)在线副本:felixcloutier.com/x86
-
stackoverflow.com/tags/sse/info 有几个链接,包括codeproject.com/Articles/874396/… 这是一个使用内在函数的介绍教程。在我将它添加到标签 wiki 时,我认为它还不错。既然您已经了解 asm,只需了解像
_mm_add_epi32这样的内部函数对应于像paddd这样的 asm 指令,就像+运算符对应于add一样 - 编译器可以优化以不同的方式执行。另请参阅 this re: what__m128ireally is 和严格别名。
标签: gcc assembly inline-assembly avx att