Search code examples
delphiinline-assemblybasm

Create class instance using Delphi inline assembler


What I would like to do is, using assembly, create a class instance, call one of it's methods and then free the instance.

I know I'm missing something very important and probably very simple, but I don't know what.

program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TSomeClass = class(TObject)
  private
    FCreateDateTime: string;
  public
    constructor Create;
    procedure SayYeah;
  end;

constructor TSomeClass.Create;
begin
  FCreateDateTime := DateTimeToStr(Now);
end;

procedure TSomeClass.SayYeah;
begin
  Writeln('yeah @ ' + FCreateDateTime);
end;

procedure Doit;
asm
  CALL TSomeClass.Create; // <= Access Violation
  CALL TSomeClass.SayYeah;
  CALL TSomeClass.Free;
end;

begin
  try
    Doit;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

FYI: I want to understand how I can achieve this at low level, not another way of doing it.

UPDATE:

Thanks to Andreas Rejbrand, I've managed to find the culprit:

Update2:

Thanks to Arnaud for finding flaw using EBX, rather than PUSH/POP EAX

var
  TSomeClass_TypeInfo: Pointer;

procedure Doit;
asm
  MOV DL, $01;
  MOV EAX, TSomeClass_TypeInfo;
  CALL TSomeClass.Create;
  PUSH EAX;
  CALL TSomeClass.SayYeah; // call method
  POP EAX;
  MOV DL, $01;
  CALL TSomeClass.Free; // pointer to instance(Self) is expected in EAX
end;

begin
  TSomeClass_TypeInfo := TSomeClass;
  try
    Doit;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

Solution

  • You can read about this in an excellent guide to Delphi assembly programming, originally found here. Unfortunately, the site is down, but you can find an archived version here. Look in particular at page 5.