Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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 &#8722;231 to
231 &#8722; 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
14-1122718012
Ajax
2005-07-30 14:06
2005.08.21
Экспоненциальное усреднение


1-1122683948
Alexandr+
2005-07-30 04:39
2005.08.21
Как самое простое преобразовать Хтмл в чистый текст?


1-1122394424
Logan
2005-07-26 20:13
2005.08.21
Как сделать чтобы при загрузке текста в ричидит, текст не менялся


10-1100068864
AlexGof
2004-11-10 09:41
2005.08.21
1С как OLE не работает из Web-приложения работающего на IIS ?


14-1122469608
oldman
2005-07-27 17:06
2005.08.21
Вот и к нам пришла жара...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский