警告: 以下の回答は、尋ねられた質問に対応していますが、誰も使用しないことをお勧めします。丸めを別の方法で実行する場合Round
は、専用の関数を記述して呼び出します。
ランタイム コード フックを使用して、 の実装を変更できますRound
。
Round
しわは、組み込み関数であるため、関数のアドレスを取得するのが少し難しいことです。また、使用される呼び出し規約に従うように注意する必要があります。入力値は x87 スタック レジスタで渡されST(0)
、戻り値は 64 ビット整数ですEDX:EAX
。
方法は次のとおりです。
procedure PatchCode(Address: Pointer; const NewCode; Size: Integer);
var
OldProtect: DWORD;
begin
if VirtualProtect(Address, Size, PAGE_EXECUTE_READWRITE, OldProtect) then
begin
Move(NewCode, Address^, Size);
FlushInstructionCache(GetCurrentProcess, Address, Size);
VirtualProtect(Address, Size, OldProtect, @OldProtect);
end;
end;
type
PInstruction = ^TInstruction;
TInstruction = packed record
Opcode: Byte;
Offset: Integer;
end;
procedure RedirectProcedure(OldAddress, NewAddress: Pointer);
var
NewCode: TInstruction;
begin
NewCode.Opcode := $E9;//jump relative
NewCode.Offset :=
NativeInt(NewAddress)-NativeInt(OldAddress)-SizeOf(NewCode);
PatchCode(OldAddress, NewCode, SizeOf(NewCode));
end;
function System_Round: Pointer;
asm
MOV EAX, offset System.@Round
end;
procedure _ROUND;
asm
{ -> FST(0) Extended argument }
{ <- EDX:EAX Result }
// your implementation goes here
end;
initialization
RedirectProcedure(System_Round, @_ROUND);
自分のバージョンを asm よりも Pascal で実装したい場合は、非標準の呼び出し規約を_ROUND
Delphi の標準呼び出し規約に適合させる必要があります。このような:
function MyRound(x: Extended): Int64;
begin
// your implementation goes here
end;
procedure _ROUND;
var
x: Extended;
asm
{ -> FST(0) Extended argument }
{ <- EDX:EAX Result }
FSTP TBYTE PTR [x]
CALL MyRound
end;
ここでは、プログラムが 32 ビットをターゲットにしていると想定していることに注意してください。64 ビットをターゲットにする必要がある場合、原則はほとんど同じですが、詳細は明らかに異なります。