正如我所見,extern
彙編代碼中的WinAPI函數的名稱有[email protected]
。Win32程序集 - 外部函數命名('@'的含義)
@4
部分的含義是什麼,以及如何確定在@
之後要使用哪個數字?
我知道這與我們鏈接的DLL有關,但在很多情況下,我們不知道在@
之後使用了什麼數字,這會導致許多令人討厭的undefined reference
錯誤。
正如我所見,extern
彙編代碼中的WinAPI函數的名稱有[email protected]
。Win32程序集 - 外部函數命名('@'的含義)
@4
部分的含義是什麼,以及如何確定在@
之後要使用哪個數字?
我知道這與我們鏈接的DLL有關,但在很多情況下,我們不知道在@
之後使用了什麼數字,這會導致許多令人討厭的undefined reference
錯誤。
參見如安德烈亞斯ħ回答說@
後的數字是一個字節的函數返回之前的號碼的功能從棧中刪除。這意味着應該很容易確定該數字,因爲它需要的字節數也會推送到堆棧上以正確調用該函數。它應該是調用之前PUSH指令的數量乘以4.在大多數情況下,這也將是傳遞給函數的參數的數量乘以4。
如果要仔細檢查你已經得到了正確的數字,你有微軟的Visual Studio安裝,你可以找到從開發人員命令提示符這樣的裝飾符號名稱:
C:\> dumpbin /headers kernel32.lib | find "ExitProcess"
Symbol name : [email protected]
Name : ExitProcess
如果」重新使用MinGW的編譯工具鏈接你的彙編代碼,你可以這樣做,而不是:
C:\> nm C:\MinGW\lib\libkernel32.a | find "ExitProcess"
00000000 I [email protected]
00000000 T [email protected]
你需要在你安裝MinGW的目錄,以取代C:\MinGW
。
由於並非所有Windows API都駐留在kernel32
導入庫中,您需要用Windows SDK文檔中給出的導入庫的名稱替換kernel32
,以獲取要鏈接到的API函數。例如,對於MessageBoxA
,您需要在Visual Studio中使用user32.lib
,而在MinGW中使用libuser32.a
。
請注意,有幾種罕見的Windows API不使用stdcall
調用約定。這些功能類似於wsprintf
,其採用可變數量的參數,其中stdcall
調用約定不支持。這些函數名稱前只有一個下劃線_
,並且沒有@
或之後的數字。他們還要求調用者從堆棧中移除參數。
如果您想獲取要使用的號碼,請確保將_NT_SYMBOL_PATH定義爲正確的值。
喜歡:
srv*https://msdl.microsoft.com/download/symbols
或
srv*c:\MyServerSymbols*https://msdl.microsoft.com/download/symbols
例如(在cmd.exe的,窗口的命令行):
set _NT_SYMBOL_PATH=srv*https://msdl.microsoft.com/download/symbols
然後使用:
dumpbin /exports /symbols kernel32.dll | grep -i ExitProcess
你必須在kernel32所在的目錄下,你必須有grep。
可能是一種使用內置find命令的方法。你也可以將它重定向到一個文件,然後在你的編輯器中查看它。
不適合我。我只是得到'289 120 ExitProcess(轉發給NTDLL.RtlExitUserProcess)'。 –
更正了......需要添加/符號 –
仍然沒有運氣,我用'/ exports/symbols'得到了同樣的結果。 –
當爲函數指定stdcall調用約定時,@符號是作爲前導下劃線的函數名稱的一部分。
該數字指定函數從堆棧中移除的字節數。
編譯器生成此編號。
添加了後綴,以便函數不會被意外地調用錯誤的調用約定,或者源代碼中的原型指定錯誤的參數數目或大小。所以意圖是提供避免程序崩潰的手段。
這種方法確實有效。 – hakeris1010