Есть процедура на Дельфе, хочу переделать ее на ассемблерную вставку, но что-то не очень получается. Пока есть 2 проблемы. Вот текст: Code (Text): Const tmp:array[0..3] of Cardinal = ($67452301,$EFCDAB89,$98BADCFE,$10325476); function MD5Buffer2(const Buffer; Size: Cardinal): TMD5Digest; var Context : TMD5Context; bits: array[0..2] of Cardinal; index, padLen: Cardinal; begin //InitContext // Context.state := tmp; asm lea edi, Context db $BE dd tmp //mov esi, tmp // Первая трабла - ну не дает просто написать mov esi, tmp и все тут, а сам именно так делает. Как могно обойти? ну не оч. охота в машинные коды влазить. movsd movsd movsd movsd // xor eax, eax // Вторая трабла - если раскоментировать получу AV, правда уже в другом месте, но мне нужно именно нулями заполнить. Пробовал и в стеке сохрянтять прежде и в другом регистре, всеравно. mov ecx, 18 rep stosd end; ...
Хм. первая трабла решена, правда опкод чуток длиннее, но это мелочь. Переделываю то что написано, правда уже зверски сократил ту реализацию. Теперь самое приятное... Хм. а что я там не понил то ? Инициализируем, заполняя остаток нулями.
Ну для начала неплохо посмотреть на описание: Code (Text): type TMD5Context = packed record State: TMD5State; Count: TMD5Count; Buffer: TMD5Buffer; end; Где все поля структуры - это динамические массивы и "насилование" этих указателей через копирование чего-то куда-то к ничему хорошему не приведет. В любом случае с размерностью буфера для копирование тоже какая-то херня: Code (Text): lea edi, Context ... movsd movsd movsd movsd mov ecx, 18 rep stosd Итого в Context залили 4*4+18*4 = 88 байт. Неудивительно что после работы такого "кода" получаем AV в разных частях программы.
Кст lea esi, [tmp] полностью эквивалентна mov esi, tmp (ну кроме длины опкода) или можно еще чего нить ожидать ?
P.S. Описание TMD5Context глядел в инете и там все поля были представляены в виде динамического массива. Возможно у тебя может быть по-другому.
В record это не указатели, это они сами и есть (у меня packed не было указано, но хотя они то и так выровнены нормально) state - 4*4 байт count - 2*4 buffer - 1*64 итого 88 байт Заполняет то нормально, но не нулями. Имхо тут дело в передаче параметров, в EAX, должен быть первый параметр функции MD5Buffer2...
Shooshpanchik Да ну? Если бы оно еще скомпилилосмь можно было бы сравнивать результаты, а пока рано )
ЗЫ, в Паскале принято давать осмысленные приставки переменным TMD5State это данные PMD5State это указатель.
Shooshpanchik Дело может быть не только в EAX, но и в ESI/EDI/ECX. Если ты портишь регистры в середине функции, то не плохобы их предварительно сохранять в стеке. Для кого вы это написали? )
Не поевришь, но push eax pop eax в том месте где комент уже приводит к AV. Я про lea esi, [tmp] mov esi, tmp В дизасм листинге они именно так написаны.
Shooshpanchik Delphi 7-ка эту хрень не компилит. А вот так: Code (Text): mov esi, offset(tmp) компилит. Давай завязывай с загадками - пости исходники в том виде в котором они у тебя есть. Все медиумы, которые могут прочитать твой код на расстоянии, в отпуске.
Вот тута до меня доперло в чем непонятка Пешу Code (Text): lea esi, tmp //в сырце Получаю Code (Text): lea esi, [tmp] //в листинге Пешу Code (Text): mov esi, tmp //в сырце И он не понимает что ему надо, тогда пишу Code (Text): db $BE dd tmp //в сырце и в листинге мы видим наше Code (Text): mov esi, tmp //в листинге Сорьки что немного запутал. Но вот с EAX, пока совсем не пойму „В действительности всё не так, как на самом деле.“ — Станислав Ежи Лец
Во !!! точно Code (Text): mov esi, offset(tmp) То что надо !!! Да почти все как в оригинале, только скопировал процедуру и добавил цифру 2 в имя. И стал править. Code (Text): Const tmp:array[0..3] of Cardinal = ($67452301,$EFCDAB89,$98BADCFE,$10325476); function MD5Buffer2(const Buffer; Size: Cardinal): TMD5Digest; var Context : TMD5Context; bits: array[0..2] of Cardinal; index, padLen: Cardinal; begin //InitContext // Context.state := tmp; asm lea edi, Context mov esi, offset(tmp) movsd movsd movsd movsd // xor eax, eax // push eax // pop eax mov ecx, 18 rep stosd end; MD5Update(Context, @buffer, Size); // Вот это поменял bits[0] := Context.count[0]; bits[1] := Context.count[1]; //Вот это тож, ну там очень тупо было, хотя это только первые наброски. index := Context.count[0] shr 3 and $3F; if index < 56 then padLen := 56 - index else padLen := 120 - index; MD5Update(Context, @PADDING, padLen); MD5Update(Context, @Bits, 8); Result.z :=Context.state; end; AV то получаю в строке FF(c, d, a, b, Buffer[14], S13, $A679438E); Я бы запостил весь сырец, но у меня счас только GPRS... Сырец нашел где-то тута: http://koders.com/default.aspx?s=MD5Buffer&la=Delphi&li=%2A&scope=&search.x=2&search.y=4
Shooshpanchik Push+pop не "могет", а вот xor eax, eax - запросто, если компилятор не сообразит перед асм-вставкой сохранить регистр eax, в котором в функцию передается указатель Buffer, и соотв-но в MD5Update будет передан нулевой указатель И вообще asm-вставки в дельфях - это источник глюков, т.к. компилятор не всегда усекает изменение регистров в асм-вставке и соотв-но не гарантирует их сохранение\восстановление. Поэтому лучше юзать не вставки, а законченные асм-функции, в которых ты сам должен отвечать за изменение, сохранение и восстановление регистров, не полагаясь на компилятор