如何复制每个双字的最后一个字节?
Posted
技术标签:
【中文标题】如何复制每个双字的最后一个字节?【英文标题】:How to duplicate last byte of each double-word? 【发布时间】:2019-01-03 22:25:40 【问题描述】:我使用SSE,我想将每个双字的最后一个字节复制4次XMM0,但我不知道该怎么做! (也许有(未)包装?)
为了说明,我想做 this.
感谢您的帮助!
【问题讨论】:
哪些版本的 SSE 可用? SSSE3 会让这一切变得简单 如果没有pshufb
,您可以使用set1_epi32(0x000000ff)
进行屏蔽,然后使用shift + OR。然后pshuflw
/ pshufhw
广播字节。这可能比屏蔽 + packusdw
/ wb
到字和字节,然后 punpcklbw
/ wd
回到双字更有效。
【参考方案1】:
您可以像这样使用 SSSE3 命令PSHUFB
执行此操作(MASM 32 位程序集)
.data
align 16
mask db 0,0,0,0, 4,4,4,4, 8,8,8,8, 12,12,12,12
.code
; value in XMM0 ; 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
pshufb xmm0, xmmword ptr [mask] ; 12 12 12 12 08 08 08 08 04 04 04 04 00 00 00 00
输出似乎与掩码匹配是巧合。 我目前无法对此进行测试,掩码字节的顺序可能会颠倒。但你应该明白了。
无论如何:注意对齐,因为
当源操作数是 128 位内存操作数时,操作数必须在 16 字节边界上对齐,否则会产生通用保护异常 (#GP)。
【讨论】:
你的面具是倒退(在我编辑之前)。该顺序对于_mm_set_epi8
是正确的,它采用高..低顺序的 args。但是低元素(索引 0)是从内存中的最低地址加载/存储的,因此这也会颠倒寄存器中双字的顺序。您评论中的符号是英特尔的正常排序,与内存顺序相反(C 数组初始化程序和 asm db
)。请参阅 Convention for displaying vector registers 了解有关大与小“端序”矢量符号的更多讨论。
您通常会在.rdata
(Windows 上的只读数据)中放置一个向量常量,而不是.data
。 (或 .rodata
在非 Windows 上。)以上是关于如何复制每个双字的最后一个字节?的主要内容,如果未能解决你的问题,请参考以下文章
存储到堆栈地址的双字是不是会影响地址+0..3 或地址-0..3 处的字节?