Search code examples
delphidelphi-7delphi-5

How to handle PByte pointer operations in D5/D7 (Operator not applicable to this operand type)


I'm trying to port DDetours lib to Delphi 5/7. The lines that wont compile have this pattern:

procedure Decode_J(PInst: PInstruction; Size: Byte);
var
  Value: Int64;
  VA: PByte;
begin
  ...
  VA := PInst^.VirtualAddr + (PInst^.NextInst - PInst^.Addr) // <- compiler error

with compiler error:

[Error] InstDecode.pas(882): Operator not applicable to this operand type

PInst^.VirtualAddr, PInst^.NextInst, PInst^.Addr are all declared as PByte (PByte = ^Byte)

What can I do to resolve this?


EDIT:

PInstruction is defined as:

  TInstruction = record
    Archi: Byte; { CPUX32 or CPUX64 ! }
    AddrMode: Byte; { Address Mode }
    Addr: PByte;
    VirtualAddr: PByte;
    NextInst: PByte; { Pointer to the Next Instruction }
    OpCode: Byte; { OpCode Value }
    OpType: Byte;
    OpKind: Byte;
    OpTable: Byte; { tbOneByte,tbTwoByte,... }
    OperandFlags: Byte;
    Prefixes: Word; { Sets of Prf_xxx }
    ModRm: TModRM;
    Sib: TSib;
    Disp: TDisplacement;
    Imm: TImmediat; { Primary Immediat }
    ImmEx: TImmediat; { Secondary Immediat if used ! }
    Branch: TBranch; { JMP & CALL }
    SegReg: Byte; { Segment Register }
    Rex: TRex;
    Vex: TVex;
    LID: TInternalData; { Internal Data }
    Errors: Byte;
    InstSize: Byte;
    Options: Byte;
    UserTag: UInt64;
  end;

  PInstruction = ^TInstruction;

Solution

  • In newer Delphi versions, PByte can be used in pointer arithmetic. Before that, the only type that could do that was PChar (PAnsiChar or PWideChar). In Delphi 5, PChar is a PAnsiChar.

    Update

    Now I know the structure of the record and know what you want to achieve, I think you should probably do the following.

    You could change all PBytes in TInstruction to PAnsiChar (or PChar, if you only care about D5), and also all PBytes in every routine. Then you get:

    PInstruction = ^TInstruction;
    TInstruction = record
      Archi: Byte; { CPUX32 or CPUX64 ! }
      AddrMode: Byte; { Address Mode }
      Addr: PAnsiChar;
      VirtualAddr: PAnsiChar;
      NextInst: PAnsiChar; { Pointer to the Next Instruction }
      ...
    end;
    
    ...
    
    procedure Decode_J(PInst: PInstruction; Size: Byte);
    var
      Value: Int64;
      VA: PAnsiChar;
    begin
      ...
      VA := PInst^.VirtualAddr + (PInst^.NextInst - PInst^.Addr);
      ...
    

    But note that if you want to read or write a byte using these PAnsiChars, you will have to cast them to PByte.