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

 

Так мы удалили использование ESI и избавились от сохранения и его восстановления. При удалении POP ESI, вспомним, что было три выхода и каждый со своим собственным POP ESI.

Code:

function CharPos26(Chr : Char; const Str : AnsiString) : Cardinal;

asm

push ebx

//push esi

//if StrLenght > 0 then

test edx,edx

jz  @Else1Begin

//StrLenght := Length(Str);

mov ebx,[edx-$04]

//I := 0;

xor ecx,ecx

dec  edx

@RepeatBegin :

//Inc(I);

inc  ecx

//until((Str[I] = Chr) or (I > StrLenght));

cmp  al,[edx+ecx]

jz   @If2

cmp  ebx,ecx

jnl  @RepeatBegin

//if I <= StrLenght then

@If2 :

cmp  ebx,ecx

jnl  @Exit

//Result := 0;

xor eax,eax

//pop  esi

pop  ebx

ret

//Result := 0;

@Else1Begin :

xor eax,eax

//pop  esi     

pop  ebx     

ret

@Exit :

mov  eax, ecx

//pop  esi

pop  ebx

end;

 

В строке после метки If2 есть строка, которая идентична второму сравнению для окончания цикла. В Паскаль эта строка была необходимой, поскольку IF I <= STRLENGHT после цикла, поскольку не было ясно, как закончился цикл. Данная строка порождала лишнею инструкцию CMP EBX, ECX, которая теперь явно не нужна. На самом деле это не так, поскольку есть два перехода на метку If2 и только в одном из них есть проверка. Если мы изменим, эти два перехода так, чтобы только один из них шел на to If2, то мы сможем удалить лишнею проверку. Вместо перехода на If2 при сравнении мы можем сделать переход напрямую на метку Exit.

Code:

function CharPos27(Chr : Char; const Str : AnsiString) : Cardinal;

asm

push ebx

//if StrLenght > 0 then

test edx,edx

jz  @Else1Begin

//StrLenght := Length(Str);

mov ebx,[edx-$04]

//I := 0;

xor ecx,ecx

dec  edx

@RepeatBegin :

//Inc(I);

inc  ecx

//until((Str[I] = Chr) or (I > StrLenght));

cmp  al,[edx+ecx]

//jz   @If2

jz   @Exit

cmp  ebx,ecx

jnl  @RepeatBegin

//if I <= StrLenght then

//@If2 :

//cmp  ebx,ecx

//jnl  @Exit

//Result := 0;

xor eax,eax

pop  ebx

ret

//Result := 0;

@Else1Begin :

xor eax,eax

pop  ebx

ret

@Exit :

mov  eax,ecx

pop  ebx

end;

 

Метка If2 становится лишней и когда мы доходим до этой позиции, то мы знаем, что достигнут конец строки (ограничитель #0) и поэтому на не надо повторно тестировать условие.

Также здесь есть два идентичных куска кода, перед меткой Else1Begin и после ее. Удалим верхний кусок.

Code:

function CharPos28(Chr : Char; const Str : AnsiString) : Cardinal;

asm

push ebx

//if StrLenght > 0 then

test edx,edx

jz   @Else1Begin

//StrLenght := Length(Str);

mov  ebx,[edx-$04]

//I := 0;

xor ecx,ecx

dec  edx

@RepeatBegin :

//Inc(I);

inc  ecx

//until((Str[I] = Chr) or (I > StrLenght));

cmp  al,[edx+ecx]

jz   @Exit

cmp  ebx,ecx

jnl  @RepeatBegin

//Result := 0;

//xor  eax,eax

//pop  ebx

//ret

//Result := 0;

@Else1Begin :

xor eax,eax

pop  ebx

ret

@Exit :

mov  eax,ecx

pop  ebx

end;

На этом наш поиск по удалению лишнего кода закончен. Чистая версия кода выглядит так:

Code:

function CharPos29(Chr : Char; const Str : AnsiString) : Cardinal;

asm

push ebx

//if StrLenght > 0 then

test edx,edx

jz   @Else1Begin

//StrLenght := Length(Str);

mov  ebx,[edx-$04]

//I := 0;

xor ecx,ecx

dec  edx

@RepeatBegin :

//Inc(I);

inc  ecx

//until((Str[I] = Chr) or (I > StrLenght));

cmp  al,[edx+ecx]

jz   @Exit

cmp  ebx,ecx

jnl  @RepeatBegin

@Else1Begin :

//Result := 0;

xor eax,eax

pop  ebx

ret

@Exit :

mov  eax,ecx

pop  ebx

end;

 

При итерации в поиске для нахождения позиции или конца строки, данные строки кода повторяются снова и снова.

inc  ecx

cmp  al,[edx+ecx]

jz   @Exit

cmp  ebx,ecx

jnl  @RepeatBegin

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

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

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

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


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