3

To better explain what I'm trying to accomplish, I'm going to start with something that works.

Say we have a procedure that can call another procedure and pass a string parameter to it:

procedure CallSaySomething(AProc: Pointer; const AValue: string);
var
  LAddr: Integer;
begin
  LAddr := Integer(PChar(AValue));
  asm
    MOV EAX, LAddr
    CALL AProc;
  end;
end;

This is the procedure that we will call:

procedure SaySomething(const AValue: string);
begin
  ShowMessage( AValue );
end;

Now I can call SaySomething like so(tested and works (: ):

CallSaySomething(@SaySomething, 'Morning people!');

My question is, how can I achieve similar functionality, but this time SaySomething should be a method:

type
  TMyObj = class
  public
    procedure SaySomething(const AValue: string); // calls show message by passing AValue
  end;

so, if you're still with me..., my goal is to get to a procedure similar to:

procedure CallMyObj(AObjInstance, AObjMethod: Pointer; const AValue: string);
begin
  asm
    // here is where I need help...
  end;
end;

I've gave it quite a few shots, but my assembly knowledge is limited.

PhiS
  • 4,540
  • 25
  • 35
  • You can probably find your way by reading this [assemblersyntax document](http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/assemblersyntax_xml.html). But why bother, declare a `type TMyMethod = procedure (Const aValue : string) of Object;` and replace the pointer type in the `CallMyObj` and remove the `AObjectInstance`. Your call would then be as simple as `AObjMethod(AValue):`. – LU RD Feb 26 '12 at 13:23
  • @LURD this is a very simplistic way of describing what I'm trying to achieve, in the end, I'm going to call methods with unknown number of parameters and type of parameters, I have found a way around it tho... using the "TExec = procedure of Object;" hack and "PUSH DWORD PTR AValue;", thank you for the link –  Feb 26 '12 at 13:30

1 Answers1

4

what is the reason to use asm?

when you are calling objects method, then instance pointer have to be the first parameter in method call

program Project1;
{$APPTYPE CONSOLE}
{$R *.res}

uses System.SysUtils;
type
    TTest = class
        procedure test(x : integer);
    end;

procedure TTest.test(x: integer);
begin
    writeln(x);
end;

procedure CallObjMethod(data, code : pointer; value : integer);
begin
    asm
        mov eax, data;
        mov edx, value;
        call code;
    end;
end;

var t : TTest;

begin
    t := TTest.Create();
    try
        CallObjMethod(t, @TTest.test, 2);
    except
    end;
    readln;
end.
teran
  • 3,214
  • 1
  • 21
  • 30
  • thank you for the code, I've found one way thus far, your way is good too, the reason for using ASM, is because the "sample" code I've posted is minimalistic, in the end, I'm going to pass unknown number of parameters and type of parameter. –  Feb 26 '12 at 13:40
  • in RTTI `invoke()` method passes unknown number of parameters with unknown type using `array of TValue`. – teran Feb 26 '12 at 13:46
  • yes, but I want to avoid using RTTI, I want to use RTTI to grab information(at startup) and then use ASM to call methods. –  Feb 26 '12 at 13:54
  • P.S. if you've published method Test, then you can use LCode := t.MethodAddress('test'); and pass LCode in stead of @TTest.test –  Feb 26 '12 at 13:55