首页 文章

如何在另一个函数中获取Delphi代码标签的地址?

提问于
浏览
1

我正在尝试将一些代码从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的地址?或者还有其他方法可以做同样的事情吗?

1 回答

  • 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 是正确的选择 . 这不是其中之一 .

相关问题