program Lambda;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
function GetRBP: Pointer; assembler;
asm
.NOFRAME
mov rax, rbp // - тут получаем текущую базу локальных переменных
// ret
// mov r8, rdx
// mov rdx, rcx
// mov rbp, [RIP+0]
// jmp [RIP+0]
// mov rcx, $ffffffffffffffff
end;
function l3LocalStubPrim(aRBP: Pointer; anAction: Pointer): Pointer;
{$WriteableConst On}
const
StubCode : array [0 .. 29 + 8] of Byte = (
$49, $89, $D0, // mov r8, edx // - у глобальной процедуры параметры передаются через ecx, edx
$48, $89, $CA, // mov edx, ecx // а у локальной через edx, r8
$48, $B9, // mov rcx, 0000000000000000 // - в rcx - база
$00, $00, $00, $00, $00, $00, $00, $00,
$FF, $25, $00, $00, $00, $00, // jmp [RIP+0] // - тут переход на anAction
$00, $00, $00, $00, $00, $00, $00, $00
, $00, $00, $00, $00, $00, $00, $00, $00
); // StubCode
begin
Move(aRBP, StubCode[8], SizeOf(aRBP)); // - конкретное значение rbp
Move(anAction, StubCode[22], SizeOf(anAction)); // - конкретное значение anAction
Result := @StubCode;
end;
function l3LocalStub(anAction: Pointer): Pointer; assembler;
asm
.NOFRAME
call GetRBP
mov rdx, rcx
mov rcx, rax
jmp l3LocalStubPrim
//call l3LocalStubPrim
end;
type
TProc1 = procedure (A: Integer);
TProc2 = procedure (A: Integer; B: Integer);
procedure Call1(aProc: TProc1);
begin
aProc(12345);
end;
procedure Call2(aProc: TProc2);
begin
aProc(12345, 789);
end;
procedure Test;
var
l_S : String;
procedure Local1(aStr: Integer);
var
l_S1 : String;
l_S2 : String;
begin
l_S1 := 'YYY';
l_S2 := l_S + l_S1;
l_S2 := l_S2 + IntToStr(aStr);
WriteLn(l_S2);
end;
procedure Local2(A: Integer; B: Integer);
begin
WriteLn(A);
WriteLn(B);
end;
var
l_RBP : NativeUInt;
l_P : Pointer;
begin
l_RBP := NativeUInt(GetRBP);
l_S := 'XXX';
Local1(10);
Local2(10, 0);
Call1(l3LocalStubPrim(GetRBP, @Local1));
Call1(l3LocalStub(@Local1));
Call2(l3LocalStubPrim(GetRBP, @Local2));
Call2(l3LocalStub(@Local2));
ReadLn;
end;
begin
try
Test;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.