【问题标题】:How to handle PByte pointer operations in D5/D7 (Operator not applicable to this operand type)如何处理 D5/D7 中的 PByte 指针操作(运算符不适用于此操作数类型)
【发布时间】:2016-07-14 10:12:23
【问题描述】:

我正在尝试将 DDetours lib 移植到 Delphi 5/7。不会编译的行有这种模式:

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

编译器错误:

[Error] InstDecode.pas(882): 运算符不适用于此操作数 输入

PInst^.VirtualAddr, PInst^.NextInst, PInst^.Addr 都被声明为PByte (PByte = ^Byte)

我能做些什么来解决这个问题?


编辑:

PInstruction 定义为:

  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;

【问题讨论】:

    标签: delphi delphi-7 delphi-5


    【解决方案1】:

    在较新的 Delphi 版本中,PByte 可用于指针运算。在此之前,唯一可以做到这一点的类型是PCharPAnsiCharPWideChar)。在 Delphi 5 中,PCharPAnsiChar

    更新

    现在我知道了记录的结构,也知道了你想要达到的目标,我想你大概应该做到以下几点。

    您可以将所有TInstruction 中的PBytes 更改为PAnsiChar(或PChar,如果您只关心D5),也可以在每个例程中更改所有PBytes。然后你得到:

    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);
      ...
    

    但请注意,如果您想使用这些 PAnsiChars 读取或写入字节,则必须将它们转换为 PByte

    【讨论】:

    • 最好明确并使用PAnsiChar,那么至少代码在所有Delphi版本上都意味着同样的事情
    • @David:我同意,但我不确定 PAnsiChar 是否真的在 Delphi 5 中定义,如果是,它是否可以与 PChar 做同样的事情。自 2001 年 IIRC 以来,我没有使用过 Delphi 5。
    • 它必须在那里定义,因为它们有PWideCharWideString 等。COM 很早就支持了。
    • @David:好的,我会编辑我的答案。感谢您的信息。
    • @Arioch'The: Inc(pointer, count) 在所有 Delphi 版本中一直有效。在 D5(PAnsiChar 除外)中不起作用的是直接使用 pointer + count 的代码。这是在 D2009 中添加的,并引入了 {$POINTERMATH} 指令。
    【解决方案2】:

    在 Delphi 5 下,尝试:

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

    使用integer() 类型转换可以解决指针算术问题。但它只能在 32 位可执行文件下工作。

    【讨论】:

    • 谢谢,但是我在PInst^.Branch.Target := VA + Value 上遇到了同样的错误,其中ValueInt64。我应该把它改成PInst^.Branch.Target := PByte(Integer(VA) + Value);吗?
    • AFAIR 另一个技巧是integer(VA) := integer(PInst^.VirtualAddr) + .....。但要注意“指针数学”——它对 PByte/Pointer 无关紧要,但它会对 PWord、PInteger 等产生影响。
    猜你喜欢
    • 1970-01-01
    • 2017-09-04
    • 2020-02-28
    • 2012-11-20
    • 2021-03-19
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多