How to get address of Delphi code label in another function?

I am trying to migrate some code from Delphi 5 to Delphi XE7-WIN64. The scenario is latest Delphi doesn't allow mixed assembly and Delphi code. Also I am asm newbie.

Original Code:

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;

The above code works in Delphi XE7-WIN32 But as you can see the above snippet has nested asm block Delphi XE7-WIN64 requires procedures/functions to only contain asm or pascal code. So I changed it to following:

{$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;

Now here the trouble starts. l1 is code label, its address (address of next executable statement) is moved to eax then pointer pProc is made to point along this address. and then pointer pProc is used in

  VirtualQuery(pProc, mbi, sizeof(mbi));

Question Is How to pass address of l1? Or is there any other method to do the same?


The code in the question makes a real meal of extracting the name of the module that contains the executing code. All you need is this:

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;

The asm code in your question was, frankly, bizarre. There's just no need to do it that way. All the code was attempting to do was find the module handle which is already available as the global HInstance variable.

As a general rule, you should try to avoid using asm . It makes code less portable and harder to understand. There are times when using asm is the right choice. This is not one of those occasions.

链接地址: http://www.djcxy.com/p/89890.html

上一篇: Delphi 5编译器错误返回接口指针而不是返回值

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