我正在尝试将一些代码从Delphi 5迁移到Delphi XE7-WIN64。 方案是最新的Delphi不允许混合汇编和Delphi代码。 我也是新手。
原始代码:
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 但正如您所看到的,上面的代码片段嵌套了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的地址?或者还有其他方法可以做同样的事情吗?
答案 0 :(得分:2)
问题中的代码真实地提取了包含执行代码的模块的名称。所有你需要的是:
function TclDbgHelpStackTracer.GetSymbolSearchPath(): string;
function GetEnvPath(const Name: string): string;
var
Value: string;
begin
Value := GetEnvironmentVariable(Name);
if Value <> '' then
Result := Value + ';'
else
Result := '';
end;
function GetModulePath(Module: HMODULE): string;
begin
Result := ExtractFileDir(GetModuleName(Module));
end;
begin
Result :=
GetEnvPath(SYMBOL_PATH) +
GetEnvPath(ALTERNATE_SYMBOL_PATH) +
GetEnvPath('SystemRoot') +
GetModulePath(HInstance) + ';' +
GetModulePath(0);
end;
坦白说,你问题中的asm
代码是奇怪的。没有必要这样做。所有代码都试图找到已经可用作全局HInstance
变量的模块句柄。
作为一般规则,您应该尽量避免使用asm
。它使代码不那么便携,更难理解。有时使用asm
是正确的选择。这不是其中之一。