"Оптимизация для PENTIUM процессора" - читать интересную книгу автора MOV EBX,[EAX] ; читаем первые 4 байта
ADD EAX,4 ; увеличиваем указатель L1: LEA ECX,[EBX-01010101H] ; уменьшаем на 1 каждый байт XOR EBX,-1 ; инвертируем все байты AND ECX,EBX ; и эти два MOV EBX,[EAX] ; читаем следующие 4 байта ADD EAX,4 ; увеличиваем указатель AND ECX,80808080H ; проверяем все битовые знаки JZ L1 ; нет нулевых байт, продолжаем цикл TEST ECX,00008080H ; тестируем первые два байта JNZ SHORT L2 SHR ECX,16 ; не первые два байта ADD EAX,2 L2: SHL CL,1 ; флаг переноса, что бы неветвить POP EBX SBB EAX,EDX ; считаем длину RET ; (или RET 4 для паскаля) STRLEN ENDP Снова мы использовали метод перекрывания конца одной операции с началом другого для улучшения спаривания. Я не развернул цикл, потому что это отняло бы много времени. Строка, конечно, должна быть выравнена на 4. Всегда будут читаться несколько байт в конце строки, так что строка не должна находиться в конце сегмента. неспарена. Используя цикл с одной неспаренной инструкции ветвления, мы делаем упор на другой, что и сохраняет нам 1 такт. Инструкция TEST ECX, 00008080H - не спариваемая. Вы могли бы использовать здесь спариваемую инструкцию OR CH, CL, но вам придется вставить NOP или что-то подобное по следующей причине: Ветвь цикла (JZ L1) обычно непредсказана, в последний раз, когда цикл завершается. А исполнение ветвления (JNZ L2) в первом такте цикла, после непредсказанного ветвления приведет к задержке в 5-10 тактов. Другая проблема с OR CH, CL - это то, что такая инструкция вызовет замедление на процессорах i486 или PentiumPro, так что я решил оставить неспариваемую инструкцию TEST. Обработка 4 байт одновременно может быть весьма трудной. Код использует алгоритм генерации ненулевого значения для байта, если только значение байта - ноль. Это дает возможность тестировать все четыре байта одной операцией. Алгоритм включает вычитание 1 из всех байт (в инструкции LEA). Я не маскировал верхние биты каждого байта перед вычитанием, как я делал в предыдущем примере, потому что это может привести к заему в следующем байте, но только в том случае, если значение текущего байта - ноль, но это нас уже не волнует, т.к. мы ищем до первого нуля. Если мы искали в обратном направлении, то после обнаружении нуля надо перечитать двойное слово, затем протестировать все четыре байта, что бы найти последний ноль и использовать BSWAP, что бы изменить порядок следования байт. |
|
|