Delphi DUnit2';被调用的RADDR函数,如何将其转换为64位?
我试图让DUnit2在64位下工作,但我对这种方法的作用感到困惑,更不用说如何将其转换为64位了。纯Pascal会更好,但因为它引用堆栈(ebp),所以可能不可能Delphi DUnit2';被调用的RADDR函数,如何将其转换为64位?,delphi,assembly,32bit-64bit,Delphi,Assembly,32bit 64bit,我试图让DUnit2在64位下工作,但我对这种方法的作用感到困惑,更不用说如何将其转换为64位了。纯Pascal会更好,但因为它引用堆栈(ebp),所以可能不可能 function CallerAddr: Pointer; assembler; const CallerIP = $4; asm mov eax, ebp call IsBadPointer test eax,eax jne @@Error mov eax, [ebp].Calle
function CallerAddr: Pointer; assembler;
const
CallerIP = $4;
asm
mov eax, ebp
call IsBadPointer
test eax,eax
jne @@Error
mov eax, [ebp].CallerIP
sub eax, 5 // 5 bytes for call
push eax
call IsBadPointer
test eax,eax
pop eax
je @@Finish
@@Error:
xor eax, eax
@@Finish:
end;
谢谢你的快速回复,但它不起作用。当函数退出时,我得到以下访问冲突。异常类别$C0000005,消息为“C0000005访问\u冲突”。−1.完全没有抓住要点。这是原始代码的文字转换-它使用64位寄存器而不是32位寄存器-因此我不能严格地称之为错误答案。然而,这显然是一个毫无帮助的答案,因为它没有显示出理解原始代码的目的或确保此函数实现与原始代码相同的目标的努力。给那些不熟悉Delphi运行时的人一点解释:上面是“常用”的32位x86汇编程序代码使用帧指针的情况;由于功能尾声
推EBP;mov ESP,EBP
结果是[EBP+4]
始终是返回地址(由用于输入函数的调用写入)。帧指针在64位上是可选的,通常经过优化,因此简单地用[RBP+8]
替换[EBP+4]
是不合适的。Delphi运行时将RtlCaptureStackBacktrace()
(就像Linux glibc将backtrace()
)作为此问题的“抽象”解决方案。@frankh在x86上不是可选的帧指针吗?此外,这与Delphi运行时无关。RtlCaptureStackBacktrace是一个Windows API。@David Hefferman:如果帧指针被优化掉,原始海报显示的代码在32位上不能/不会工作。因此,我的假设是(因为它应该适用于Delphi编译代码),它们不是可选的(在32位Delphi中)。rtlcapturestacktrace()
上的确认-缺少下面的kernel32.dll
。我之所以发表这篇评论,主要是因为被接受的答案是一个“神奇”的答案,任何不熟悉这一点的人都无法从中学习…@Frank,没有必要做出任何假设。文档清楚地表明,堆栈帧是可选的。
function CallerAddr: Pointer; assembler;
const
CallerIP = $4;
asm
mov rax, rcx ;For int.. XMM0 for float
call IsBadPointer
test rax,rax
jne @@Error
mov rax, [rcx].CallerIP
sub rax, 5 // 5 bytes for call
push rax
call IsBadPointer
test rax,rax
pop rax
je @@Finish
@@Error:
xor rax, rax
@@Finish:
end;
function RtlCaptureStackBackTrace(FramesToSkip: ULONG; FramesToCapture: ULONG;
out BackTrace: Pointer; BackTraceHash: PULONG): USHORT; stdcall;
external 'kernel32.dll' name 'RtlCaptureStackBackTrace' delayed;
function CallerAddr: Pointer;
begin
// Skip 2 Frames, one for the return of CallerAddr and one for the
// return of RtlCaptureStackBackTrace
if RtlCaptureStackBackTrace(2, 1, Result, nil) > 0 then
begin
if not IsBadPointer(Result) then
Result := Pointer(NativeInt(Result) - 5)
else
Result := nil;
end
else
begin
Result := nil;
end;
end;