如何在x64中使用StackAlloc? [英] How to use StackAlloc in x64?

查看:129
本文介绍了如何在x64中使用StackAlloc?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在 X64中的DelphiXE7中使用 StackAlloc Graphics32 c $ c>但是它与erorr崩溃。我尝试向代码添加 NOFRAME ,这也没有帮助。

I am trying to use StackAlloc from Graphics32 in DelphiXE7 in X64 however it crashes with erorr. I tried adding NOFRAME to the code and that didn't help either.

首先机会异常在$ 000000000013FF10。异常类$ C0000005,消息'c0000005 ACCESS_VIOLATION'。进程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
由于这个原因,返回地址不会放回堆栈。

Your version of StackAlloc lacks PUSH R8 at the end of x64 version. Due to this, the return address is not put back on the stack.

这篇关于如何在x64中使用StackAlloc?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆