Быстро определить, совпадает ли "строка" хотя бы с одной "строкой" из двух наборов - Assembler
Формулировка задачи:
Строки не текстовые. Это просто какая-то последовательность из 32-х байт.
Есть адрес первого байта проверяемой строки.
Есть адрес первого байта 1-го набора. Первый набор всегда состоит из 1 элемента.
Есть адрес первого байта 2-го набора. Количество элементов в этом наборе известно и пока пусть равно 3. Но позже понадобится вариант для размера второго набора в 7 элементов.
Разделителей в наборах нет. 32-байтовые последовательности в наборах идут одна за другой.
Вот самый простой вариант, скорость работы которого меня не устраивает:
Попытался сэкономить на MOV RAX,[Str...]. Получилась вот такая здоровая фигня:
Тут не закончено - не хватает ещё многих меток и текста, который должен следовать за этими метками. Я могу это закончить, просто терпения и времени не хватило пока. Ещё очень большой риск сделать ошибку, которую потом будет нереально отловить. Одна неверная буква в метке и всё. Предполагаю, что написание подобного текста для случая, когда второй набор из 7 элементов займёт многие часы.
Так вот, вопрос: есть ли способы
// Str - адрес проверяемой строки // N1 - адрес 1-го набора // N2 - адрес 2-го набора MOV RAX,[Str] CMP RAX,[N1] JNE @ne0 MOV RAX,[Str+8] CMP RAX,[N1+8] JNE @ne0 MOV RAX,[Str+16] CMP RAX,[N1+16] JNE @ne0 MOV RAX,[Str+24] CMP RAX,[N1+24] JE @result_eq @ne0: MOV RAX,[Str] CMP RAX,[N2] JNE @ne1 MOV RAX,[Str+8] CMP RAX,[N2+8] JNE @ne1 MOV RAX,[Str+16] CMP RAX,[N2+16] JNE @ne1 MOV RAX,[Str+24] CMP RAX,[N2+24] JE @result_eq @ne1: MOV RAX,[Str] CMP RAX,[N2+$20] JNE @ne2 MOV RAX,[Str+8] CMP RAX,[N2+$20+8] JNE @ne2 MOV RAX,[Str+16] CMP RAX,[N2+$20+16] JNE @ne2 MOV RAX,[Str+24] CMP RAX,[N2+$20+24] JE @result_eq @ne2: MOV RAX,[Str] CMP RAX,[N2+$40] JNE @result_ne MOV RAX,[Str+8] CMP RAX,[N2+$40+8] JNE @result_ne MOV RAX,[Str+16] CMP RAX,[N2+$40+16] JNE @result_ne MOV RAX,[Str+24] CMP RAX,[N2+$40+24] JNE @result_ne @result_eq: // есть совпадение JMP @finish @result_ne: // нет совпадений @finish: RET
// R11 - адрес проверяемой строки // R12 - адрес первого набора // T - адрес второго набора MOV R13,[R11] // 1 CMP R13,[R12] // r0 JNE @N_1xxx_xxxx_xxxx // > ..1 r0- (s0) CMP R13,[T] // s0 JNE @yxxx_N_1xxx_xxxx // > ..1 r0+ s0- (s1) CMP R13,[T+$20] // s1 JNE @yxxx_yxxx_N_1xxx // > ..1 r0+ s0+ s1- (r2) CMP R13,[T+$40] // r2 JNE @y2xx_yxxx_yxxx_N_M // > 2 r2- (r0) MOV R13,[R11+8] // 2 CMP R13,[R12+8] // r0 JNE @N_y2xx_yxxx_yxxx // > ..2 r0- (s0) CMP R13,[T+8] // s0 JNE @yyxx_N_y2xx_yxxx // > ..2 r0+ s0- (s1) CMP R13,[T+$20+8] // s1 JNE @yyxx_yyxx_N_y2xx // > ..2 r0+ s0+ s1- (r2) CMP R13,[T+$40+8] // r2 JNE @yy3x_yyxx_yyxx_N_M // > 3 r2- (r0) MOV R13,[R11+16] // 3 CMP R13,[R12+16] // r0 JNE @N_yy3x_yyxx_yyxx // > ..3 r0- (s0) CMP R13,[T+16] // s0 JNE @yyyx_N_yy3x_yyxx // > ..3 r0+ s0- (s1) CMP R13,[T+$20+16] // s1 JNE @yyyx_yyyx_N_yy3x // > ..3 r0+ s0+ s1- (r2) CMP R13,[T+$40+16] // r2 JNE @yyy4_yyyx_yyyx_N_M // > 4 r2- (r0) MOV R13,[R11+24] // 4 CMP R13,[R12+24] // r0 JE @N1N2_Y CMP R13,[T+24] // s0 JE @N1N2_Y CMP R13,[T+$20+24] // s1 JE @N1N2_Y CMP R13,[T+$40+24] // r2 JE @N1N2_Y JMP @N1N2_N @N_1xxx_xxxx_xxxx: // < ..1 r0- (s0) CMP R13,[T] // s0 JNE @N_N_1xxx_xxxx // ..1 r0- s0- (s1) CMP R13,[T+$20] // s1 JNE @N_yxxx_N_1xxx // ..1 r0- s0+ s1- (r2) CMP R13,[T+$40] // r2 JNE @N_y2xx_yxxx_N // 2 r0- r2- (s0) MOV R13,[R11+8] // 2 r0- @N_y2xx_yxxx_yxxx: // < ..2 r0- (s0) CMP R13,[T+8] // s0 JNE @N_N_y2xx_yxxx // ..2 r0- s0- (s1) CMP R13,[T+$20+8] // s1 JNE @N_yyxx_N_y2xx // ..2 r0- s0+ s1- (r2) CMP R13,[T+$40+8] // r2 JNE @N_yy3x_yyxx_N // 3 r0- r2- (s0) MOV R13,[R11+16] // 3 r0- @N_yy3x_yyxx_yyxx: // < ..3 r0- (s0) CMP R13,[T+16] // s0 JNE @N_N_yy3x_yyxx // ..3 r0- s0- (s1) CMP R13,[T+$20+16] // s1 JNE @N_yyyx_N_yy3x // ..3 r0- s0+ s1- (r2) CMP R13,[T+$40+16] // r2 JNE @N_yyyx_yyyx_N // 4 r0- r2- (s0) MOV R13,[R11+24] // 4 r0- CMP R13,[T+24] // s0 JE @N1N2_Y CMP R13,[T+$20+24] // s1 JE @N1N2_Y CMP R13,[T+$40+24] // r2 JE @N1N2_Y JMP @N1N2_N @yxxx_N_1xxx_xxxx: // < ..1 r0+ s0- (s1) CMP R13,[T+$20] // s1 JNE @yxxx_N_N_xxxx CMP R13,[T+$40] // r2 JNE @yxxx_N_yxxx_N MOV R13,[R11+8] // 2 s0- CMP R13,[R12+8] // r0 JNE @N_N_yxxx_yxxx @yyxx_N_y2xx_yxxx: // < ..2 r0+ s0- (s1) CMP R13,[T+$20+8] // s1 JNE @yyxx_N_N_yxxx CMP R13,[T+$40+8] // r2 JNE @yyxx_N_yyxx_N MOV R13,[R11+16] // 3 s0- CMP R13,[R12+16] // r0 JNE @N_N_yyxx_yyxx @yyyx_N_yy3x_yyxx: // < ..3 r0+ s0- (s1) CMP R13,[T+$20+16] // s1 JNE @yyyx_N_N_yyxx CMP R13,[T+$40+16] // r2 JNE @yyyx_N_yyyx_N MOV R13,[R11+24] // 4 s0- CMP R13,[R12+24] // r0 JE @N1N2_Y CMP R13,[T+$20+24] // s1 JE @N1N2_Y CMP R13,[T+$40+24] // r2 JE @N1N2_Y JMP @N1N2_N @yxxx_yxxx_N_1xxx: // < ..1 r0+ s0+ s1- (r2) CMP R13,[T+$40] // r2 JNE @yxxx_yxxx_N_N MOV R13,[R11+8] // 2 s1- CMP R13,[R12+8] // r0 JNE @N_yxxx_N_yxxx CMP R13,[T+8] // s0 JNE @yyxx_N_N_yxxx @yyxx_yyxx_N_y2xx: // < ..2 r0+ s0+ s1- (r2) CMP R13,[T+$40+8] // r2 JNE @yyxx_yyxx_N_N MOV R13,[R11+16] // 3 s1- CMP R13,[R12+16] // r0 JNE @N_yyxx_N_yyxx CMP R13,[T+16] // s0 JNE @yyyx_N_N_yyxx @yyyx_yyyx_N_yy3x: // < ..3 r0+ s0+ s1- (r2) CMP R13,[T+$40+16] // r2 JNE @yyyx_yyyx_N_N MOV R13,[R11+24] // 4 s1- CMP R13,[R12+24] // r0 JE @N1N2_Y CMP R13,[T+24] // s0 JE @N1N2_Y CMP R13,[T+$40+24] // r2 JE @N1N2_Y JMP @N1N2_N @y2xx_yxxx_yxxx_N_M: // < 2 r2- (r0) MOV R13,[R11+8] // 2 r2- CMP R13,[R12+8] // r0 JNE @N_yxxx_yxxx_N CMP R13,[T+8] // s0 JNE @yyxx_N_yxxx_N CMP R13,[T+$20+8] // s1 JNE @yyxx_yyxx_N_N @yy3x_yyxx_yyxx_N_M: // < 3 r2- (r0) MOV R13,[R11+16] // 3 r2- CMP R13,[R12+16] // r0 JNE @N_yyxx_yyxx_N CMP R13,[T+16] // s0 JNE @yyyx_N_yyxx_N CMP R13,[T+$20+16] // s1 JNE @yyyx_yyyx_N_N @yyy4_yyyx_yyyx_N_M: // < 4 r2- (r0) MOV R13,[R11+24] // 4 r2- CMP R13,[R12+24] // r0 JE @N1N2_Y CMP R13,[T+24] // s0 JE @N1N2_Y CMP R13,[T+$20+24] // s1 JE @N1N2_Y JMP @N1N2_N @N1N2_Y: // есть совпадение JMP @finish @N1N2_N: // нет совпадений @finish: RET
Не по теме:
Возможно, с целью защиты от ошибок придётся написать отдельную программу для генерации такого текста.
быстро
определить, совпадает ли 32-байтная строка с какой-то строкой из набора? По первому варианту: вроде как можно было бы загружать части строк не в RAX, а в XMM0 и XMM1, но там вроде бы команда сравнения может не сработать, если окажется что часть строки соответствует числу NaN. Или всё-таки можно как-то сравнить значения регистров XMM между собой или с участком памяти для абсолютно любого содержимого? Проц, на котором всё это должно работать не умеет AVX.Решение задачи: «Быстро определить, совпадает ли "строка" хотя бы с одной "строкой" из двух наборов»
textual
Листинг программы
mov r9,[Str] mov r10,[Str+8] mov r11,[Str+16] mov r12,[Str+24]
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д