Сейчас на форуме: tyns777 (+4 невидимых)

 eXeL@B —› Программирование —› Хочу перевести функцию работы со строками на асм вставки под delphi и максимально оптимизировать.
Посл.ответ Сообщение


Ранг: 450.3 (мудрец), 13thx
Активность: 0.20
Статус: Участник

Создано: 12 октября 2009 15:44
· Личное сообщение · #1

Хочу написать на асме вставки в процедуру для Дельфи которая приведённа ниже. Желательно конечно переписать полностью на асме. Работать должна с длинными строками более 255 символов. Смысл думаю понятен, выделяет строку по номеру через разделитель. Например GetSubStr('aaa:bb:c:ddd:e',':',2) вернёт строку bb, если разделителя не найдено возвращаем передаваемую строку в случае индекса 1, или пустую строку в случае другого. Если в строке нет элемента с таким номером, то пустую возвращаем. Так же хотелось бы сделать что бы разделитель был не обязательно однобайтовый...
В общем спрашиваю по тому, что возможно кто посоветует готовое решение или может даже подобная функция есть в дельфи, либо кто-то за пять минут черкнёт. Я в свою очередь тоже попытаюсь изобразить на асме это, но хотелось бы максимально оптимизировано, а я в этом не силён...
Приведённая функция работает сейчас хуже, чем описано как должна работать, но и этого в принципе достаточно, лишь бы шустро было...

Code:
  1. function GetSubStr(st:string; expl:string; n:integer):string;
  2. Var p,i:integer;
  3. Begin
  4. for i:=1 to n-1 do
  5. begin
  6. p:=pos(expl,st);
  7. st:=copy(st,p+1,Length(st)-p);
  8. while (pos(expl,st)=1) and (length(st)>0) do
  9. delete(st,1,1);
  10. end;
  11. p:=pos(expl,st);
  12. if p<>0 then result:=copy(st,1,p-1)
  13. else result:=st;
  14. End;





Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 12 октября 2009 16:15
· Личное сообщение · #2

Вроде эта функция , но на асм полностью ...

Code:
  1. InString proc startpos:DWORD,lpSource:DWORD,lpPattern:DWORD
  2.  
  3.   ; ------------------------------------------------------------------
  4.   ; InString searches for a substring in a larger string and if it is
  5.   ; found, it returns its position in eax.
  6.   ;
  7.   ; It uses a one (1) based character index (1st character is 1,
  8.   ; 2nd is 2 etc...) for both the "StartPos" parameter and the returned
  9.   ; character position.
  10.   ;
  11.   ; Return Values.
  12.   ; If the function succeeds, it returns the 1 based index of the start
  13.   ; of the substring.
  14.   ; 0 = no match found
  15.   ; -1 = substring same length or longer than main string
  16.   ; -2 = "StartPos" parameter out of range (less than 1 or longer than
  17.   ; main string)
  18.   ; ------------------------------------------------------------------
  19.  
  20.     LOCAL sLen:DWORD
  21.     LOCAL pLen:DWORD
  22.  
  23.     push ebx
  24.     push esi
  25.     push edi
  26.  
  27.     invoke StrLen,lpSource
  28.     mov sLen, eax           ; source length
  29.     invoke StrLen,lpPattern
  30.     mov pLen, eax           ; pattern length
  31.  
  32.     cmp startpos, 1
  33.     jge @F
  34.     mov eax, -2
  35.     jmp isOut               ; exit if startpos not 1 or greater
  36.   @@:
  37.  
  38.     dec startpos            ; correct from 1 to 0 based index
  39.  
  40.     cmp  eax, sLen
  41.     jl @F
  42.     mov eax, -1
  43.     jmp isOut               ; exit if pattern longer than source
  44.   @@:
  45.  
  46.     sub sLen, eax           ; don't read past string end
  47.     inc sLen
  48.  
  49.     mov ecx, sLen
  50.     cmp ecx, startpos
  51.     jg @F
  52.     mov eax, -2
  53.     jmp isOut               ; exit if startpos is past end
  54.   @@:
  55.  
  56.   ; ----------------
  57.   ; setup loop code
  58.   ; ----------------
  59.     mov esi, lpSource
  60.     mov edi, lpPattern
  61.     mov al, [edi]           ; get 1st char in pattern
  62.  
  63.     add esi, ecx            ; add source length
  64.     neg ecx                 ; invert sign
  65.     add ecx, startpos       ; add starting offset
  66.  
  67.     jmp Scan_Loop
  68.  
  69.     align 16
  70.  
  71.   ; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  72.  
  73.   Pre_Scan:
  74.     inc ecx                 ; start on next byte
  75.  
  76.   Scan_Loop:
  77.     cmp al, [esi+ecx]       ; scan for 1st byte of pattern
  78.     je Pre_Match            ; test if it matches
  79.     inc ecx
  80.     js Scan_Loop            ; exit on sign inversion
  81.  
  82.     jmp No_Match
  83.  
  84.   Pre_Match:
  85.     lea ebx, [esi+ecx]      ; put current scan address in EBX
  86.     mov edx, pLen           ; put pattern length into EDX
  87.  
  88.   Test_Match:
  89.     mov ah, [ebx+edx-1]     ; load last byte of pattern length in main string
  90.     cmp ah, [edi+edx-1]     ; compare it with last byte in pattern
  91.     jne Pre_Scan            ; jump back on mismatch
  92.     dec edx
  93.     jnz Test_Match          ; 0 = match, fall through on match
  94.  
  95.   ; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  96.  
  97.   Match:
  98.     add ecx, sLen
  99.     mov eax, ecx
  100.     inc eax
  101.     jmp isOut
  102.     
  103.   No_Match:
  104.     xor eax, eax
  105.  
  106.   isOut:
  107.     pop edi
  108.     pop esi
  109.     pop ebx
  110.  
  111.     ret
  112.  
  113. InString endp


-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube




Ранг: 78.3 (постоянный)
Активность: 0.030
Статус: Участник

Создано: 12 октября 2009 18:12
· Личное сообщение · #3

есть готовые модули, faststring, qstring И т.д.




Ранг: 450.3 (мудрец), 13thx
Активность: 0.20
Статус: Участник

Создано: 12 октября 2009 18:42
· Личное сообщение · #4

mak пишет:
Вроде эта функция , но на асм полностью ...


Насколько я понял функция ищет позицию подстроки в основной строке с позиции указанной в startpos.
Это лишь часть алгоритма, но и его можно использовать дописав остальное. Мне одно не ясно, похоже этот код древний очень, почему не используются инструкции типа SCAS? Не похож он на вершину оптимизации...

fakit пишет:
есть готовые модули, faststring, qstring И т.д.


Ищу сейчас. Если под рукой есть ссылки - буду признателен.




Ранг: 450.3 (мудрец), 13thx
Активность: 0.20
Статус: Участник

Создано: 12 октября 2009 19:48
· Личное сообщение · #5

Вот нашёл интересный код на базе которого можно всё сделать:

Code:
  1. proc search,_baseadr,_stradr,_basel,_strl
  2. pushad
  3. cld
  4. push [_strl]
  5. push [_stradr]
  6. call UpCases
  7. mov edi,[_baseadr]      ; адрес базовой строки
  8. .NXTSE:
  9. mov esi,[_stradr]       ; адрес искомой строки
  10. mov ecx,[_basel]
  11. mov al,byte[esi]; элемент
  12. repnz scasb
  13. jnz .SEARTH_ERROR
  14. dec edi
  15. mov esi,[_stradr]
  16. mov ecx,[_strl]         ; длина строки
  17. repe cmpsb
  18. jnz .NXTSE
  19. mov eax,edi
  20. sub eax,[_strl]
  21. mov [resylt],eax
  22. jmp .EXT
  23. ;Строка найденна
  24. .SEARTH_ERROR:
  25. mov [resylt],0
  26. .EXT:
  27. popad
  28. mov eax,[resylt]
  29. ret
  30. resylt dd 0
  31. endp


Отсюда выкинуть UpCases, добавить смещение с которого начинать поиск, добавить индекс нужного элемента, если результат найден, инкрементировать счётчик найденных вхождений и сравнивать с индексом, как только равны - отрезаем от позиции подстроки+длина подстроки до следующей если есть или до конца. Так примерно?

p.s. Нашёл AcedStrings, как я понял дальнейшее развитие QStrings. Интересно, но нужно функции нет, есть из чего слепить, но хотелось бы всё в одной asm вставке...



Ранг: 172.2 (ветеран)
Активность: 0.070
Статус: Участник

Создано: 12 октября 2009 19:55
· Личное сообщение · #6

если не ошибаюсь
Code:
  1. lea eax, STROKA
  2. push    offset SubStr 
  3. push eax
  4. call    strstr
  5. add esp, 8


-----
HOW MUCH BLOOD WOULD YOU SHED TO STAY ALIVE





Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 12 октября 2009 21:36
· Личное сообщение · #7

Ну да , там можно задавать разные патерны , как ты и хотел , длинее , на выходе в есх длина слова , на еах расположение патерна. Пару строчек и код копируется откуда надо , длина кода известна , размер известен , начало тоже задается в начале кода. Копию делаешь как те угодно.

Код не старый , команды типа lods, scas, movs медленее обычно , этот код был проверен и оттестирован тамерными макросами , и расчитан на скоростную оптимизацию но не размерную. Хочешь чтобы было быстрее задействуй сопроцессор.

Результаты старых тестов данной процедуры

Code:
  1. Intel(R) Core(TM)2 Duo CPU     E8500  @ 3.16GHz (SSE4)
  2.  
  3. Search Test 1 - value expected 37; lenSrchPattern ->22
  4. InString - JJ:                         38 ; clocks: 99
  5. InString - Lingo:                      37 ; clocks: 39
  6.  
  7. Search Test 2 - value expected 1007; lenSrchPattern ->17
  8. InString - JJ:                         1008 ; clocks: 22567
  9. InString - Lingo:                      1007 ; clocks: 6294
  10.  
  11. Search Test 3 - value expected 1008 ;lenSrchPattern ->16
  12. InString - JJ:                         1009 ; clocks: 712
  13. InString - Lingo:                      1008 ; clocks: 502
  14.  
  15. Search Test 4 - value expected 1008 ;lenSrchPattern ->16
  16. InString - JJ:                         1009 ; clocks: 6600
  17. InString - Lingo:                      1008 ; clocks: 1418
  18.  
  19. Search Test 5 - value expected 1008 ;lenSrchPattern ->16
  20. InString - JJ:                         1009 ; clocks: 5426
  21. InString - Lingo:                      1008 ; clocks: 1308
  22.  
  23. Search Test 6 - value expected 1008 ;lenSrchPattern ->16
  24. InString - JJ:                         1009 ; clocks: 629
  25. InString - Lingo:                      1008 ; clocks: 498
  26.  
  27. Search Test 7 - value expected 1009 ;lenSrchPattern ->14
  28. InString - JJ:                         1010 ; clocks: 625
  29. InString - Lingo:                      1009 ; clocks: 502
  30.  
  31. Search Test 8 - value expected 1001 ;lenSrchPattern ->1
  32. InString - JJ:                         0 ; clocks: 781
  33. InString - Lingo:                      1001 ; clocks: 102
  34.  
  35. Search Test 9 - value expected 1001 ;lenSrchPattern ->2
  36. InString - JJ:                         1002 ; clocks: 611
  37. InString - Lingo:                      1001 ; clocks: 512
  38.  
  39. Search Test 10 - value expected 1001 ;lenSrchPattern ->3
  40. InString - JJ:                         1002 ; clocks: 625
  41. InString - Lingo:                      1001 ; clocks: 435
  42.  
  43. Search Test 11 - value expected 1001 ;lenSrchPattern ->4
  44. InString - JJ:                         1002 ; clocks: 635
  45. InString - Lingo:                      1001 ; clocks: 496
  46.  
  47. Search Test 12 - value expected 1001 ;lenSrchPattern ->5
  48. InString - JJ:                         1002 ; clocks: 795
  49. InString - Lingo:                      1001 ; clocks: 638
  50.  
  51. Search Test 13 --Find 'Duplicate inc' in 'windows.inc' ;lenSrchPattern ->13
  52. InString - JJ:                         1127625 ; clocks: 679836
  53. InString - Lingo:                      1127624 ; clocks: 543385
  54.  
  55. Press ENTER to exit...


-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube




Ранг: 25.1 (посетитель)
Активность: 0.010
Статус: Участник

Создано: 12 октября 2009 21:51
· Личное сообщение · #8

FastProject ;)



Ранг: 309.8 (мудрец), 21thx
Активность: 0.170
Статус: Участник

Создано: 12 октября 2009 22:18
· Личное сообщение · #9

ntdll!strstr
shlwapi!StrStrIA
shlwapi!StrStrIW

-----
Shalom ebanats!



 eXeL@B —› Программирование —› Хочу перевести функцию работы со строками на асм вставки под delphi и максимально оптимизировать.
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати