问题陈述:需要从寄存器中提取位于ymm0
寄存器AL
中值的位置的字节。
我的方法:(相当丑陋):
;将 XMM1 设置为"向右移动一个字节"掩码 ;XMM1 : 000F0E0D0C0B0A090807060504030201 CMP AL,15 ;检查 YMM0 或更高的下 XMMWORD 中 贾is_in_higher 异或CX,CX 莫夫 CL,阿拉巴马 loop_for_next : VPextrb edx,ymm0,ymm0,0 vpshufb xmm0,xmm0,xmm1 ;右移 xmm0 作为掩码 循环loop_for_next .. is_in_higher : vperm2i128 ymm0,ymm0,ymm0,01 ;将上部 128 交换为下部 128 JMP loop_for_next
有没有更优雅的方法呢?任何建议不胜感激。挑战的关键在于VPEXTRB
仅采用即时索引值,而不是CL
(或AL
)寄存器作为索引值
谢谢。。。
您的代码需要 AVX2 ( vperm2i128
),但我无法测试它,因为我只有 AVX。无论如何,您的代码对不需要循环的任务使用循环。我的解决方案使用简单的查找表和vpshufb
(需要 SSSE3)指令来重新排序字节。在 YASM 中测试。
代码如下:
[位 64]部分 .文本全球_start_开始:set_example_values: 莫夫·阿尔,0x1e ;字节索引: 0...31, 0x00...0x1f vmovaps ymm0,[example_data] ;定义数据code_starts_here: CMP AL,15 JNA no_need_to_reorder_octalwords vperm2f128 ymm0,ymm0,ymm0,0x81 ;重新排序 ymm0。零顶部 16 字节。no_need_to_reorder_octalwords: 和 EAX,15 SHL EAX,4 vmovaps xmm1,[rax+shuffle_table] ;每个字节都是一个索引,f0 = 设置为 0。 vpshufb xmm0,xmm1 ;将右字节复制到 xmm0 的字节 0。 ;将 xmm0 的剩余字节数归零。 移动 RDX,xmm0 ;复制到 RDX。 ...。数据对齐 32; F E D C B A 9 8 7 6 5 4 3 2 1 0example_data做0xafaeadacabaaa9a8a7a6a5a4a3a2a1a0; 1f1e1d1c1b1a19181716151413121110 做0xbfbebdbcbbbab9b8b7b6b5b4b3b2b1b0shuffle_table dd 0xf0f0f000, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f001, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f002, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f003, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f004, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f005, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f006, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f007, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f008, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f009, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f00a, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f00b, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f00c, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f00d, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f00e, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 DD 0xf0f0f00f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0
虽然
我不确定,但可能是这样的:
and eax, 0x0000001F // eax = [al & 31, 0, 0, 0]
or eax, 0x80808000 // eax = [al & 31, 0x80, 0x80, 0x80]
vmovd xmm1, eax // ymm1 = [eax, 0, 0, 0, 0, 0, 0, 0]
vpshufb ymm0, ymm0, ymm1 // ...
vmovd eax, xmm0 // eax = [ymm0.byte[al & 31], 0, 0, 0]
从位置 al 的 ymm0 提取的字节存储在 eax 中。