【发布时间】:2014-12-19 09:13:02
【问题描述】:
我正在尝试将一些代码从 Delphi 5 迁移到 Delphi XE7-WIN64。 该方案是最新的 Delphi 不允许混合汇编和 Delphi 代码。 我也是asm新手。
原代码:
function TclDbgHelpStackTracer.GetSymbolSearchPath(): string;
var
sPath: array[0..MAX_PATH] of char;
mbi: MEMORY_BASIC_INFORMATION;
pProc: Pointer;
label l1;
begin
asm
mov eax, offset l1
mov pProc, eax
end;
l1:
Result := '';
if (GetEnvironmentVariable(SYMBOL_PATH) <> '') then
Result := GetEnvironmentVariable(SYMBOL_PATH) + ';';
if (GetEnvironmentVariable(ALTERNATE_SYMBOL_PATH) <> '') then
Result := Result + GetEnvironmentVariable(ALTERNATE_SYMBOL_PATH) + ';';
if (GetEnvironmentVariable('SystemRoot') <> '') then
Result := Result + GetEnvironmentVariable('SystemRoot') + ';';
VirtualQuery(pProc, mbi, sizeof(mbi));
GetModuleFileName(Cardinal(mbi.AllocationBase), sPath, MAX_PATH);
StrRScan(sPath, '\')^ := #0;
Result := Result + sPath + ';';
GetModuleFileName(0, sPath, MAX_PATH);
StrRScan(sPath, '\')^ := #0;
Result := Result + sPath;
end;
以上代码在Delphi XE7-WIN32中工作 但是你可以看到上面的 sn-p 有嵌套的 asm 块 Delphi XE7-WIN64 要求过程/函数只包含 asm 或 pascal 代码。 所以我把它改成如下:
{$IFDEF WIN64}
procedure AsmProc(pProc: Pointer);
asm
mov eax, offset l1
mov pProc, eax
end;
{$ENDIF}
function TclDbgHelpStackTracer.GetSymbolSearchPath(): string;
var
sPath: array[0..MAX_PATH] of char;
mbi: MEMORY_BASIC_INFORMATION;
pProc: Pointer;
label l1;
begin
{$IFDEF WIN32}
asm
mov eax, offset l1
mov pProc, eax
end;
{$ELSE}
AsmProc(pProc);
{$ENDIF}
l1:
Result := '';
if (GetEnvironmentVariable(SYMBOL_PATH) <> '') then
Result := GetEnvironmentVariable(SYMBOL_PATH) + ';';
if (GetEnvironmentVariable(ALTERNATE_SYMBOL_PATH) <> '') then
Result := Result + GetEnvironmentVariable(ALTERNATE_SYMBOL_PATH) + ';';
if (GetEnvironmentVariable('SystemRoot') <> '') then
Result := Result + GetEnvironmentVariable('SystemRoot') + ';';
VirtualQuery(pProc, mbi, sizeof(mbi));
GetModuleFileName(Cardinal(mbi.AllocationBase), sPath, MAX_PATH);
StrRScan(sPath, '\')^ := #0;
Result := Result + sPath + ';';
GetModuleFileName(0, sPath, MAX_PATH);
StrRScan(sPath, '\')^ := #0;
Result := Result + sPath;
end;
现在麻烦开始了。 l1 是代码标签,它的地址(下一条可执行语句的地址)被移动到 eax 然后使指针 pProc 指向该地址。 然后在
中使用指针pProc VirtualQuery(pProc, mbi, sizeof(mbi));
问题是如何传递l1的地址?或者有没有其他方法可以做到这一点?
【问题讨论】:
-
去掉asm会得到启示。它还有助于开始检查错误并停止截断指针。在进入 64 位世界之前,您必须认识到指针是 64 位宽的。
-
正如@rob-kennedy 在我的(现已删除)答案下评论的那样,您可以通过使用全局
HInstance变量而不是Cardinal(mbi.AllocationBase)并抛出pProc和程序集来实现相同的目的代码离开 -
@xmojmr 我没有删除你的答案。 :( 我将在星期一尝试修复,因为我是 OOO。
-
而且我似乎也丢失了@rob-kennedy 的评论。
-
我自己删除了答案,因为它只是部分有用。这是 Rob 的评论:“此代码调用
VirtualQuery来获取基内存地址。它假定它将是整个 DLL 的基地址,并且它进一步假定 i> 基地址可以代表模块句柄。它将“句柄”传递给GetModuleFileName以获取 DLL 的名称。但是 DLL 在全局HInstance变量中已经有一个句柄。那里根本不需要打电话给VirtualQuery。”
标签: delphi assembly delphi-5 delphi-xe7