[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]