2014-12-19 23 views
1

我想從Delphi 5遷移一些代碼到Delphi XE7-WIN64。 該場景是最新的Delphi不允許混合裝配和Delphi代碼。 另外我是asm新手。如何在另一個函數中獲取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; 

上面的代碼工作在德爾福XE7-WIN32 但你可以看到上面的代碼中已經嵌套匯編塊 德爾福XE7,WIN64需要過程/函數只包含ASM或帕斯卡代碼。 所以我把它改成如下:

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

啓動將通過刪除asm來達成。它也將有助於開始檢查錯誤並停止截斷指針。在你進入64位世界之前,你必須認識到指針是64位寬的。 – 2014-12-20 01:09:49

+1

由於@ rob-kennedy在我的(現在已刪除的)答案下評論,您可以通過使用全局'HInstance'變量而不是'Cardinal(mbi.AllocationBase)'來實現同樣的效果,並將'pProc'和彙編代碼 – xmojmr 2014-12-20 06:52:18

+0

@xmojmr我沒有刪除你的答案。 :(我將在星期一嘗試修復,因爲我是OOO。 – AEonAX 2014-12-20 07:41:39

回答

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是正確的選擇。這不是其中之一。

+0

謝謝你的答案。看起來很完美,將在週一作爲答覆進行覈對和接受。 – AEonAX 2014-12-20 12:55:03

相關問題