Как-то кривовато это всё выглядит. Что случится, если в процедуры будет передана нулевая длина? Кроме того, цикл в ассемблерной процедуре кажется выполняет на одну итерацию меньше, чем требуется. Ну и, если правильно путаю, инструкция LOOP дороговатая, её лучше избегать.
С учётом сказанного:
Код: Выделить всё
procedure Swap1(Len: ptrUInt; P1, P2: Pointer); assembler; nostackframe; inline;
asm
TEST RCX, RCX
JZ @Done
@L:
MOV AL,[RDX+RCX]
MOV BL,[R8+RCX]
MOV [RDX+RCX],BL
MOV [R8+RCX],AL
LOOP @L
@Done:
end;
Код: Выделить всё
procedure Swap2(Len: ptrUInt; P1, P2: Pointer); inline;
var
pb1: PByte absolute P1;
pb2: PByte absolute P2;
b: Byte;
I: ptrUInt;
begin
for I := 1 to Len do begin
b := pb1^;
pb1^ := pb2^;
pb2^ := b;
Inc(pb1);
Inc(pb2);
end;
end;
Код: Выделить всё
procedure Swap3(Len: ptrUInt; P1, P2: Pointer); assembler; nostackframe; inline;
asm
test rcx, rcx
jz @Done
@Loop:
dec rcx
mov al, [rdx+rcx]
mov bl, [r8+rcx]
mov [rdx+rcx], bl
mov [r8+rcx], al
jnz @Loop
@Done:
end;
Результат 5000000 прогонов на sizeof(shortstring):
А вообще-то, чтобы сравнивать сравнимое Swap2 должна выглядеть как-то так:
Код: Выделить всё
procedure Swap2(Len: ptrUInt; P1, P2: Pointer); inline;
var
pb1: PByte absolute P1;
pb2: PByte absolute P2;
b: Byte;
I: ptrUInt;
begin
if Len = 0 then exit;
for I := Len - 1 downto 0 do begin
b := pb1[I];
pb1[I] := pb2[I];
pb2[I] := b;
end;
end;
и тогда результат: