"Оптимизация для PENTIUM процессора" - читать интересную книгу автораПример 9:
MOV ESI, [A] ; адрес массива байт MOV ECX, [N] ; число элементов массива TEST ECX, ECX ; сравнение N с 0 JZ SHORT L2 MOV EAX, [ESI] ; читаем первые четыре байта L1: MOV EBX, EAX ; копируем в EBX AND EAX, 7F7F7F7FH ; берем младшие 7 бит каждого байта в EAX XOR EBX, EAX ; берем старшие биты каждого байта в EBX ADD EAX, 02020202H ; увеличивает значение всех четырех байт XOR EBX, EAX ; возвращаем биты обратно MOV EAX, [ESI+4] ; читаем следующие четыре байта MOV [ESI], EBX ; сохраняем результат ADD ESI, 4 ; приращиваем указатель SUB ECX, 4 ; уменьшаем счетчик цикла JA L1 ; цикл L2: Этот цикл исполняется за 5 тактов, для каждых 4 байт. Разумеется, массив должен быть выравнен на 4. Если число элементов массива не делимо на 4, то вы можете добавить несколько дополнительных байт в начале или конце массива, что бы выравнять его на четыре. Этот цикл всегда будет читать часть байт за концом массива, так что вы должны убедиться, что массив не расположен в конце сегмента, что бы избежать GPF. Примечание - я замаскировал каждый верхний бит, в каждом байте, для того что бы избежать возможного переноса при сложении. Я, так же, использовал XOR вместо ADD, возвращая старшие биты на место, что бы снова избежать возможного переноса. Инструкция ADD ESI, 4 может быть удалена, если использовать счетчик цикла в качестве индекса, как в примере 4. Однако, это приведет к нечетному количеству инструкций в теле цикла, так что цикл по прежнему будет исполняться 5 тактов. Используя непарную инструкцию ветвления мы можем сохранить один такт после последней операции, когда переход непредсказан, но мы должны затратить несколько дополнительных тактов в прологе кода, устанавливая указатель на конец массива и расчитывая -N, таким образом два метода будут одинаково быстрыми. Метод представленный здесь наиболее простой и короткий. Следующий пример находит длину нуль-терминированной строки, поиском первого нулевого байта. Это быстрее, чем REP SCASB: Пример 10: STRLEN PROC NEAR MOV EAX,[ESP+4] ; получаем указатель MOV EDX,7 ADD EDX,EAX ; pointer+7 используется в конце PUSH EBX |
|
|