Форум: "Основная";
Текущий архив: 2005.08.21;
Скачать: [xml.tar.bz2];
ВнизОшибка при вызове ReallocMem в ассемблере Найти похожие ветки
← →
Mx © (2005-07-15 09:50) [0]Написал две подпрограммы для работы с битами, обе ассемблерные. Первая возвращает значение бита по индексу, вторая - устанавливает, а если надо, и расширяет диапазон. Последнее производится засчет ReallocMem, но че то не фурычит. Не могу понять. Интересно, что я протестил код некой _ReallocMem из System.pas (а не из GetMem.inc), так там тоже при вызове MemoryManager.ReallocMem происходит ошибка. А может я указываю адрес не той процедуры?
Исходный текст:function GetBit(Buffer: Pointer; Index: Integer): Boolean;
asm
MOV ECX,EDX
SAR ECX,3
ADD EAX,ECX
SUB EDX,ECX
BT [EAX],EDX
SETC Result
end;
procedure SetBit(var Buffer: Pointer; Index: Integer; Value: Boolean);
asm
PUSH ECX
PUSH EDX
SAR EDX,3
INC EDX
CALL System.@ReallocMem
MOV ECX,EDX
POP EDX
ADD EAX,ECX
SUB EDX,ECX
POP ECX
CMP CL,0
JE @@clr
@@set:
BTS [EAX],EDX
RET
@@clr:
BTC [EAX],EDX}
end;
procedure TForm1.FormCreate(Sender: TObject);
var
P: Pointer;
begin
P := nil;
try
SetBit(P, 1, True);
SetBit(P, 2, True); // ошибка возникает тут, при повторном вызове
SetBit(P, 8, True);
SetBit(P, 13, True);
SetBit(P, 12, True);
finally
FreeMem(P);
end;
end;
Ошибка: "всеми любимый" EAccessViolation
Спасибо.
← →
Digitman © (2005-07-15 10:06) [1]пошаговую трассировку с контролем состояния РОН до и после вызова System.@ReallocMem делал ?
← →
Amoeba © (2005-07-15 10:20) [2]Не изобретай велосипед! Посмотри как это сделано в бибилотеке QSrtings^
function Q_BitTest(P: Pointer; Index: Integer): Boolean;
asm
BT [EAX],EDX
SETC AL
end;
function Q_BitSet(P: Pointer; Index: Integer): Boolean;
asm
BTS [EAX],EDX
SETC AL
end;
function Q_BitReset(P: Pointer; Index: Integer): Boolean;
asm
BTR [EAX],EDX
SETC AL
end;
function Q_BitToggle(P: Pointer; Index: Integer): Boolean;
asm
BTC [EAX],EDX
SETC AL
end;
← →
Mx © (2005-07-15 10:45) [3]
> Digitman ©
> пошаговую трассировку с контролем состояния РОН до и после
> вызова System.@ReallocMem делал ?
Делал. Перед вызовом в EAX адрес Buffer"а. После ReallocMem в EAX уже лежит значение этой переменной. К тому же обнуляется EDX, ввиду чего его приходится POP"ить. Но это мне, к сожалению, ни о чем не говорит.
> Amoeba ©
Такие процедуры всего лишь проверяют бит в пределах одного байта. У меня же бит может иметь индекс свыше 31, плюс автоматически выделяется память. Мне это надо делать в нескольких местах и заниматься выделением памяти и определением индекса байта каждый раз мне не хочется.
← →
REA (2005-07-15 10:50) [4]А TBits не покатит?
← →
Digitman © (2005-07-15 11:10) [5]..
CALL System.@ReallocMem
MOV ECX,EDX
POP EDX
ADD EAX,ECX
SUB EDX,ECX <- проблема здесь : из номера бита вычитаешь вирт.адрес
POP ECX
← →
Sha © (2005-07-15 11:12) [6]Вызываемая функция имеет право изменять содержимое eax, edx, ecx.
← →
Anatoly Podgoretsky © (2005-07-15 11:25) [7]Испорчен var Buffer [EAX]
← →
Mx © (2005-07-15 11:26) [8]
> REA (15.07.05 10:50) [4]
> А TBits не покатит?
Придется хранить сотни экземпляров TBits, а требуется и память экономить (поэтому биты, а не массив Boolean) и время.
> Digitman © (15.07.05 11:10) [5]
> SUB EDX,ECX <- проблема здесь : из номера бита вычитаешь
> вирт.адрес
Оба! Я оставил MOV ECX,EDX после ReallocMem так, как при первом вызове EDX нуль, а потом то нет! Но я не заметил. Пока сваливать надо, вечером отпишусь, что получилось.
← →
Mx © (2005-07-15 11:27) [9]
> Anatoly Podgoretsky © (15.07.05 11:25) [7]
> Испорчен var Buffer [EAX]
Каким образом? Что надо исправить?
← →
Digitman © (2005-07-15 11:34) [10]ADD EAX,ECX <- а здесь ты складываешь неизвестно что с новым адресом нового буфера
← →
Anatoly Podgoretsky © (2005-07-15 11:37) [11]Mx © (15.07.05 11:27) [9]
Сохранять, остальные ты почему то сохраняешь.
← →
DiamondShark © (2005-07-15 11:39) [12]
> Каким образом? Что надо исправить?
Сохранять EAX перед вызовом @ReallocMem
Да и дальше фигня полная. EAX содержит не адрес буфера, а адрес адреса буфера.
А ты один уровень косвенности потерял.
← →
Digitman © (2005-07-15 11:41) [13]
> а требуется и память экономить
для порядка, равного сотням (и даже тысячам), экономия эта - мизерная
> и время
основное время в твоем коде и аналогах в TBits так или иначе приходится на выполнение "тяжелых" инструкций BT/BTS/BTR
все прочее же дан.случае компилятор оптимизирует, поверь, ничуть не хуже тебя
← →
Anatoly Podgoretsky © (2005-07-15 11:52) [14]Digitman © (15.07.05 11:41) [13]
Смею предположить, что лучше. Приходилось сталкиваться с переводами на АСМ, с виду нормальными, кроме скорости, по сравнению с Паскаль версией.
← →
Digitman © (2005-07-15 12:17) [15]
> Anatoly Podgoretsky © (15.07.05 11:52) [14]
> Смею предположить, что лучше
возможно и лучше
> Mx
вот ты за производительность своего алгоритма заботишься, а сам при этом делаешь заведомо дурной в этом плане ход : при установке бита по делу и без дела вызываешь ReallocMem()
← →
Amoeba © (2005-07-15 13:02) [16]
> Mx © (15.07.05 10:45) [3]
>
> > Amoeba ©
>
> Такие процедуры всего лишь проверяют бит в пределах одного
> байта. У меня же бит может иметь индекс свыше 31, плюс автоматически
> выделяется память. Мне это надо делать в нескольких местах
> и заниматься выделением памяти и определением индекса байта
> каждый раз мне не хочется.
Вы здесь не правы, поверьте моему опыту использования этих процедур. Они работают с байтовыми массивами любой длины. Так что индекс может быть намного большим чем 31. И не надо определять никакие индексы байтов.
← →
Mx © (2005-07-15 16:54) [17]
> DiamondShark © (15.07.05 11:39) [12]
> EAX содержит не адрес буфера, а адрес адреса буфера.
В какой момент? Перед вызовом в нем адрес буфера. После вызова его значение становится равным этому буферу, т.е. тому, что запишется в Buffer. Только что специально проверил.
> Amoeba © (15.07.05 13:02) [16]
Вот читаю из книги про процы, так там второй параметр BTx должен быть в диапазоне 0..31. Следовательно больше Integer"а с ними не поработаешь. Конечно, можно указатель увеличивать, но разницы никакой. Конкретно каждая процедура больше чем в 32-х битах ничего не изменит. Если, конечно, верить книге.
> Digitman © (15.07.05 12:17) [15]
> вот ты за производительность своего алгоритма заботишься,
> а сам при этом делаешь заведомо дурной в этом плане ход
> : при установке бита по делу и без дела вызываешь ReallocMem()
Есть альтернатива? Можно, конечно, еще Count запоминать.
Если положиться на компилятор, то как тогда? Через сдвиги? Насчет TBits, каждый раз конструировать его экземпляры, ждать проверки вхождения индекса в диапазон. Если можно этого избежать, то почему бы не воспользоваться.
← →
Digitman © (2005-07-15 17:03) [18]
> Можно, конечно, еще Count запоминать
почему бы и нет ?
> Если положиться на компилятор, то как тогда? Через сдвиги?
а посмотри внимательно на код, генерируемый компилятором при проверке на вхождение эл-та во множество и модификации множества !
там идет та же работа с битовым массивом и используются те же BT/BTS/BTR
← →
begin...end © (2005-07-15 17:04) [19]> Mx © (15.07.05 16:54) [17]
> В какой момент? Перед вызовом в нем адрес буфера.
Это же var-параметр...
← →
Mx © (2005-07-15 17:20) [20]
> Digitman © (15.07.05 17:03) [18]
> там идет та же работа с битовым массивом и используются
> те же BT/BTS/BTR
Значит альтернативы нет. Count я думаю все же ввиду.
> begin...end © (15.07.05 17:04) [19]
> Это же var-параметр...
Ну. Я не утверждаю обратного, но после вызова ReallocMem в EAX"е лежит значение Buffer"а (значение указателя P в методе TForm1.FormCreate), а не адрес адреса, как написано в [12].
Да, глубоко перед всеми извиняюсь! Название темы не совсем корректно. Ошибка не в вызове ReallocMem, а при установке/сбросе бита (думал в тот момент о Realloc"е, вот и чиркнул машинально). Так что проблема именно в определении его индекса.
← →
begin...end © (2005-07-15 17:34) [21]> Mx © (15.07.05 16:54) [17]
> Вот читаю из книги про процы, так там второй параметр
> BTx должен быть в диапазоне 0..31. Следовательно
> больше Integer"а с ними не поработаешь.
> Если, конечно, верить книге.
Книге нужно верить.
Если второй параметр будет больше 31, то он будет изменён на остаток от деления на 32. Например, если параметр равен 32 или 64, то будет взведён нулевой бит.
← →
DiamondShark © (2005-07-15 17:38) [22]
> Ошибка не в вызове ReallocMem, а при установке/сбросе бита
Дык.
У тебя после вызова ReallocMem бред написан, адрес, который ты, якобы, вычислил указывает на деревню дедушке. Соответственно, команда учтановки бита лезет чёрт-те куда.
← →
begin...end © (2005-07-15 17:38) [23]> Mx © (15.07.05 17:20) [20]
> Ну. Я не утверждаю обратного...
Нет, Вы утверждаете обратное. В [17] Вы пишете: "Перед вызовом в нем адрес буфера". На самом деле это не так.
← →
DiamondShark © (2005-07-15 17:43) [24]
> begin...end © (15.07.05 17:34) [21]
Вообще-то, всё немного не так.
BTS—Bit Test and Set
Description
Selects the bit in a bit string (specified with the first operand, called the bit base) at the bitposition
designated by the bit offset operand (second operand), stores the value of the bit in the
CF flag, and sets the selected bit in the bit string to 1. The bit base operand can be a register or
a memory location; the bit offset operand can be a register or an immediate value. If the bit base
operand specifies a register, the instruction takes the modulo 16 or 32 (depending on the register
size) of the bit offset operand, allowing any bit position to be selected in a 16- or 32-bit register,
respectively (see Figure 3-1). If the bit base operand specifies a memory location, it represents
the address of the byte in memory that contains the bit base (bit 0 of the specified byte) of the
bit string (see Figure 3-2). The offset operand then selects a bit position within the range −231 to
231 − 1 for a register offset and 0 to 31 for an immediate offset.
IA-32 Intel® Architecture
Software Developer’s
Manual
Volume 2A:
Instruction Set Reference, A-M
← →
Mx © (2005-07-15 17:43) [25]
> begin...end © (15.07.05 17:38) [23]
> Нет, Вы утверждаете обратное. В [17] Вы пишете: "Перед вызовом
> в нем адрес буфера". На самом деле это не так.
А что же? Перед ReallocMem в EAX лежит адрес переменной Buffer. Об этом я написал еще в [3]. То, что Buffer эквивалентен P подразумевается само собой. Перед первым вызовом SetBit в @P дает тоже число, что и EAX в SetBit. После SetBit, EAX = P.
> DiamondShark © (15.07.05 17:38) [22]
> Дык.
> У тебя после вызова ReallocMem бред написан, адрес, который
> ты, якобы, вычислил указывает на деревню дедушке. Соответственно,
> команда учтановки бита лезет чёрт-те куда.
Согласен, исправил, работает.
← →
begin...end © (2005-07-15 17:53) [26]> DiamondShark © (15.07.05 17:43) [24]
Спасибо.
> Mx © (15.07.05 17:43) [25]
> Перед ReallocMem в EAX лежит адрес переменной Buffer.
Если, говоря "адрес буфера", Вы имели в виду адрес переменной Buffer, то Вы правы.
Однако, по-моему, под буфером логичнее понимать область памяти, на которую указывает Buffer.
← →
begin...end © (2005-07-15 18:24) [27]> Mx
Обратите внимание на [24]. Автор [16] был прав.
← →
Mx © (2005-07-15 18:38) [28]А как быть с диапазоном, превышающим -231 -- 230 ?
← →
begin...end © (2005-07-15 18:40) [29]> Mx © (15.07.05 18:38) [28]
Это не -231 ... 230. Это -2^31 ... 2^31 - 1.
← →
Anatoly Podgoretsky © (2005-07-15 19:22) [30]Mx © (15.07.05 16:54) [17]
Ты не книге верь, а документации Интел, этот диапазон 2^31
← →
Mx © (2005-07-15 19:35) [31]Да, все работает. Процедурку SetBit я переписал на Delphi"йском, а GetBit сделал как Q_BitTest (thanks Amoeba).
Всем спасибо!
← →
Defunct © (2005-07-17 15:52) [32]> Mx
хм.. если на асме требуется сделать вызов какой-то делфишной функции, то грош цена такой асмовской встравке.
← →
TProgrammer (2005-07-31 23:28) [33]
> Defunct © (17.07.05 15:52) [32]
> хм.. если на асме требуется сделать вызов какой-то делфишной
> функции, то грош цена такой асмовской встравке.
ИМХО вставлять не забывай, когда бред постишь.
← →
Alex Konshin © (2005-08-01 00:10) [34]Во-первых, класс для битовых массивов есть в VCL, по-моему называется TBits.
Не помню, чем он мне не понравился и я тоже написал свой. Смотри в юните Arrays у меня на сайте.
← →
Defunct © (2005-08-01 02:28) [35]TProgrammer (31.07.05 23:28) [33]
Старый знакомый нарисовался.
Все свои посты применяй сперва к себе.
В моем же посте, я не вижу ни капли бреда, и imho ставить на прописные истины не обязан.
← →
TProgrammer (2005-08-01 16:46) [36]
> В моем же посте, я не вижу ни капли бреда, и imho ставить
> на прописные истины не обязан.
Ну если ты его не видишь, это не значит что его там нет. И пойди расскажи свои прописные истины программистам Borland"a, которые к твоим "истинам" не особо не прислушивались когда писали VCL. Ты же видел хоть раз исходники VCL ?
← →
Defunct © (2005-08-02 01:26) [37]TProgrammer (01.08.05 16:46) [36]
> Ты же видел хоть раз исходники VCL ?
Нет, не видел. И какое отношение программисты Borland имеют к прописным истинам?
Как твой проект? Позволю себе напомнить.
Выдержка из нашего с тобой последнего разговора:
> 3. Пишу. Большое и серьезное. И со мной это делает 12 человек - поэтому когда мне нужно убрать форму, это значит мне нужно убрать форму - потому как проектированием этого проекта занимаюсь не я.
12 "профи" пишут что-то большое и серьезное, и все 12 "профи" сошлись на выводе, что надо делать через ж...
Конечно я помню, что ты любитель решать все через одно место, и поэтому пусть будет по-твоему. Делай в своих асм вставках вызовы дельфишных процедур, можешь даже вызовы васиковых процедур делать, меня это нисколько не беспокоит. Делай как хочешь. Убирай форму там где ее можно и не создавать. Твое дело.
ps: заполни анкету.
← →
Mx © (2005-08-02 01:57) [38]Ээээ, а к чему темку-то подняли? Чтоб поругаться?
← →
TProgrammer (2005-08-02 02:04) [39]
> Нет, не видел. И какое отношение программисты Borland имеют
> к прописным истинам?
Оно и видно, что не видел. Потому как половина функций из модуля SysUtils, используют в ассемблерных вставках вызовы дельфийских функций. Видимо программисты Borland тоже все делают через ж... Как же им не хватает великого мастера Defunct"a который бы показал им путь во тьме.
> Как твой проект?
Спасибо, хорошо. Месяц как сдали.
> Позволю себе напомнить.
> Выдержка из нашего с тобой последнего разговора:
Приятно видеть, что ты бережно хранишь все свои диалоги. На ночь не перечитываешь ?
> меня это нисколько не беспокоит.
Если не беспокоит - то что ж ты тогда полез-то ? Скучно было ?
> ps: заполни анкету.
Уже бегу.
← →
Defunct © (2005-08-02 10:56) [40]TProgrammer (02.08.05 02:04) [39]
> Потому как половина функций из модуля SysUtils, используют в ассемблерных вставках вызовы дельфийских функций.
Правда? А с каких это пор модуль SysUtils стал входить в состав VCL? И второе попробуй найди в модуле SysUtils хотя бы один вызов delphiшной функции, а не ассемблерной вставки.
> На ночь не перечитываешь ?
нет, просто злопамятный.
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2005.08.21;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.036 c