Содержание материала

 

Строка, помеченная как "New" введена, для создания переменной цикла I. Строка MOV EBX, [EBP-$10] копирует переменную I в регистр EBX. Следующая строка копирует переменную Stop в регистр ECX. Затем в строке CMP EBX, ECX они сравниваются, и инструкцией JBE @LOOPSTART управление передается в начало цикла, если I меньше или равно Stop. Поскольку мы используем регистр EBX и он не разрешен для свободного использования, поэтому мы его сохраняем его в стеке.

Мы решили проверять окончания цикла в начале цикла. Данный тест разделен компилятором на две части. Перед входом в цикл проверяется, что цикл может выполниться как минимум один раз и реальное окончание цикла проверяется в конце. Такая техника оптимизации называется инверсия цикла. Теперь мы сменим цикл так, что бы такую оптимизацию. Потом мы увидим преимущества от этой оптимизации.

Code:

function ForLoopBASM4(Start, Stop : Integer) : Integer;

asm

push ebp

push ebx

mov ebp,esp

add esp,-$14

mov [ebp-$08],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,[ebp-$08]

//sub edx,eax

//jl @LoopEnd

mov [ebp-$10],eax

  //begin

  @LoopStart :

    mov ebx, [ebp-$10]

    mov ecx, [ebp-$08]

    cmp ebx, ecx

    ja  @LoopEnd

    //Result := Result + I;

    mov eax,[ebp-$10]

    add [ebp-$0c],eax

    inc dword ptr [ebp-$10]

  //end;

  //mov ebx, [ebp-$10]

  //mov ecx, [ebp-$08]

  //cmp ebx, ecx

  //jbe @LoopStart

  jmp @LoopStart

@LoopEnd :

  mov eax,[ebp-$0c]

mov esp,ebp

pop ebx

pop ebp

end;

 

 

Проверка на окончания цикла была перемещена в начало и тест был инвертирован. На месте старой проверки теперь находится безусловный переход. Этот переход единственное, что сделано по отношению к инверсной оптимизации. В не оптимизированном цикле было два  перехода,  оптимизированным один. Проверка вверху, то что проверяется всегда. Start был на Stop и теперь лишнее и поэтому удалено. Перед проведением измерений по эффекту от двух оптимизаций, хорошей идеей будет оптимизировать часть или все, что возможно, стек в регистры, регистры в стек. Данный процесс называется размещение в регистрах и это одна из самых важных оптимизаций на всех архитектурах, но это особенно важно для архитектуры Intel, поскольку в ней малое количество доступных регистров. Если нет места для всех переменных в регистрах, то важно определить какие переменные поместить в регистры. Инструкции MOV в теле цикла наиболее важные кандидаты на это. Они выполняются большое количество раз. Инструкции за пределами цикла выполняются только раз. Переменные внутри цикла первыми должны быть размещены в регистрах. Это переменные I, Stop и Result. Теперь рассмотрим использование регистров для временных переменных. Если переменная всегда копируется в тот же самый временный регистр, то ее желательно разместить в этом регистре. Переменная Stop в регистре EDX при входе в функцию и также используется как временный регистр, во всех строках, кроме двух строк. Здесь есть две строки в цикле, которые мы добавили, изменим их

mov ecx, [ebp-$08]

cmp ebx, ecx

на

mov edx, [ebp-$08]

cmp ebx, edx

Регистр EAX используется для Start вверху функции и как Result в остальной части функции. Если нет перекрытия по использованию, то мы можем использовать EAX для Result, как только Start прекратит его использования. После того, как Start назначен переменной I (MOV [EBP-$10], EAX), он больше нигде не используется и регистр EAX свободен для использования для Result, кроме тех строк, где EAX используется как временное хранилище для I.

mov eax,[ebp-$10]

add [ebp-$0c],eax

inc dword ptr [ebp-$10]

после того, как ECX прекращает использоваться, мы можем его использовать как временное хранилище для I, вместо EAX.

mov ecx,[ebp-$10]

add [ebp-$0c],ecx

inc dword ptr [ebp-$10]

Подведем итог по первой части оптимизации по использованию регистров: Result в EAX, I в ECX и Stop в EDX.

В начале заменим все строки со Stop. [EBP-$08] на использование EDX.

Code:

function ForLoopBASM6(Start, Stop : Integer) : Integer;

asm

push ebp

push ebx

mov ebp,esp

add esp,-$14

//mov [ebp-$08],edx

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,[ebp-$08]

mov edx,edx

mov [ebp-$10],eax

  //begin

  @LoopStart :

    mov ebx, [ebp-$10]

    //mov edx, [ebp-$08]

    mov edx, edx

    cmp ebx, edx

    ja  @LoopEnd

    //Result := Result + I;

    mov ecx,[ebp-$10]

    add [ebp-$0c],ecx

    inc dword ptr [ebp-$10]

  //end;

  jmp @LoopStart

@LoopEnd :

  mov eax,[ebp-$0c]

mov esp,ebp

pop ebx

pop ebp

end;

 

Затем распределим ECX для I, заменив  [EBP-$10] на ECX.

Code:

function ForLoopBASM7(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 [ebp-$10],eax

mov ecx,eax

  //begin

  @LoopStart :

    //mov ebx, [ebp-$10]

    mov ebx, ecx

    mov edx, edx

    cmp ebx, edx

    ja  @LoopEnd

    //Result := Result + I;

    //mov ecx,[ebp-$10]

    mov ecx,ecx

    add [ebp-$0c],ecx

    //inc dword ptr [ebp-$10]

    inc ecx

  //end;

  jmp @LoopStart

@LoopEnd :

  mov eax,[ebp-$0c]

mov esp,ebp

pop ebx

pop ebp

end;

 

И на конец используем EAX для Result. Поскольку EAX также используется вверху функции для Start и как временный регистр для инициализации Result нулем, то мы должны добавить несколько строк для копирования Result в EAX после как EAX более нигде не будет использоваться для других целей.

Code:

function ForLoopBASM8(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]                //New

  //begin

  @LoopStart :

    mov ebx, ecx

    mov edx, edx

    cmp ebx, edx

    ja  @LoopEnd

    //Result := Result + I;

    mov ecx,ecx

    //add [ebp-$0c],ecx

    add eax,ecx

    inc ecx

  //end;

  jmp @LoopStart

@LoopEnd :

  //mov eax,[ebp-$0c]

  mov eax,eax

mov esp,ebp

pop ebx

pop ebp

end;

 

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить