Как написать на masm под х86 функцию поиска кол-ва вхождений последовательности байт в большом массиве байт? - Assembler

Узнай цену своей работы

Формулировка задачи:

Привет! В общем читаю я файл (большой) и хочу найти кол-во вхождений в этот файл некоторой последовательности байт, допустим "AC DF EE FF", как можно на ассемблере (буду вставлять в виде ассемблеровской вставки в код на С++) написать экстремально быстрый поиск этой последовательности? В общем на входе:
Листинг программы
  1. char* haystack; //массив байтов заранее не известного содержимого
  2. char* hsSize; //размер haystack
  3. char* needle; // последовательность байт, которую нужно искать в haystack
  4. char* nSize; //размер needle
В общем в haystack могут быть любые данные, такие "ААААААААFCFCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", а может быть и белый шум... В общем нужен код ассемблеровской вставки с экстремально быстрым поиском Моде задействовать SSE2 ? или ещё чего? Это только приветствуется! Почему ассемблер? Хочу минимизировать кол-во инструкций при поиске. Знаю, что для человека, хорошо знакомого с masm-ом, накидь пару строк не составит труда, по этому надеюсь на ваше помощь в великие гуру хардкора
Между прочим, я как бы не студент и халявщик))) Я просто хочу ускорить свой софт и пока что раздумываю над тем, как можно это сделать. Просто бурта форс с небольшой оптимизацией меня как - то не впечатлил:
Листинг программы
  1. unsigned int FileScanner::smartBruteForce(QByteArray &data, QByteArray &needle)
  2. {
  3. unsigned int count = 0;
  4. unsigned int dataSize = data.size();
  5. unsigned int needleSize = needle.size();
  6. unsigned int needleSizeCut = needleSize - 1;
  7. char* dp = data.data();
  8. char* np = needle.data();
  9. char lastNeedle = *(np + needleSize - 1);
  10. for(unsigned int i = 0; i < dataSize - needleSize + 1; i++)
  11. {
  12. if(*(dp + (i + needleSizeCut)) != lastNeedle) //This is smart technology ))))
  13. continue;
  14. unsigned int j;
  15. for(j = 0; j < needleSize; j++)
  16. {
  17. if(*(dp + (i + j)) != *(np + j))
  18. break;
  19. }
  20. if(j == needleSize)
  21. count++;
  22. }
  23. return count;
  24. }
Ещё думал над КМП методом (Алгоритм Кнута–Морриса-Пратта), но он относительно хорош для поиска одного вхождения, а не всех или я пока что не особо в него в ник... Думал даже на GPU ускорить, но тут всю скорость просрёшь на копирование данных в видео память...

Решение задачи: «Как написать на masm под х86 функцию поиска кол-ва вхождений последовательности байт в большом массиве байт?»

textual
Листинг программы
  1. org  100h
  2. jmp  start
  3.  
  4. mess0   db  13,10,'<==== TRUE $'  ; мессага если есть вхождение,
  5. mess1   db  13,10,'<=== FALSE $'  ; .. и если нет вхождения под/строки
  6.  
  7. haystack  db  '45210fffdknvbcdhgff751fghdj001234'  ; строка (данные твоего файла)
  8. hsSize    =   $ - haystack   ; длина строки
  9. needle    db  '0knvbcdhg'    ; под/строка
  10. nSize     =   $ - needle     ; длина под/строки
  11.  
  12. start:
  13. ;================================================================================
  14.    mov   di,haystack         ; место для поиска SCASB'ом
  15.    mov   cx,hsSize           ; кол-во повторов
  16.    mov   al,byte [needle]    ; искать будем первый символ под/строки
  17. find:                        ;
  18.    repne scasb               ; прекратить при совпадении!
  19.    jz    ok                  ; переход, если есть совпадение
  20.    jmp   errorFind           ; иначе: ошибка!
  21. ok:                          ;
  22.    push  cx di               ; сохраняем счётчик и позицию в строке
  23.    mov   cx,nSize            ; меняем счётчик на длину под/строки
  24.    dec   di                  ; SCASB проскочил позицию. вернём её..
  25.    mov   si,needle           ; SI указывает на адрес под/строки
  26.    repe  cmpsb               ; сравниваем строки до не совпадения
  27.    jz    stopFind            ; переход, если строки совпали
  28.    pop   di cx               ; иначе: восстанавливаем счётчик и позицию в строке
  29.    jmp   find                ; и продолжаем поиск в строке со-старой позиции
  30. ;================================================================================
  31. stopFind:                    ; поиск дал результат!
  32.    mov   ah,9                ;
  33.    mov   dx,mess0            ;
  34.    int   21h                 ;
  35.    jmp   exit                ;
  36. errorFind:                   ; прокол!
  37.    mov   ah,9                ;
  38.    mov   dx,mess1            ;
  39.    int   21h                 ;
  40.  
  41. exit:                        ;
  42.    xor   ax,ax               ;
  43.    int   16h                 ;
  44.    int   20h                 ; выход!

Объяснение кода листинга программы

Ниже представлен код на языке Assembler со следующей постановкой задачи — «Как написать на masm под х86 функцию поиска кол-ва вхождений последовательности байт в большом массиве байт?» org 100h jmp start mess0 db 13,10,'<==== TRUE $' mess1 db 13,10,'<=== FALSE $' haystack db '45210fffdknvbcdhgff751fghdj001234' hsSize = $ - haystack needle db '0knvbcdhg' nSize = $ - needle start: ;================================================================================ mov di,haystack mov cx,hsSize mov al,byte [needle] find: repne scasb jz ok jmp errorFind ok: push cx di mov cx,nSize dec di mov si,needle repe cmpsb jz stopFind pop di cx jmp find stopFind: mov ah,9 mov dx,mess0 int 21h jmp exit errorFind: mov ah,9 mov dx,mess1 int 21h exit: xor ax,ax int 16h int 20h Вывод: Кол-во вхождений последовательности '0knvbcdhg' в строке '45210fffdknvbcdhgff751fghdj001234' равно 2.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

7   голосов , оценка 4.143 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы