如何提取位于AL中定义的索引位置的字节



问题陈述:需要从寄存器中提取位于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 中。

最新更新