![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как использовать movups в Asm в Delphi ? [D7, WinXP]
Anton © (2007-12-09 02:58:00)Как средствами Дельфи можно выравнивать массив на 16 байт?
Для увеличения скорости програмы сделал asm всавку, но на невыровненных по 16 байт массивах могу использовать только movups, а хочется использовать movaps.
@!!ex (2007-12-11 09:38:00) [1]> [0] Anton (09.12.07 02:58)
разница между этими командами минимальна. Больше потеряешь выравнивая поля.
Лично я пользуюсь movUps и горя не знаю. ;)
DiamondShark (2007-12-10 13:53:00) [2]Прямо клуб телепатов.
А посмотреть в Instruction Set Reference с каким типом данных работают упомянутые инструкции -- это ниже своего достоинства.
Юрий Зотов (2007-12-10 09:47:00) [3]> Сергей М. © (10.12.07 09:39) [9]
> умудриться вызвать исключение при пересылке действительно можно
И легко. Если, например, пересылать произвольную частьмассива с НЕвыравненными элементами.
Сергей М. (2007-12-10 09:39:00) [4]
> Юрий Зотов © (10.12.07 09:27) [8]
Речь идет конкретно о сабжевых маш.инструкциях.
Они требуют выравнивание операндов на сабжевую границу.
Операндами являются нач.адреса блоков памяти.
За содержимое же блока памяти, на которую ссылается операнд-источник, отвечает сам программист - процессору оно по барабану.
Хотя умудриться вызвать исключение при пересылке действительно можно, если ожидаемая структура данных в блоке-источнике не соответствует ожидаемой процессором.
Юрий Зотов (2007-12-10 09:27:00) [5]> Сергей М. © (10.12.07 09:21) [7]
Однако же, сами по себе элементы массива на 16-байтовую границу тоже не выровняются, какой-то фокус для этого все же нужен. Isn't it?
Сергей М. (2007-12-10 09:21:00) [6]
> надо же еще и все элементы массива выровнять
Это надо еще умудриться напортачить с выравниванием внутри самого массива)
Юрий Зотов (2007-12-10 09:04:00) [7]Народ, получить кусок памяти по адресу, кратному 16 - это только одна часть вопроса. Но надо же еще и все элементымассива выровнять.
Сергей М. (2007-12-10 09:00:00) [8]
> Anton (09.12.07 02:58)
Аллокируй память под массив средствами менеджера в составе msvcrXX.dll - там выравнивание как раз 16-байтное.
Pavia (2007-12-10 08:56:00) [9]Предлогаю использовать следующии две процедуры.
procedure GetMemA16(var p:Pointer; Size:Integer);
var t:Pointer;
i:Integer;
begin
GetMem(t,Size+16);
i:=((DWord(t) div 16)+1)*16;
p:=Pointer(i);
DWord(Pointer(DWord(p)-4)^):=DWord(t);
end;
procedure FreeMemA16(p:Pointer);
begin
if p<> nil then p:=Pointer(Pointer(DWord(p)-4)^);
FreeMem(p);
end;
guav (2007-12-09 12:53:00) [10]Если выделять через VirtualAlloc, то данные будут выровнены на границу страницы памяти (это больше чем 16 байт). Однако выделение там тоже постраничное, потому неэффективно выделять таким образом небольшие объёмы. Если массив достаточчно большой, то использовать VirtualAlloc/VitrualFree - самое простое решение.
Юрий Зотов (2007-12-09 08:55:00) [11]Вот искусственный способ выравнивания самого массива и его элементов на 16 байт. Работает независимо от директив компилятора, но я совершенно не уверен, что в этом способе есть практический смысл. Это решайте сами.
const
LowArrayIndex = 0;
HighArrayIndex = 99;
type
TArrayElementType = Integer;
TElementRecord = packed record
Element: TArrayElementType;
Dummy: packed array[1..(16 - SizeOf(TArrayElementType))] of byte;
end;
TArray = packed array[LowArrayIndex..HighArrayIndex] of TElementRecord;
PArray = ^TArray;
TArrayContainer = packed record
Offset: packed array[1..16] of byte;
Data: TArray;
end;
var
ArrayContainer: TArrayContainer;
PData: PArray;
procedure TForm1.FormCreate(Sender: TObject);
begin
PData := PArray(@ArrayContainer);
while (Cardinal(PData) mod $10) <> 0 do
PData := PArray(Cardinal(PData) + 1);
Caption := IntToHex(Cardinal(PData), 8);
end;
Юрий Зотов (2007-12-09 07:38:00) [12]Выравнивание в D7 - максимум на 8 байт. Возможно, в более современных версиях есть и на 16 (посмотрите директиву компилятора {$A}).