The function you are looking at is
procedure XorMem(var Mem1; const Mem2; Count : Cardinal); register;
from the ogutil
unit.
Personally I would not bother converting this to x64 assembler. There are quite a few tricky details that you need to get right in order to do so. It makes more sense to me to port to Pascal and let the compiler deal with the details. The simplest most naive translation looks like this:
procedure XorMem(var Mem1; const Mem2; Count: Cardinal);
var
p1, p2: PByte;
begin
p1 := PByte(@Mem1);
p2 := PByte(@Mem2);
while Count>0 do
begin
p1^ := p1^ xor p2^;
inc(p1);
inc(p2);
dec(Count);
end;
end;
If this is performance critical then you'd want to unroll the loop a little to operate on large operands. Say 32 bit operands on x86 and 64 bit operands on x64.
A version that operated on 32 bit operands might look like this:
procedure XorMem(var Mem1; const Mem2; Count: Cardinal);
var
p1, p2: PByte;
begin
p1 := PByte(@Mem1);
p2 := PByte(@Mem2);
while Count>3 do
begin
PCardinal(p1)^ := PCardinal(p1)^ xor PCardinal(p2)^;
inc(p1, 4);
inc(p2, 4);
dec(Count, 4);
end;
while Count>0 do
begin
p1^ := p1^ xor p2^;
inc(p1);
inc(p2);
dec(Count);
end;
end;
Actually, you can easily enough write a version that automatically uses 32 or 64 bit operands as determined by the compilation target. The trick is to use the NativeUInt
type which is machine word size.
procedure XorMem(var Mem1; const Mem2; Count: Cardinal);
var
p1, p2: PByte;
begin
p1 := PByte(@Mem1);
p2 := PByte(@Mem2);
while Count>SizeOf(NativeUInt)-1 do
begin
PNativeUInt(p1)^ := PNativeUInt(p1)^ xor PNativeUInt(p2)^;
inc(p1, SizeOf(NativeUInt));
inc(p2, SizeOf(NativeUInt));
dec(Count, SizeOf(NativeUInt));
end;
while Count>0 do
begin
p1^ := p1^ xor p2^;
inc(p1);
inc(p2);
dec(Count);
end;
end;
This final version is pretty efficient when compiled with optimisations enabled. I would not look beyond that final Pascal version.