gpt4 book ai didi

delphi - 如何在 x64 中使用 StackAlloc?

转载 作者:行者123 更新时间:2023-12-03 15:09:05 26 4
gpt4 key购买 nike

我试图在X64中的DelphiXE7中使用Graphics32中的StackAlloc,但是它因错误而崩溃。我尝试将 NOFRAME 添加到代码中,但这也没有帮助。

第一次机会异常(exception),$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。因此,返回地址不会放回堆栈中。

关于delphi - 如何在 x64 中使用 StackAlloc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27809091/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com