Вопрос такой: есть понятия "прямой" и "обратный" порядок байт. Как их переставить местами, скажем для типа Integer. Т.е. 1-й байт должен стоять на 4-месте и т.д. Swap для Integer не помогает.
Я подумал, написал вот это:
function Invert(Value: integer): integer;
var src: array[0..3] of byte absolute Value;
dst: array[0..3] of byte absolute Result;
begin
dst[0] := src[3]; dst[1] := src[2];
dst[2] := src[1]; dst[3] := src[0];
end;
но насколько это правильно и быстро?
Есть ли возможность сделать это по другому, может быть быстрее?
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
28-04-2006 12:22
»вопрос КС №36581«, »вопрос КС №36673«.
А вообще, вы можете запускать одну процедуру не один, а несколько раз. Например,
OldTime:=GetTickCount;
For I:=1 to 1000000 do Z:=Func(...);
ShowMessage(inttostr(GetTickCount-OldTme));
Это сколько времени потрачено на миллион вызовов. Конечно, это число можно варьировать.
IntToStr(GetTickCount-n) всегда дает 0, причем для всех примеров. Означает ли это, что все они работают одинаково быстро?
Это значит, что для измерения столь малых промежутков времени ни GetTickCount, ни PerfomanceCounters не подходят, единственный способ, это мерить такты процессора:
function RDTSC:Int64;
asm
rdtsc;
end;
И что получается - код предложенный мной выполняется в 4 операции, а Маратом Сафиным - в 7. Означает ли это что мой код быстрее?
Это ничего не означает пока не задан конкретный процессор. Процессоры могут выполнять как несколько операций за такт, так и тратить несколько тактов на одну операцию.
Вот это почитайте: http://www.fastcode.dk/fastcodeproject/basmforbeginners/BASMForBeginners1.htm
function EndianLong(L: Integer):Integer;
begin
Result := Swap(L shr 16) OR (Integer(Swap(L and $ffff)) shl 16);
{
mov edx,eax
shr edx,$10
xchg dl,dh
and eax,$0000ffff
xchg al,ah
shl eax,$10
or edx,eax
mov eax,edx
}
end;
procedure TForm1.Button1Click(Sender: TObject);
var n,l: integer;
begin
l := 1000;
n := GetTickCount;
l := EndianLong(l);
ShowMessage(IntToStr(GetTickCount-n) + ' 1000 : '+IntToStr(l));
end;
function Invert(Value: integer): integer;
var src: array[0..1] of smallint absolute Value;
dst: array[0..1] of smallint absolute Result;
begin
dst[0] := Swap(src[1]); dst[1] := Swap(src[0]);
{
mov ax,[ebp-$02]
xchg al,ah
mov [ebp-$08],ax
mov ax,[ebp-$04]
xchg al,ah
mov [ebp-$06},ax
mov eax,[ebp-$08]
}
end;
procedure TForm1.Button2Click(Sender: TObject);
var n,l: integer;
begin
l := 1000;
n := GetTickCount;
l := Invert(l);
ShowMessage(IntToStr(GetTickCount-n) + ' 1000 : '+IntToStr(l));
end;
function SwapInt(X: integer): integer; assembler;
asm
bswap eax
{
здесь понятно
}
end;
procedure TForm1.Button3Click(Sender: TObject);
var n,l: integer;
begin
l := 1000;
n := GetTickCount;
l := SwapInt(l);
ShowMessage(IntToStr(GetTickCount-n) + ' 1000 : '+IntToStr(l));
end;
function Invert2(Value: integer): integer;
var src: array[0..3] of byte absolute Value;
dst: array[0..3] of byte absolute Result;
begin
dst[0] := src[3]; dst[1] := src[2];
dst[2] := src[1]; dst[3] := src[0];
{
mov al,[ebp-$01]
mov [ebp-$08],al
mov al,[ebp-$02]
mov [ebp-$07],al
}
end;
procedure TForm1.Button4Click(Sender: TObject);
var n,l: integer;
begin
l := 1000;
n := GetTickCount;
l := Invert2(l);
ShowMessage(IntToStr(GetTickCount-n) + ' 1000 : '+IntToStr(l));
end;
end.
В фигурных скобках привожу асемблерный код. Бесспорным лидером конечно является 3 вариант, за что Noskov большое спасибо.
Но я, как человек далекий от асемблера, хотел бы выяснить следующее:
IntToStr(GetTickCount-n) всегда дает 0, причем для всех примеров. Означает ли это, что все они работают одинаково быстро?
И что получается - код предложенный мной выполняется в 4 операции, а Маратом Сафиным - в 7. Означает ли это что мой код быстрее?
function Invert(Value: integer): integer;
var src: array[0..1] of smallint absolute Value;
dst: array[0..1] of smallint absolute Result;
begin
dst[0] := Swap(src[1]); dst[1] := Swap(src[0]);
end;
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.