Вероятно, проще всего сосредоточиться на том, что делает версия x86:
function GetVersionizedPointer(var PointerStorage: TVersionizedPointerStorage): PVersionizedPointer;
const
vp_size = sizeof(TVersionizedPointer);
asm
add EAX, vp_size - 1
and EAX, not(vp_size - 1)
end;
ABI x86 означает, что адрес PointerStorage
передается в функцию в EAX
. Возвращаемое значение, другой адрес, также возвращается в EAX
. Это знание позволяет нам понять, что делает функция, и позволяет нам писать это так: Pascal:
function GetVersionizedPointer(var PointerStorage: TVersionizedPointerStorage): PVersionizedPointer;
var
Address: NativeUInt;
begin
Address := NativeUInt(@PointerStorage);
Address := Address + (SizeOf(TVersionizedPointer) - 1);
Address := Address and not (SizeOf(TVersionizedPointer) - 1);
Result := PVersionizedPointer(Address);
end;
Я написал это довольно многословно, чтобы прояснить, что делает каждый шаг. Переменной адреса присваивается адрес PointerStorage
, и поэтому он играет ту же роль, что и EAX
в исходной версии.
Сделайте вашу жизнь проще в будущем, используя эту чистую версию Pascal, и потеря кода ассемблера.