大佬教程收集整理的这篇文章主要介绍了如何在64位Delphi XE2中将方法转换为回调过程?,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
const AsmPopEDX = $5A; AsmMovEAX = $B8; AsmPushEAX = $50; AsmPushEDX = $52; AsmJmpShort = $E9; type Tstub = packed record PopEDX: Byte; MovEAX: Byte; SelfPointer: Pointer; PushEAX: Byte; PushEDX: Byte; JmpShort: Byte; Displacement: Integer; end; { ----------------------------------------------------------------------------- } function Createstub(ObjectPtr: Pointer; MethodPtr: Pointer): Pointer; var stub: ^Tstub; begin // Allocate memory for the stub // 1/10/04 Support for 64 bit,executable code must be in virtual space stub := VirtualAlloc(nil,SizeOf(Tstub),MEM_COMMIT,PAGE_EXECUTE_READWRITE); // Pop the return address off the stack stub^.PopEDX := AsmPopEDX; // Push the object pointer on the stack stub^.MovEAX := AsmMovEAX; stub^.SelfPointer := ObjectPtr; stub^.PushEAX := AsmPushEAX; // Push the return address BACk on the stack stub^.PushEDX := AsmPushEDX; // Jump to the 'real' procedure,the method. stub^.JmpShort := AsmJmpShort; stub^.Displacement := (Integer(MethodPtr) - Integer(@(stub^.JmpShort))) - (SizeOf(stub^.JmpShort) + SizeOf(stub^.Displacement)); // Return a pointer to the stub Result := stub; end; { ----------------------------------------------------------------------------- } { ----------------------------------------------------------------------------- } procedure Disposestub(stub: Pointer); begin // 1/10/04 Support for 64 bit,executable code must be in virtual space VirtualFree(stub,MEM_DECOMMIT); end;
我很感激将它转换为64位的任何帮助.我知道Win64中的调用约定是不同的,并且最多四个参数被传递到寄存器中.因此可能必须修改Createstub以包含参数的数量.它实际上不使用四个以上的参数,即整数或指针(没有浮点参数).
type ICallBACkstub = interface(IInterfacE) function GetstubPointer: Pointer; property stubPointer : Pointer read GetstubPointer; end; TCallBACkstub = class(TinterfacedObject,ICallBACkstub) private fstubPointer : Pointer; fCodeSize : Integer; function GetstubPointer: Pointer; public constructor Create(Obj : TObject; MethodPtr: Pointer; NumArgs : Integer); destructor Destroy; override; end; constructor TCallBACkstub.Create(Obj: TObject; MethodPtr: Pointer; NumArgs: Integer); {$IFNDEF CPUX64} // as before {$ELSE CPUX64} const RegParamCount = 4; ShadowParamCount = 4; Size32Bit = 4; Size64Bit = 8; ShadowStack = ShadowParamCount * Size64Bit; SkipParamCount = RegParamCount - ShadowParamCount; StackSrsOffset = 3; c64stack: arraY[0..14] of byte = ( $48,$81,$ec,00,// sub rsp,$0 $4c,$89,$8c,$24,ShadowStack,00// mov [rsp+$20],r9 ); CopySrcOffset=4; CopyDstOffset=4; c64copy: arraY[0..15] of byte = ( $4c,$8b,// mov r9,[rsp+0] $4c,00// mov [rsp+0],r9 ); RegMethodOffset = 10; RegSelfOffset = 11; c64regs: arraY[0..28] of byte = ( $4d,$c1,// mov r9,r8 $49,$d0,// mov r8,rdx $48,$ca,// mov rdx,rcx $48,$b9,// mov rcx,Obj $48,$b8,00 // mov rax,MethodPtr ); c64jump: arraY[0..2] of byte = ( $48,$ff,$e0 // jump rax ); CallOffset = 6; c64call: arraY[0..10] of byte = ( $48,// call rax $48,$c4,// add rsp,$0 $c3// ret ); var i: Integer; P,PP,Q: PByte; lCount : Integer; lSize : Integer; lOffset : Integer; begin lCount := SizeOf(c64regs); if NumArgs>=RegParamCount then Inc(lCount,sizeof(c64stack)+(NumArgs-RegParamCount)*sizeof(c64copy)+sizeof(c64call)) else Inc(lCount,sizeof(c64jump)); Q := VirtualAlloc(nil,lCount,PAGE_EXECUTE_READWRITE); P := Q; lSize := 0; if NumArgs>=RegParamCount then begin lSize := ( 1+ ((NumArgs + 1 - SkipParamCount) div 2) * 2 )* Size64Bit; // 16 byte stack align pp := p; move(c64stack,P^,SizeOf(c64stack)); Inc(P,StackSrsOffset); move(lSize,Size32Bit); p := pp; Inc(P,SizeOf(c64stack)); for I := 0 to NumArgs - RegParamCount -1 do begin pp := p; move(c64copy,SizeOf(c64copy)); Inc(P,CopySrcOffset); lOffset := lSize + (i+ShadowParamCount+1)*Size64Bit; move(lOffset,Size32Bit); Inc(P,CopyDstOffset+Size32Bit); lOffset := (i+ShadowParamCount+1)*Size64Bit; move(lOffset,Size32Bit); p := pp; Inc(P,SizeOf(c64copy)); end; end; pp := p; move(c64regs,SizeOf(c64regs)); Inc(P,RegSelfOffset); move(Obj,SizeOf(Obj)); Inc(P,RegMethodOffset); move(MethodPtr,SizeOf(MethodPtr)); p := pp; Inc(P,SizeOf(c64regs)); if NumArgs<RegParamCount then move(c64jump,SizeOf(c64jump)) else begin move(c64call,SizeOf(c64call)); Inc(P,CallOffset); move(lSize,Size32Bit); end; fCodeSize := lcount; fstubPointer := Q; {$ENDIF CPUX64} end; destructor TCallBACkstub.Destroy; begin VirtualFree(fstubPointer,fCodeSize,MEM_DECOMMIT); inherited; end; function TCallBACkstub.GetstubPointer: Pointer; begin Result := fstubPointer; end;
以上是大佬教程为你收集整理的如何在64位Delphi XE2中将方法转换为回调过程?全部内容,希望文章能够帮你解决如何在64位Delphi XE2中将方法转换为回调过程?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。