2012-03-25 54 views
1

我一直在使用NASM在Windows中進行一些x86編程,我遇到了一些困惑。我很困惑,爲什麼我必須這樣做:與NASM一起使用DLL

extern [email protected] 

具體來說,我感到困惑的「_」和「@ 4」。我知道'@ 4'是堆棧的大小,但它爲什麼需要?當我用十六進制編輯器查看kernel32.dll時,我只看到'ExitProcess'而不是'_ExitProcess @ 4'。

我也困惑,爲什麼C函數不需要下劃線和堆棧大小像這樣:

extern printf 

不是C函數爲什麼需要裝飾品?

我的第三個問題是「這是我應該如何使用這些功能的方式?」現在我正在連接實際的dll文件本身。

回答

1

我知道'@ 4'是棧的大小,但它爲什麼需要?

爲了使鏈接器報告一個致命的錯誤,如果你的編譯程序採用了錯誤的調用約定的函數(如果你忘記在C頭文件,忽略所有的編譯器警告或者聲明沒有按這可能發生完全匹配共享庫中的函數)。

爲什麼C函數不需要裝飾?使用該cdecl調用約定

功能與裝飾一個領先的(所以它實際上是_printf)。

沒有參數大小編碼到裝飾名稱中的原因是調用者負責設置和拆除堆棧,因此參數計數不匹配對於堆棧設置不會是致命的(儘管調用函數當然,如果沒有給出正確的參數,它可能仍會崩潰)。參數數量可能是可變的,例如printf

當我用hex編輯器查看kernel32.dll時,我只看到了ExitProcess而不是[email protected]

的錯位的名稱,通常被映射到使用定義文件(*.def)DLL的實際出口名稱,然後被編譯到可以在你的鏈接器調用中使用*.lib導入庫文件。 kernel32.dll的這種定義文件的示例是this one。以下行定義ExitProcess映射:

[email protected] = ExitProcess 

這是我應該使用這些功能的方式嗎?

我不太瞭解NASM,但到目前爲止我見過的代碼通常會指定裝飾名稱,就像您的示例中一樣。

你可以找到更多的信息on this excellent page about Win32 calling conventions

+0

我試着在'printf'之前加上一個下劃線'extern _printf',但它沒有編譯。任何想法爲什麼?我將所有對printf的調用都改爲'call _printf'。 – 2012-03-25 16:46:41

+0

@Hudson:它可以使用'extern printf/call printf'?我很驚訝,我的NASM安裝不是這種情況。也許你的NASM真的知道調用約定?你使用了'-fwin32'標誌嗎? – 2012-03-25 16:48:21

+0

是的,這就是我想的。我要看看NASM的文件來找到答案。 – 2012-03-25 16:51:10