Сравнение участков памяти

Тема в разделе "WASM.BEGINNERS", создана пользователем FakeMan, 2 июл 2008.

  1. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    Доброго времени суток.
    Создал этот топик в поисках оптимального решения следующей задачи: необходимо написать максимально быструю ф-ю сравнивающую 2 участка памяти заданного размера.
    На данный момент имеется следующий код
    Код (Text):
    1. function memcmp ( const X, Y: Pointer; Size: Integer): Integer;
    2. asm
    3.   mov esi, X
    4.   mov edi, Y
    5.   mov dl,cl
    6.   and dl,3
    7.   shr ecx,2
    8.   xor eax,eax
    9.   rep cmpsd
    10.   jb @@less
    11.   ja @@great
    12.   mov cl,dl
    13.   rep cmpsb
    14.   jz @@end
    15.   ja @@great
    16.   @@less:
    17.   dec eax
    18.   jmp @@end
    19.   @@great:
    20.   inc eax
    21.   @@end:
    22. end;
    Но что-то мне подсказывает что это не самый быстрый вариант.
    Прошу помочь с поиском оптимального решения.
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Во-первых, у тебя какое-то нестандартное сравнение делается на больше\меньше при cmpsd - обычно сравнивают первый несовпаадающий байт, а не дворд. Поэтому при несовпадении дворда нужно сделать откат esi,edi на 4 и проверить байты либо через cmpsb, либо через bswap+cmp+ja\jb
    Во-вторых, мануалы по оптимизации советуют избегать rep cmps (особенно при малых ecx) и использовать для сравнения циклы (лучше с разворотом, но и без разворота д.б. по крайней мере не хуже cmps)
     
  3. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    [дубль]
     
  4. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    leo А чего не написал человеку Список рекомендуемых мануалов ?
     
  5. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    Заметил еще одну интересную проблему при использовании этого кода.
    К примеру этот код ведет себя крайне неадекватно
    Код (Text):
    1. for I := 0 To Size - 1 do
    2.   begin
    3.     if MemCmp ( A, B, 16 ) = 0 then
    4.       begin
    5.         //.....
    6.       end;
    7.   end;
    Так вот при заходе на вторую интерацию I равняется не 2м, как ожидается, а числу даже большему чем Size.
    Такого я еще не видел :dntknw: (Девид Блейн?)
     
  6. muxamor

    muxamor New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2008
    Сообщения:
    20
    Код (Text):
    1. function memcmp(const p1, p2: pointer; size: DWORD): integer; register;
    2. asm
    3.   push edi
    4.   push esi
    5.   mov edi, eax
    6.   mov esi, edx
    7.   xor eax, eax
    8.   repe cmpsb
    9.   jg @@1
    10.   setl al
    11.   pop esi
    12.   pop edi
    13.   retn
    14. @@1:
    15.   dec eax
    16.   pop esi
    17.   pop edi
    18. end;
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Во-первых, если переменная цикла нигде не используется, то компилятор обычно оптимизирует цикл и изменяет счетчик i не от 0 вверх, а наоборот от числа итераций до 0.
    Во-вторых, если ты в функциях не будешь сохранять\восстанавливать регистры esi\edi\ebx\ebp, то еще и не такое можешь увидеть :)
     
  8. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    Переменная конечно же используется, просто привел крайне упрощенный кусок. от I много чего зависит.
    Опять те же грабли (