Ассемблер и Delphi

Тема в разделе "WASM.BEGINNERS", создана пользователем Shooshpanchik, 14 сен 2009.

  1. Shooshpanchik

    Shooshpanchik Member

    Публикаций:
    0
    Регистрация:
    29 сен 2006
    Сообщения:
    117
    Есть процедура на Дельфе, хочу переделать ее на ассемблерную вставку, но что-то не очень получается. Пока есть 2 проблемы.
    Вот текст:

    Код (Text):
    1. Const tmp:array[0..3] of Cardinal = ($67452301,$EFCDAB89,$98BADCFE,$10325476);
    2. function MD5Buffer2(const Buffer; Size: Cardinal): TMD5Digest;
    3. var
    4.   Context : TMD5Context;
    5.   bits: array[0..2] of Cardinal;
    6.   index, padLen: Cardinal;
    7. begin
    8. //InitContext
    9. // Context.state := tmp;
    10.   asm
    11.     lea edi, Context
    12.     db $BE
    13.     dd tmp //mov esi, tmp    // Первая трабла - ну не дает просто написать mov esi, tmp и все тут, а сам именно так делает. Как могно обойти? ну не оч. охота в машинные коды влазить.
    14.     movsd
    15.     movsd
    16.     movsd
    17.     movsd
    18. //    xor eax, eax    // Вторая трабла -  если раскоментировать получу AV, правда уже в другом месте, но мне нужно именно нулями заполнить. Пробовал и в стеке сохрянтять прежде и в другом регистре, всеравно.
    19.     mov ecx, 18
    20.     rep stosd
    21.   end;
    22. ...
     
  2. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Код (Text):
    1. lea esi, tmp[0]
     
  3. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Во вторых - по-моему полное непонимаение что такое TMD5Context
     
  4. Shooshpanchik

    Shooshpanchik Member

    Публикаций:
    0
    Регистрация:
    29 сен 2006
    Сообщения:
    117
    Хм. первая трабла решена, правда опкод чуток длиннее, но это мелочь.
    Переделываю то что написано, правда уже зверски сократил ту реализацию. Теперь самое приятное... Хм. а что я там не понил то ? Инициализируем, заполняя остаток нулями.
     
  5. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Ну для начала неплохо посмотреть на описание:
    Код (Text):
    1. type TMD5Context = packed record
    2.   State: TMD5State;
    3.   Count: TMD5Count;
    4.   Buffer: TMD5Buffer;
    5. end;
    Где все поля структуры - это динамические массивы и "насилование" этих указателей через копирование чего-то куда-то к ничему хорошему не приведет.

    В любом случае с размерностью буфера для копирование тоже какая-то
    херня:
    Код (Text):
    1.     lea edi, Context
    2.     ...
    3.     movsd
    4.     movsd
    5.     movsd
    6.     movsd
    7.     mov ecx, 18
    8.     rep stosd
    Итого в Context залили 4*4+18*4 = 88 байт. Неудивительно что после работы такого "кода" получаем AV в разных частях программы.
     
  6. Shooshpanchik

    Shooshpanchik Member

    Публикаций:
    0
    Регистрация:
    29 сен 2006
    Сообщения:
    117
    Кст
    lea esi, [tmp]
    полностью эквивалентна
    mov esi, tmp
    (ну кроме длины опкода) или можно еще чего нить ожидать ?
     
  7. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    P.S. Описание TMD5Context глядел в инете и там все поля были представляены в виде динамического массива. Возможно у тебя может быть по-другому.
     
  8. Shooshpanchik

    Shooshpanchik Member

    Публикаций:
    0
    Регистрация:
    29 сен 2006
    Сообщения:
    117
    В record это не указатели, это они сами и есть (у меня packed не было указано, но хотя они то и так выровнены нормально)
    state - 4*4 байт
    count - 2*4
    buffer - 1*64
    итого 88 байт
    Заполняет то нормально, но не нулями. Имхо тут дело в передаче параметров, в EAX, должен быть первый параметр функции MD5Buffer2...
     
  9. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Shooshpanchik
    Да ну? Если бы оно еще скомпилилосмь можно было бы сравнивать результаты, а пока рано :))
     
  10. Shooshpanchik

    Shooshpanchik Member

    Публикаций:
    0
    Регистрация:
    29 сен 2006
    Сообщения:
    117
    ЗЫ, в Паскале принято давать осмысленные приставки переменным TMD5State это данные PMD5State это указатель.
     
  11. Shooshpanchik

    Shooshpanchik Member

    Публикаций:
    0
    Регистрация:
    29 сен 2006
    Сообщения:
    117
    А по бряку в View CPU видно дизасм листинг. Там он так это предоставляет.
     
  12. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Shooshpanchik
    Дело может быть не только в EAX, но и в ESI/EDI/ECX. Если ты портишь регистры в середине функции, то не плохобы их предварительно сохранять в стеке.
    Для кого вы это написали? :))
     
  13. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Shooshpanchik
    Это вы опять про что?
     
  14. Shooshpanchik

    Shooshpanchik Member

    Публикаций:
    0
    Регистрация:
    29 сен 2006
    Сообщения:
    117
    Не поевришь, но
    push eax
    pop eax
    в том месте где комент уже приводит к AV.

    Я про
    lea esi, [tmp]
    mov esi, tmp
    В дизасм листинге они именно так написаны.
     
  15. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Shooshpanchik
    Delphi 7-ка эту хрень не компилит. А вот так:
    Код (Text):
    1. mov esi, offset(tmp)
    компилит.
    Давай завязывай с загадками - пости исходники в том виде в котором они у тебя есть. Все медиумы, которые могут прочитать твой код на расстоянии, в отпуске.
     
  16. Shooshpanchik

    Shooshpanchik Member

    Публикаций:
    0
    Регистрация:
    29 сен 2006
    Сообщения:
    117
    Вот тута до меня доперло в чем непонятка

    Пешу
    Код (Text):
    1. lea esi, tmp //в сырце
    Получаю
    Код (Text):
    1. lea esi, [tmp] //в листинге
    Пешу
    Код (Text):
    1. mov esi, tmp //в сырце
    И он не понимает что ему надо, тогда пишу
    Код (Text):
    1. db $BE
    2. dd tmp //в сырце
    и в листинге мы видим наше
    Код (Text):
    1. mov esi, tmp //в листинге
    Сорьки что немного запутал.

    Но вот с EAX, пока совсем не пойму

    „В действительности всё не так, как на самом деле.“ — Станислав Ежи Лец
     
  17. Shooshpanchik

    Shooshpanchik Member

    Публикаций:
    0
    Регистрация:
    29 сен 2006
    Сообщения:
    117
    Во !!! точно
    Код (Text):
    1. mov esi, offset(tmp)
    То что надо !!!
    Да почти все как в оригинале, только скопировал процедуру и добавил цифру 2 в имя.
    И стал править.

    Код (Text):
    1. Const tmp:array[0..3] of Cardinal = ($67452301,$EFCDAB89,$98BADCFE,$10325476);
    2. function MD5Buffer2(const Buffer; Size: Cardinal): TMD5Digest;
    3. var
    4.   Context : TMD5Context;
    5.   bits: array[0..2] of Cardinal;
    6.   index, padLen: Cardinal;
    7. begin
    8. //InitContext
    9. // Context.state := tmp;
    10.   asm
    11.     lea edi, Context
    12.     mov esi, offset(tmp)
    13.     movsd
    14.     movsd
    15.     movsd
    16.     movsd
    17. //    xor eax, eax
    18. //    push eax
    19. //    pop eax
    20.     mov ecx, 18
    21.     rep stosd
    22.   end;
    23.  
    24.   MD5Update(Context, @buffer, Size); // Вот это поменял
    25.  
    26.   bits[0] := Context.count[0];
    27.   bits[1] := Context.count[1]; //Вот это тож, ну там очень тупо было, хотя это только первые наброски.
    28.  
    29.   index := Context.count[0] shr 3 and $3F;
    30.   if index < 56 then padLen := 56 - index
    31.                 else padLen := 120 - index;
    32.   MD5Update(Context, @PADDING, padLen);
    33.   MD5Update(Context, @Bits, 8);
    34.   Result.z :=Context.state;
    35. end;
    AV то получаю в строке

    FF(c, d, a, b, Buffer[14], S13, $A679438E);

    Я бы запостил весь сырец, но у меня счас только GPRS... :dntknw:
    Сырец нашел где-то тута:
    http://koders.com/default.aspx?s=MD5Buffer&la=Delphi&li=%2A&scope=&search.x=2&search.y=4
     
  18. warsem

    warsem Сеня

    Публикаций:
    0
    Регистрация:
    26 янв 2005
    Сообщения:
    170
    Адрес:
    Германия, NRW
    (просто догадка, т.к. ни когда не пробовал таких извратов в делфи)
    mov esi, dword ptr [tmp]
     
  19. Shooshpanchik

    Shooshpanchik Member

    Публикаций:
    0
    Регистрация:
    29 сен 2006
    Сообщения:
    117
    warsem
    А мы с ESI то уже решили :)
    А вот почему

    Код (Text):
    1. push eax
    2. pop eax
    могет привести к AV ?
     
  20. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Shooshpanchik
    Push+pop не "могет", а вот xor eax, eax - запросто, если компилятор не сообразит перед асм-вставкой сохранить регистр eax, в котором в функцию передается указатель Buffer, и соотв-но в MD5Update будет передан нулевой указатель

    И вообще asm-вставки в дельфях - это источник глюков, т.к. компилятор не всегда усекает изменение регистров в асм-вставке и соотв-но не гарантирует их сохранение\восстановление. Поэтому лучше юзать не вставки, а законченные асм-функции, в которых ты сам должен отвечать за изменение, сохранение и восстановление регистров, не полагаясь на компилятор