[Back to MEMORY SWAG index]  [Back to Main SWAG index]  [Original]


PROGRAM Tst_VMT;

Type   TAObject = object
                   constructor Init;
                   procedure   MethodA; virtual;
                   procedure   MethodB; virtual;
                  end;
Type   TBObject = object(TAObject)
                   procedure   MethodA; virtual;
                  end;

Var    MethodAOffsetInVMT,
       MethodBOffsetInVMT  : integer;
       ItIsAObject         : TAObject;
       ItIsBObject         : TBObject;

{--- TAObject -------------------------------------------------------}

Constructor TAObject.Init;

Begin
End;

{--------------------------------------------------------------------}

Procedure TAObject.MethodA;

Begin
    Writeln('It is method A !!!');
End;

{--------------------------------------------------------------------}

Procedure TAObject.MethodB;

Begin
    Writeln('It is method B !!!');
End;

{--- TAObject -------------------------------------------------------}

Procedure TBObject.MethodA;

Begin
    Writeln('It is method A (some changed) !!!');
End;

{--------------------------------------------------------------------}

Function GetOffsetInVMT(VMTAddr : pointer; MethodAddr : pointer): integer;

Type   TAddrRec       = record  Offs,Segm : word  end;

Const  VMTHeaderSize  = 8;     { This is a size of VMT header     }
       MaxMethodsOffs = 100 * SizeOf(pointer) + VMTHeaderSize;
                       { Maximal offset of method in VMT (abstract) }

Var    VMTOffs        : word;
       CurAddr        : ^pointer;

Begin
    VMTOffs := VMTHeaderSize;
    While (VMTOffs < MaxMethodsOffs) and
          (pointer( Ptr(TAddrRec(VMTAddr).Segm,
                        TAddrRec(VMTAddr).Offs + VMTOffs)^
                  ) <> MethodAddr) do
     Inc(VMTOffs, SizeOf(pointer));
    If VMTOffs >= MaxMethodsOffs
     then  GetOffsetInVMT := 0   { Damn, there is no such method! }
     else  GetOffsetInVMT := VMTOffs;
End;

{--------------------------------------------------------------------}

Begin
    ItIsAObject.Init;
    ItIsBObject.Init;
    ItIsAObject.MethodA;
    ItIsAObject.MethodB;
    MethodAOffsetInVMT := GetOffsetInVMT(TypeOf(TAObject),
                                         @TAObject.MethodA);
    MethodBOffsetInVMT := GetOffsetInVMT(TypeOf(TAObject),
                                         @TAObject.MethodB);
    Writeln(MethodAOffsetInVMT);
    Writeln(MethodBOffsetInVMT);

    { --- Let's call TBObject.MethodA  }
    asm
      mov  di,offset ItIsBObject
      push ds              { Pushing @Self for object in stack }
      push di
      mov  di,[di]         { VMT offset in data segment }
      add  di,[MethodAOffsetInVMT]  { Adding method offset in VMT }
      call dword ptr [di]
    end;
End.


[Back to MEMORY SWAG index]  [Back to Main SWAG index]  [Original]