delphi – 如何在x64中使用StackAlloc?

前端之家收集整理的这篇文章主要介绍了delphi – 如何在x64中使用StackAlloc?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图在X64中的DelphiXE7中使用Graphics32中的StackAlloc但是它与erorr崩溃了.我尝试将NOFRAME添加代码中,这也没有帮助.

第一次机会异常在$000000000013FF10.消息’c0000005 ACCESS_VIOLATION’的异常类$C0000005. Process Stack.exe(4536)

program Stack;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,System.Classes;

function StackAlloc(Size: Integer): Pointer; register;
asm
{$IFDEF cpuX86}
        POP       ECX          // return address
        MOV       EDX,ESP
        ADD       EAX,3
        AND       EAX,not 3   // round up to keep ESP dword aligned
        CMP       EAX,4092
        JLE       @@2
@@1:
        SUB       ESP,4092
        PUSH      EAX          // make sure we touch guard page,to grow stack
        SUB       EAX,4096
        JNS       @@1
        ADD       EAX,4096
@@2:
        SUB       ESP,EAX
        MOV       EAX,ESP     // function result = low memory address of block
        PUSH      EDX          // save original SP,for cleanup
        MOV       EDX,ESP
        SUB       EDX,4
        PUSH      EDX          // save current SP,for sanity check  (sp = [sp])
        PUSH      ECX          // return to caller
{$ELSE}
        .NOFRAME
        MOV       RAX,RCX
        POP       R8           // return address
        MOV       RDX,RSP     // original SP
        ADD       ECX,15
        AND       ECX,NOT 15  // round up to keep SP dqword aligned
        CMP       ECX,4092
        JLE       @@2
@@1:
        SUB       RSP,4092
        PUSH      RCX          // make sure we touch guard page,to grow stack
        SUB       ECX,4096
        JNS       @@1
        ADD       ECX,4096
@@2:
        SUB       RSP,RCX
        MOV       RAX,RSP     // function result = low memory address of block
        PUSH      RDX          // save original SP,for cleanup
        MOV       RDX,RSP
        SUB       RDX,8
        PUSH      RDX          // save current SP,for sanity check  (sp = [sp])
{$ENDIF}
end;

{ StackFree pops the memory allocated by StackAlloc off the stack.
- Calling StackFree is optional - SP will be restored when the calling routine
  exits,but it's a good idea to free the stack allocated memory ASAP anyway.
- StackFree must be called in the same stack context as StackAlloc - not in
  a subroutine or finally block.
- Multiple StackFree calls must occur in reverse order of their corresponding
  StackAlloc calls.
- Built-in sanity checks guarantee that an improper call to StackFree will not
  corrupt the stack. Worst case is that the stack block is not released until
  the calling routine exits. }

procedure StackFree(P: Pointer); register;
asm
{$IFDEF cpuX86}
        POP       ECX                     { return address }
        MOV       EDX,DWORD PTR [ESP]
        SUB       EAX,8
        CMP       EDX,ESP                { sanity check #1 (SP = [SP]) }
        JNE       @Exit
        CMP       EDX,EAX                { sanity check #2 (P = this stack block) }
        JNE       @Exit
        MOV       ESP,DWORD PTR [ESP+4]  { restore prevIoUs SP  }
@Exit:
        PUSH      ECX                     { return to caller }
{$ELSE}
        POP       R8                       { return address }
        MOV       RDX,QWORD PTR [RSP]
        SUB       RCX,16
        CMP       RDX,RSP                 { sanity check #1 (SP = [SP]) }
        JNE       @Exit
        CMP       RDX,RCX                 { sanity check #2 (P = this stack block) }
        JNE       @Exit
        MOV       RSP,QWORD PTR [RSP + 8] { restore prevIoUs SP  }
 @Exit:
        PUSH      R8                       { return to caller }
{$ENDIF}
end;

var
  SL: ^TStringList;
begin
  SL := StackAlloc(SizeOf(TStringList)); // Crashes here.
  SL^ := TStringList.Create;
  SL^.Add('sda');
  FreeAndNil(SL^);
  StackFree(sl);
  Readln;
end.

解决方法

您的StackAlloc版本在x64版本末尾缺少PUSH R8. 因此,返回地址不会被放回堆栈.
原文链接:https://www.f2er.com/delphi/103205.html

猜你在找的Delphi相关文章