Как извлечь байт, расположенный в позиции индекса, определенной в AL
Постановка проблемы: нужно извлечь из ymm0
зарегистрировать байт, расположенный в позиции, значение которой находится в регистре AL
,
Мой метод: (довольно некрасиво)
; Установите XMM1 как маску "сдвиг на один байт вправо"; XMM1: 000F0E0D0C0B0A090807060504030201 см,15; проверьте, если в нижнем xmmword ymm0 или выше ja is_in_higher xor CX,CX мов CL,AL loop_for_next: vpextrb edx,ymm0,ymm0,0 vpshufb xmm0,xmm0,xmm1; вправо сдвигает xmm0 как маску loop loop_for_next .. is_in_higher: vperm2i128 ymm0,ymm0,ymm0,01; меняет верхнюю 128 на нижнюю 128 jmp loop_for_next
Есть ли более элегантный способ сделать это? Любой совет приветствуется. Суть проблемы заключается в том, что VPEXTRB
принимает только непосредственное значение индекса, а не CL
(или же AL
) зарегистрируйтесь как значение индекса
Спасибо...
2 ответа
Ваш код требует AVX2 (vperm2i128
) и я не смог его протестировать, так как у меня только AVX. В любом случае ваш код использует цикл для задачи, для которой цикл не нужен. Мое решение использует простую таблицу поиска и vpshufb
(требуется SSSE3) инструкция для переупорядочения байтов. Проверено в YASM.
Вот код:
[биты 64] раздел. текст глобальный _start _Начните: set_example_values: mov al, 0x1e; индекс байтов: 0...31, 0x00...0x1f vmovaps ymm0,[example_data]; определить данные code_starts_here: комп 15, 15 jna no_need_to_reorder_octalwords vperm2f128 ymm0, ymm0, ymm0,0x81; изменить порядок ymm0. ноль верхних 16 байт. no_need_to_reorder_octalwords: и eax,15 ЗЫ,4 vmovaps xmm1,[rax+shuffle_table]; каждый байт является индексом, f0 = установлен в 0. vpshufb xmm0,xmm1; скопируйте правый байт в байт 0 из xmm0.; ноль остальные байты xmm0. movq rdx, xmm0; скопировать в rdx. ... .данные выровнять 32; fedcba 9 8 7 6 5 4 3 2 1 0 example_data do 0xafaeadacabaaa9a8a7a6a5a4a3a2a1a0; 1f1e1d1c1b1a19181716151413121110 do 0xbfbebdbcbbbab9b8b7b6b5b4b3b2b1b0 shuffle_table dd 0xf0f0f000, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f001, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f002, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f003, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f004, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f005, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f006, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f007, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f008, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f009, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f00a, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f00b, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f00c, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f00d, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 0xf0f0f00e, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0 дд 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]
Байт, извлеченный из ymm0 в местоположении al, сохраняется в eax.