Так мы удалили использование 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
Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.
ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!