![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ошибка при вызове ReallocMem в ассемблере [D7, WinXP]
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
Спасибо.
DiamondShark (2005-07-15 11:39:00) [61]
> Каким образом? Что надо исправить?
Сохранять EAX перед вызовом @ReallocMem
Да и дальше фигня полная. EAX содержит не адрес буфера, а адрес адреса буфера.
А ты один уровень косвенности потерял.
Anatoly Podgoretsky (2005-07-15 11:37:00) [62]Mx © (15.07.05 11:27) [9]
Сохранять, остальные ты почему то сохраняешь.
Digitman (2005-07-15 11:34:00) [63]ADD EAX,ECX <- а здесь ты складываешь неизвестно что с новым адресом нового буфера
Mx (2005-07-15 11:27:00) [64]
> Anatoly Podgoretsky © (15.07.05 11:25) [7]
> Испорчен var Buffer [EAX]
Каким образом? Что надо исправить?
Mx (2005-07-15 11:26:00) [65]
> 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 нуль, а потом то нет! Но я не заметил. Пока сваливать надо, вечером отпишусь, что получилось.
Anatoly Podgoretsky (2005-07-15 11:25:00) [66]Испорчен var Buffer [EAX]
Sha (2005-07-15 11:12:00) [67]Вызываемая функция имеет право изменять содержимое eax, edx, ecx.
Digitman (2005-07-15 11:10:00) [68]..
CALL System.@ReallocMem
MOV ECX,EDX
POP EDX
ADD EAX,ECX
SUB EDX,ECX<- проблема здесь : из номера бита вычитаешь вирт.адрес
POP ECX
REA (2005-07-15 10:50:00) [69]А TBits не покатит?
Mx (2005-07-15 10:45:00) [70]
> Digitman ©
> пошаговую трассировку с контролем состояния РОН до и после
> вызова System.@ReallocMem делал ?
Делал. Перед вызовом в EAX адрес Buffer'а. После ReallocMem в EAX уже лежит значение этой переменной. К тому же обнуляется EDX, ввиду чего его приходится POP'ить. Но это мне, к сожалению, ни о чем не говорит.
> Amoeba ©
Такие процедуры всего лишь проверяют бит в пределах одного байта. У меня же бит может иметь индекс свыше 31, плюс автоматически выделяется память. Мне это надо делать в нескольких местах и заниматься выделением памяти и определением индекса байта каждый раз мне не хочется.
Amoeba (2005-07-15 10:20:00) [71]Не изобретай велосипед! Посмотри как это сделано в бибилотеке 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;
Digitman (2005-07-15 10:06:00) [72]пошаговую трассировку с контролем состояния РОН до и после вызова System.@ReallocMem делал ?