поскольку мы особо не обращали внимания при конвертировании на другие вещи, то у нас образовалось много строк типа MOV EAX, EAX. Сразу видно они излишни ;-). Просто удалим их.
Code: |
function ForLoopBASM9(Start, Stop : Integer) : Integer; asm push ebp push ebx mov ebp,esp add esp,-$14 //mov edx,edx mov [ebp-$04],eax //Result := 0; xor eax,eax mov [ebp-$0c],eax //for I := Start to Stop do mov eax,[ebp-$04] //mov edx,edx mov ecx,eax mov eax, [ebp-$0c] //begin @LoopStart : mov ebx, ecx //mov edx, edx cmp ebx, edx ja @LoopEnd //Result := Result + I; //mov ecx,ecx add eax,ecx inc ecx //end; jmp @LoopStart @LoopEnd : //mov eax,eax mov esp,ebp pop ebx pop ebp end; |
При оптимизации ассемблерного кода есть две линии поведения, которым мы можем следовать. Мы можем думать как человек, пытаясь проявлять сообразительность, используя информацию из кода. Мы поступили так, когда распределяли регистры. Другой путь – это пытаться использовать системный подход, так как поступает компилятор/оптимизатор. Это путь разработки алгоритмов. Данный подход позже даст многое для оптимизации, так мы поступали много раз выше. Удаление лишних строк кода, MOV EAX, EAX, был примером удаления мертвого кода, что является базисом для любых оптимизаторов.
Вверху функции мы еще имеем некоторые ссылки на стек. Для их удаления мы должны разместить эти переменные также в регистрах. В данное время мы выберем регистры EDI и ESI, поскольку они ни где не используются. Используем ESI для [EBP-$04] и EDI для [EBP-$0C]. Поскольку регистры ESI и EDI должны быть сохранены, мы поместим их в стек и потом восстановим.
Code: |
function ForLoopBASM10(Start, Stop : Integer) : Integer; asm push ebp push ebx push esi push edi mov ebp,esp add esp,-$14 //mov [ebp-$04],eax mov esi,eax //Result := 0; xor eax,eax //mov [ebp-$0c],eax mov edi,eax //for I := Start to Stop do //mov eax,[ebp-$04] mov eax,esi mov ecx,eax //mov eax, [ebp-$0c] mov eax, edi //begin @LoopStart : mov ebx, ecx cmp ebx, edx ja @LoopEnd //Result := Result + I; add eax,ecx inc ecx //end; jmp @LoopStart @LoopEnd : mov esp,ebp pop edi pop esi pop ebx pop ebp end; |
Фрейм стека больше нигде не используется и поэтому нет нужды его настраивать, это также сохранит 4 инструкции. Затем заметим, что две строки
mov eax,esi
mov ecx,eax
могут быть заменены одной.
mov ecx, esi
Это пример упрощения копирования с дальнейшим удалением мертвого кода. Любые другие строки не используют значения в EAX далее следующей строки, которая копирует обратно в ECX. Фактически это сразу переписывается строкой MOV EAX, EDI. Поэтому мы можем заменить вторую строку, на строку MOV ECX, ESI и удалить первую, которая становится мертвым кодом.
Code: |
function ForLoopBASM11(Start, Stop : Integer) : Integer; asm //push ebp push ebx push esi push edi //mov ebp,esp //add esp,-$14 mov esi,eax //Result := 0; xor eax,eax mov edi,eax //for I := Start to Stop do //mov eax,esi //mov ecx,eax mov ecx, esi mov eax, edi //begin @LoopStart : //mov ebx, ecx //cmp ebx, edx cmp ecx, edx ja @LoopEnd //Result := Result + I; add eax,ecx inc ecx //end; jmp @LoopStart @LoopEnd : //mov esp,ebp pop edi pop esi pop ebx //pop ebp end; |
Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.
ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!