Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Ошибка при вызове ReallocMem в ассемблере [D7, WinXP]


Страницы:   1 2 3 4

Mx ©   (2005-07-15 09:50:00) 

Написал две подпрограммы для работы с битами, обе ассемблерные. Первая возвращает значение бита по индексу, вторая - устанавливает, а если надо, и расширяет диапазон. Последнее производится засчет 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

Спасибо.


Defunct   (2005-07-17 15:52:00) [41]

> Mx

хм.. если на асме требуется сделать вызов какой-то делфишной функции, то грош цена такой асмовской встравке.


Mx   (2005-07-15 19:35:00) [42]

Да, все работает. Процедурку SetBit я переписал на Delphi'йском, а GetBit сделал как Q_BitTest (thanks Amoeba).

Всем спасибо!


Anatoly Podgoretsky   (2005-07-15 19:22:00) [43]

Mx ©   (15.07.05 16:54) [17]
Ты не книге верь, а документации Интел, этот диапазон 2^31


begin...end   (2005-07-15 18:40:00) [44]

> Mx ©   (15.07.05 18:38) [28]

Это не -231 ... 230. Это -2^31 ... 2^31 - 1.


Mx   (2005-07-15 18:38:00) [45]

А как быть с диапазоном, превышающим -231 -- 230 ?


begin...end   (2005-07-15 18:24:00) [46]

> Mx

Обратите внимание на [24]. Автор [16] был прав.


begin...end   (2005-07-15 17:53:00) [47]

> DiamondShark ©   (15.07.05 17:43) [24]

Спасибо.

> Mx ©   (15.07.05 17:43) [25]
> Перед ReallocMem в EAX лежит адрес переменной Buffer.

Если, говоря "адрес буфера", Вы имели в виду адрес переменной Buffer, то Вы правы.
Однако, по-моему, под буфером логичнее понимать область памяти, на которую указываетBuffer.


Mx   (2005-07-15 17:43:00) [48]


> 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 бред написан, адрес, который
> ты, якобы, вычислил указывает на деревню дедушке. Соответственно,
> команда учтановки бита лезет чёрт-те куда.

Согласен, исправил, работает.


DiamondShark   (2005-07-15 17:43:00) [49]


> 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


begin...end   (2005-07-15 17:38:00) [50]

> Mx ©   (15.07.05 17:20) [20]
> Ну. Я не утверждаю обратного...

Нет, Вы утверждаете обратное. В [17] Вы пишете: "Перед вызовом в нем адрес буфера". На самом деле это не так.


DiamondShark   (2005-07-15 17:38:00) [51]


> Ошибка не в вызове ReallocMem, а при установке/сбросе бита

Дык.
У тебя после вызова ReallocMem бред написан, адрес, который ты, якобы, вычислил указывает на деревню дедушке. Соответственно, команда учтановки бита лезет чёрт-те куда.


begin...end   (2005-07-15 17:34:00) [52]

> Mx ©   (15.07.05 16:54) [17]

> Вот читаю из книги про процы, так там второй параметр
> BTx должен быть в диапазоне 0..31. Следовательно
> больше Integer'а с ними не поработаешь.

> Если, конечно, верить книге.

Книге нужно верить.
Если второй параметр будет больше 31, то он будет изменён на остаток от деления на 32. Например, если параметр равен 32 или 64, то будет взведён нулевой бит.


Mx   (2005-07-15 17:20:00) [53]


> 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:04:00) [54]

> Mx ©   (15.07.05 16:54) [17]
> В какой момент? Перед вызовом в нем адрес буфера.

Это же var-параметр...


Digitman   (2005-07-15 17:03:00) [55]


> Можно, конечно, еще Count запоминать


почему бы и нет ?


> Если положиться на компилятор, то как тогда? Через сдвиги?


а посмотри внимательно на код, генерируемый компилятором при проверке на вхождение эл-та во множество и модификации множества !

там идет та же работа с битовым массивом и используются те же BT/BTS/BTR


Mx   (2005-07-15 16:54:00) [56]


> 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, каждый раз конструировать его экземпляры, ждать проверки вхождения индекса в диапазон. Если можно этого избежать, то почему бы не воспользоваться.


Amoeba   (2005-07-15 13:02:00) [57]


> Mx ©   (15.07.05 10:45) [3]
>
> > Amoeba ©
>
> Такие процедуры всего лишь проверяют бит в пределах одного
> байта. У меня же бит может иметь индекс свыше 31, плюс автоматически
> выделяется память. Мне это надо делать в нескольких местах
> и заниматься выделением памяти и определением индекса байта
> каждый раз мне не хочется.


Вы здесь не правы, поверьте моему опыту использования этих процедур. Они работают с байтовыми массивами любой длины. Так что индекс может быть намного большим чем 31. И не надо определять никакие индексы байтов.


Digitman   (2005-07-15 12:17:00) [58]


> Anatoly Podgoretsky ©   (15.07.05 11:52) [14]


> Смею предположить, что лучше


возможно и лучше


> Mx


вот ты за производительность своего алгоритма заботишься, а сам при этом делаешь заведомо дурной в этом плане ход : при установке бита по делу и без дела вызываешь ReallocMem()


Anatoly Podgoretsky   (2005-07-15 11:52:00) [59]

Digitman ©   (15.07.05 11:41) [13]
Смею предположить, что лучше. Приходилось сталкиваться с переводами на АСМ, с виду нормальными, кроме скорости, по сравнению с Паскаль версией.


Digitman   (2005-07-15 11:41:00) [60]


>  а требуется и память экономить


для порядка, равного сотням (и даже тысячам), экономия эта - мизерная


> и время


основное время в твоем коде и аналогах в TBits так или иначе приходится на выполнение "тяжелых" инструкций BT/BTS/BTR

все прочее же дан.случае компилятор оптимизирует, поверь, ничуть не хуже тебя


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо