如何在x64中使用StackAlloc? [英] How to use StackAlloc in x64?
本文介绍了如何在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屋!
查看全文