![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поиск в бинарном файле [D5, WinXP]
Dimaxx © (2004-09-24 23:32:00)
Страницы: < 1 2 3 4 5 6 7 8 9 10 ... 13 14 >
Сабж. Нужен алгоритм действительно быстрого поиска последовательности байт любой длины в файлах любого размера (до гигабайта). Читать кусками по-деревенски не катит. Раньше у меня был алгоритм, но с падением Фуджика все пропало.
GuAV (2004-10-07 20:11:00) [21]Реализация [242] для поиска из [193]
@@WideScan:
Cmp ECx, 16
Jb @@SmallScan
Mov Al,[EAx]
Mov Ah, Al
MovD MM6, EAx
PUNPCKLWD MM6, MM6
PUNPCKLDQ MM6, MM6
Push ECx
Test EDx, 7
Jz @@Scan5
Mov ECx, EDx
And ECx, 7
And EDx, not 7
MovQ MM7, [EDx]
PCMPEQB MM7, MM6
PACKSSWB MM7, MM7
MovD EAx, MM7
And EAx, SmallTestArray[ECx*4].DWord
Jnz @@1stbytes
Mov EAx, ECx
Mov ECx, [ESp]
Add EDx, 8
Sub ECx, EAx
@@Scan5:
MovQ MM7, [EDx]
PCMPEQB MM7, MM6
PACKSSWB MM7, MM7
MovD EAx, MM7
Test EAx, EAx
Jnz @@CharFound2
Add EDx,8
Sub ECx,8
Jg @@Scan5
@@Exit_False2:
Emms
Pop EAx
Xor EAx, EAx
Ret
@@1stbytes:
Mov [ESp], ECx
Mov ECx, 8
@@CharFound2:
Dec Ecx
Test EAx,0Fh
Jnz @@Check2
Shr EAx,4
Jmp @@CharFound2
@@Loop2:
Dec Ecx
Test Al,Al
Js @@Check2
Shr EAx,8
Jmp @@Loop2
@@Check2:
Test ECx,ECx
Js @@Exit_False2
Emms
Pop EAx
Sub EAx, ECx
Ret
> пересечемся в аське
никак. только мыло.
Defunct (2004-10-07 19:33:00) [22]2 GuruAV: я смотрю вы из Харькова, не хотите быть соавтором статьи в ВАКовском журнале "Проблемы программирования"? Если да, тогда давайте пересечемся в аське.
GuAV (2004-10-07 16:10:00) [23]По поводу поиска по восем байт без AV мысль такая.
сначала Test Buffer, 7 и если не нуль то
{
читать в mmreg 8 байт из [Buffer and (not 7)]
в начало могут попасть байты из длины и счета ссылок, чтобы их проигнорировать, тестить результатPCMPEQB / PACKUSWBвот такой маской (адресовать в самой маске по [Buffer and 7)])
SmallTestArray: array[0..7] of LongWord =поправить буфер Buffer:=Buffer and (not 7)
($00000000,
$F0000000,
$FF000000,
$FFF00000,
$FFFF0000,
$FFFFF000,
$FFFFFF00,
$FFFFFFF0);
}
потом читать по 8 байт из буфера (он уже QWord aligned)
потом читать остаток, если он есть. Причём 8 байт, хотя осталось меньше. Тестить масокй из аналогичного массива. Буфер остался QWord Aligned, поэтому чтение не пересечет 4к-границу, т.е. AV не будет.
GuAV (2004-10-07 02:23:00) [24]
@@CompareWholeString:
Test EBx, EBx
Jz @@Constant_Exists
Cmp EDx, EBx
Jna @@Exit_False
Push ESi
Push EDi
Add EDi, EBx
Add ESi, EBx
@@CWs_1:
Test EBx, 1
Jz @@CWs_2
Sub ESi, 1
Sub EDi, 1
MOV AL, [ESi]
CMP AL, [EDi]
JNE @@SkipBTest1
@@CWs_2:
Test EBx, 2
Jz @@CWs_4
Sub ESi, 2
Sub EDi, 2
MOV AX, [ESi]
CMP AX, [EDi]
JNE @@SkipBTest1
@@CWs_4:
Test EBx, 4
Jz @@CWs_8
Sub ESi, 4
Sub EDi, 4
MOV EAX, [ESi]
CMP EAX, [EDi]
JNE @@SkipBTest1
@@CWs_8:
MOV ECX, EBX
@@CW_Loop:
SUB ECX, 8
JL @@Constant_Exists1
SUB ESi, 8
SUB EDi, 8
MovQ MM3, [ESi]
MovQ MM2, [EDi]
PCMPEQB MM3, MM2
PACKSSWB MM3, MM3
MovD EAX, MM3
Cmp EAX, -1
JE @@CW_Loop
@@SkipBTest:
Mov ECx, EDx
@@SkipBTest1:
Cmp EDx,4
Pop EDi
Pop ESi
Jg @@Scan
Jmp @@LastDWord
@@Constant_Exists1:
Pop EDi
Pop ESi
@@Constant_Exists:
Pop EAx
Sub EAx, EDx
GuAV (2004-10-07 02:05:00) [25][239] опять не рабочий код дал, блин... вот рабочий:
@@CompareWholeString:
Test EBx, EBx
Jz @@Constant_Exists
Cmp EDx, EBx
Jna @@Exit_False
MOV ECX, EBX
@@CWs_1:
Test ECx, 1
Jz @@CWs_2
Sub ECx, 1
MOV AL, [ESi+ECx]
CMP AL, [EDi+ECx]
JNE @@SkipBTest
@@CWs_2:
Test ECx, 2
Jz @@CWs_4
Sub ECx, 2
MOV AX, [ESi+ECx]
CMP AX, [EDi+ECx]
JNE @@SkipBTest
@@CWs_4:
Test ECx, 4
Jz @@CWs_8
Sub ECx, 4
MOV EAX, [ESi+ECx]
CMP EAX, [EDi+ECx]
JNE @@SkipBTest
@@CWs_8:
@@CW_Loop:
SUB ECX, 8
JL @@Constant_Exists
MovQ MM3, [ESi+ECx]
MovQ MM2, [EDi+ECx]
PCMPEQB MM3, MM2
PACKSSWB MM3, MM3
MovD EAX, MM3
Cmp EAX, -1
JE @@CW_Loop
@@SkipBTest:
Mov ECx, EDx
Cmp EDx,4
Jg @@Scan
Jmp @@LastDWord
@@Constant_Exists:
Pop EAx
Sub EAx, EDx
GuAV (2004-10-07 01:49:00) [26]
@@CompareWholeString:
Test EBx, EBx
Jz @@Constant_Exists
Cmp EDx, EBx
Jna @@Exit_False
MOV ECX, EBX
@@CWs_1:
Test ECx, 1
Jz @@CWs_2
MOV AL, [ESi+ECx]
CMP AL, [EDi+ECx]
Sub ECx, 1
@@CWs_2:
Test ECx, 2
Jz @@CWs_4
MOV AX, [ESi+ECx]
CMP AX, [EDi+ECx]
Sub ECx, 4
@@CWs_4:
Test ECx, 4
Jz @@CWs_8
MOV EAX, [ESi+ECx]
CMP EAX, [EDi+ECx]
Sub ECx, 8
@@CWs_8:
@@CW_Loop:
SUB ECX, 8
JL @@Constant_Exists
MovQ MM3, [ESi+ECx]
MovQ MM2, [EDi+ECx]
PCMPEQB MM3, MM2
PACKSSWB MM3, MM3
MovD EAX, MM3
Cmp EAX, -1
JE @@CW_Loop
@@SkipBTest:
Mov ECx, EDx
Cmp EDx,4
Jg @@Scan
Jmp @@LastDWord
@@Constant_Exists:
Pop EAx
Sub EAx, EDx
Defunct © (07.10.04 01:09) [238]
Не думаю что я справлюсь раньше. Пока я ещё не полностью понимаю работу имеющесйся. Однако, завтра у меня будет много времени.
Defunct (2004-10-07 01:09:00) [27]У меня промелькнула идея которая не только может значительно ускорить функцию, но и решит проблему с validate 0. Как вы думаете, если при MMX сканировании и при CharPos (раскрученном цикле) формировать массив найденных символов и потом с ним и работать. (т.е. например, просмотрели 8 символов, нашли 3 совпадения и дальше уже работает с совпадениями, все найденные совпадения не подходят - тогда продолжаем смотреть следующие 8 символов).
PS: меня сейчас время поджимает, смогу рассмотреть эту идею только на выходных, если у вас есть время можете попробовать раньше.
GuAV (2004-10-07 00:33:00) [28]Defunct © (07.10.04 00:14) [236]
не знал про это. тогда так:
@@WideScan:
Cmp ECx, 16
Jb @@SmallScan
Mov Al,[EAx]
Mov Ah, Al
MovD MM6, EAx
PUNPCKLWD MM6, MM6
PUNPCKLDQ MM6, MM6
Push EBx
Push EDx
Mov EBx, ECx
And EBx, not 7
Add EBx, EDx
Test EDx, 4
Jz @@WSc_Scan5
MovD MM7, [EDx] // load a part of buffer that needs to be scaned
PCMPEQB MM7, MM6 // make a bit mask (mm6 filled by 1st char of da constant)
MovD EAx, MM7 // get mixed dword
Test EAx, EAx
Jnz @@WSc_DFound
Add EDx, 4
Sub EBx, 4 // do not check dword again
@@WSc_Scan5:
MovQ MM7, [EDx]
и далее по тексту.
то есть, если был DWord align, то при WSc_Scan5 будет QWord align, а не быть его может только в извращённых условиях типа validate0, под которые подстраиваемся, но не оптимизируем.
Defunct (2004-10-07 00:14:00) [29]Guru, а вы учитываете выравнивание на границу QWord при MMX сканировании? На очень больших строках будет существенный проигрыш если не учитываете.
Это же было не от фонаря сделано [193]:
MovQ MM7, [Edi]
PCMPEQB MM7, MM6
PACKSSWB MM7, MM7
MovD EAx, MM7
Test EAx, EAx
Jnz @@CharFound
Add EDi, 8
Mov EAx, Edi
And EAx, 7
Sub EDi,EAx // Aligning index
Sub ECx,8
Add ECx,EAx
Cmp ECx,4
Jnge @@LastDword
У меня получалось добиться индекса 133 в SB2, но тогда мой тест (просмотр 12.5Gb) выполнялся на 2 секунды дольше.
Defunct (2004-10-07 00:03:00) [30]с новым SmallScan [232] стало гораздо хуже:
PosGuru&Def 4 194 134 328
Defunct (2004-10-07 00:00:00) [31]2 GuruAV
На P4 - очень хорошо:
PosGuru&Def 4 188 134 322
PosDef_MMX C 194 139 333
на P2 тоже стало лучше но не на много:
PosGuru&Def 4 1148 692 1840
PosDef_MMX C 1168 699 1867
PosJOH_MMX_a 8 1139 933 2072
GuAV (2004-10-06 23:49:00) [32]kaZaNoVa © (06.10.04 23:24) [231]
Как только, так сразу.
GuAV (2004-10-06 23:42:00) [33][230] не то выложил. не работает. вот что имелось ввиду:
@@SmallScan:
Mov Al, [EAx]
Push ECx
Xchg EDx, EDi
Repne ScasB
Jne @@SSc_Done
Xchg EDx, EDi
Pop EAx
Sub EAx, ECx
Ret
@@SSc_Done:
Xchg EDx, EDi
Pop EAx
Xor EAx, EAx
Ret
kaZaNoVa (2004-10-06 23:24:00) [34]2ALL выложите плиз полный окончательный вариант "ускоренной POS" ;)
GuAV (2004-10-06 23:22:00) [35]Мой smallscan тоже не выходит за буфер. кроме того вместе с предыдущим кодом у меня быстрее чем [193]
@@SmallScan:
Mov Al, [EAx]
Push ECx
Xchg EDx, EDi
Shr ECx, 2
Jz @@SSc_SkipD
Repne ScasD
Je @@SSc_D
@@SSc_SkipD:
Mov ECx, [ESp]
And ECx, 3
Jz @@SSc_Done
Repne ScasB
Jne @@SSc_Done
Xchg EDx, EDi
Pop EAx
Sub EAx, ECx
Ret
@@SSc_Done:
Xchg EDx, EDi
Pop EAx
Xor EAx, EAx
Ret
@@SSc_D:
Add ECx, ECx
Xchg EDx, EDi
Add ECx, ECx
Pop EAx
Sub EAx, ECx
Ret
Проверте на Р4, плиз.
GuAV (2004-10-06 22:19:00) [36]Такой WideScan не вылазит за буфер ни на байт.
Имхо надо сделать остальное типа так же.
@@WideScan:
Cmp ECx, 16
Jb @@SmallScan
Mov Al,[EAx]
Mov Ah, Al
MovD MM6, EAx
PUNPCKLWD MM6, MM6
PUNPCKLDQ MM6, MM6
Push EBx
Push EDx
Mov EBx, ECx
And EBx, not 7
Add EBx, EDx
@@WSc_Scan5:
MovQ MM7, [EDx]
PCMPEQB MM7, MM6
PACKSSWB MM7, MM7
MovD EAx, MM7
Test EAx, EAx
Jnz @@WSc_QFound
Add EDx, 8
Cmp EDx, EBx
Jl @@WSc_Scan5
Mov EBx, ECx
And EBx, 7 // is anything left ?
Jz @@WSc_Done
Test EBx, 4 // dword or more left ?
Jz @@WSc_Last123
@@WSc_LastDword2:
MovD MM7, [EDx] // load a part of buffer that needs to be scaned
PCMPEQB MM7, MM6 // make a bit mask (mm6 filled by 1st char of da constant)
MovD EAx, MM7 // get mixed dword
Test EAx, EAx
Jnz @@WSc_DFound
Add EDx, 4
@@WSc_Last123:
MovD EAx, MM6 // no MMX anymore
Test EBx, 2
Jz @@WSc_LastOne
Cmp AL, [EDx]
Jz @@WSc_AtLast1
Inc EDx
Cmp AL, [EDx]
Jz @@WSc_AtLast1
Inc EDx
@@WSc_LastOne:
Test EBx, 1
Jz @@WSc_Done
Cmp AL, [EDx]
Jz @@WSc_AtLast1
@@WSc_Done:
Pop EDx
Xor EAx, EAx
Pop EBx
Emms
Ret
@@WSc_AtLast1:
Inc EDx
@@WSc_AtLast:
Mov EAx, EDx
Pop EDx
Sub EAx, EDx
Pop EBx
Emms
Ret
@@WSc_QFound:
MovQ MM7, [EDx]
PCMPEQB MM7, MM6
MovD EAx, MM7
Test EAx, EAx
Jnz @@WSc_DFound
Add EDx,4
PSRLQ MM7,32
MovD EAx, MM7
@@WSc_DFound:
Inc EDx
Test EAx, $000000FF
Jnz @@WSc_AtLast
Inc EDx
Test EAx, $0000FF00
Jnz @@WSc_AtLast
Inc EDx
Test EAx, $00FF0000
Jnz @@WSc_AtLast
Inc EDx
Jmp @@WSc_AtLast
@Small_String:
Sha (2004-10-06 18:32:00) [37]> Defunct © (06.10.04 18:26) [225]
> 100% где-то в тесте что-то не учтено.
При этом хорошо бы еще сказать что именно не учтено :)
Давай начнем с исправления очевидной ошибки в ConstantPos('ef9','efg');
Defunct (2004-10-06 18:29:00) [38]> При заходе на вторую пересылку адрес в edx уже на 1 больше.
Понял
Sha (2004-10-06 18:27:00) [39]в Sha © (06.10.04 18:13) [223] случайно выкусил не тот код.
Ошибка происходит, там где ты ее нашел.
Defunct (2004-10-06 18:26:00) [40]Еще один загадочный эксепшин. Идет проверка, не выходит ли подстрока за границу буфера, и если не выходит, тогда происходит сканирование в обратном порядке (с конца строки). Опять же Exception?
Cmp Cl, Bl <-- проверка на выход за границу буфера
Jb @NotFound2 <-- буфер меньше длинны подстроки - выход
Push ECx
Mov ECx, EBx
@Loop2:
Mov Al, [ESi+ECx]
Cmp Al, [EDx+ECx-1] <--- Exceptoin здесь
Jnz @Scan7
Loop @Loop2
100% где-то в тесте что-то не учтено.