Здраствуйте уважаемые, хотел спросить у вас совета: Пишу программу, в которой скорость выполнения инструкций в цикле играет ключевую роль, каждый такт идёт в счёт, проситал статьи по оптимизации у вас, но окончательного ответа не нашёл: 1. Как быстрее измерить длину строки? 2. Как быстрее очистить некую область памяти(размер области известен) 3. Как быстрее переместить данные из одной области в памяти в другую?(размер известен) 4. Как быстрее сравнить две строки?(размер известен) Если подкрепите свой ответ примером, буду очень признателен! Заранее благодарен.
BUGOR Ищи по форуму (кажется в этом разделе), были коды на все 4 ф-ции, у тебя известен размер - можно ещё под отдельный камень пооптимизировать Тем уже нет, искать надо в оффлайн или гугле, вот strlen для не очень маленьких строк Код (Text): ;====================================== strlenA: mov eax,[esp+4] align 16 @@: mov ecx,dword[eax] and ecx,0x7F7F7F7F add ecx,0x7F7F7F7F or ecx,dword[eax] add eax,4 or ecx,0x7F7F7F7F add ecx,1 jz @b neg ecx bsf ecx,ecx add ecx,1 shr ecx,3 sub ecx,5 add eax,ecx sub eax,[esp+4] ret 4 ;====================================== Код (Text): ========================================= Длина строки/такты | lstrlen | strlenA | ========================================= 10 | 118 | 30 100 | 475 | 140 1000 | 4047 | 1070(выровн4)/1510(невыровн) =========================================
bogrus Огромное спасибо, попробую! А насчёт 3 и 4 не мог бы ты мне помочь? Неужели никто не может помочь?
В аттаче 3 функции, оптимизированные примерно под такую же задачу: многократный вызов в цикле. 1482259362__strfuncs.asm
Быстрее использовать строки в стиле Pascal. Тогда 1 сводится к чтению длины из переменной, 4 также ускоряется (сначала можно проверить, равна ли длина строк, а затем - равны ли сами строки). Вообще, при операциях с буферами и строками удобнее хранить длину буфера, чем работать с null terminated-строками. Многие API-функции возвращают длину строки, записанной в буфер, поэтому никаких дополнительных расходов на вызов strlen не требуется.
Вот strcmp из ntdll.dll, работает довольно быстро (намного быстрее lstrlenA из kernel32.dll): Код (Text): mystrcmp macro ;compares two strings: ; ecx -> str1 ; edx -> str2 test edx, 3 jnz short @not_dword_aligned @go_on: mov eax, [edx] cmp al, [ecx] jnz short @not_equal test al, al jz short @null_reached cmp ah, [ecx+1] jnz short @not_equal test ah, ah jz short @null_reached shr eax, 10h cmp al, [ecx+2] jnz short @not_equal test al, al jz short @null_reached cmp ah, [ecx+3] jnz short @not_equal add ecx, 4 add edx, 4 test ah, ah jnz short @go_on align 4 @null_reached: xor eax, eax jmp short @end align 4 @not_equal: sbb eax, eax add eax, eax add eax, 1 jmp short @end align 4 @not_dword_aligned: test edx, 1 jz short @word_aligned mov al, [edx] add edx, 1 cmp al, [ecx] jnz short @not_equal add ecx, 1 test al, al jz short @null_reached test edx, 2 jz short @go_on @word_aligned: mov ax, [edx] add edx, 2 cmp al, [ecx] jnz short @not_equal test al, al jz short @null_reached cmp ah, [ecx+1] jnz short @not_equal test ah, ah jz short @null_reached add ecx, 2 jmp short @go_on @end: Я думаю переписать код между @go_on и @null_reached так: читаем по дворду с каждой строки, вычитаем одно из другого, проверяем на конец строки по Агнеру Фогу... Так быстрее получится или нет? Как считаете?
Да-да Очепятка, сорри. Кстати, разница в скорости очень существенная: если программа с ntdll.strcmp обрабатывает файл за 6 секунд, то с использованием kernel32.lstrcmpA она обрабатывает его аж за 18 секунд!