在Windows驅動程式調用彙編檔案匯出的函數
本文介紹如何在驅動程式的C檔案中調用ASM檔案中匯出的彙編函數
引言
Windows驅動程式使用DDK或者IFSDDK(以下簡稱DDK)中的Build.exe程式對源檔案進行編譯和連結,操作時只需啟動相應的DDK命令列程式,進入待編譯的源檔案目錄,執行Build命令即可得到.sys檔案。
Build命令實際上是調用了一個nmake程式,nmake程式隨後調用cl.exe和link.exe,並指定所有的編譯和連結選項,與應用程式不同,程式員在使用build命令時無法對編譯連結選項進行修改,從而無法在build命令中幹先行編譯或者連結過程。
64位平台不再支援內嵌式的彙編代碼,為了使驅動程式中仍然可以使用組合語言,通常的做法是將彙編代碼寫成獨立的函數放入單獨的彙編檔案中,並對彙編檔案進行編譯形成obj檔案,而後在連結期對所有目標檔案(包括驅動C代碼的目標檔案)進行連結。但是DDK內建的Build程式並不直接支援對彙編檔案的編譯和連結(也可能我還沒有發現這樣的方法)。因此需要通過其他手段將彙編代碼目標檔案和C代碼目標檔案進行連結。本文講述的方法是通過修改SOURCE檔案和強制指定外部函數呼叫慣例的方式來達到在Windows驅動程式中調用獨立彙編函數的目的。
需要注意的問題
1.32位平台和64位平台中呼叫慣例的不同
32位平台下,驅動程式預設採用__stdcall呼叫慣例,該約定編譯產生的函數名均帶有尾碼@xxx,而彙編代碼採用__cdecl呼叫慣例,用彙編器編譯產生的函數名並不帶尾碼,從而導致C代碼無法引用彙編檔案中的函數(連結器會報錯:unresolvedexternalasm_rng_available@xxx)。解決這一問題的方法是強制指定調用外部的彙編函數為__cdecl呼叫慣例,即如果在C檔案中調用彙編檔案中的asm_rng_available函數,聲明方式應如下:
externint __cdecl asm_rng_available() ;
強制指定__cdecl呼叫慣例後可以保證C編譯器產生的asm_rng_available函數名和彙編檔案中產生的函數名是一樣的。
64位體繫結構中只有一個本機呼叫慣例和一個__cdecl約定可以被編譯器忽略,其他的呼叫慣例都已經被清除,所以64位下的DDK編譯器產生的函數名和彙編器產生的函數名是一致的,函數名不會帶有尾碼,因此不必修改。即如果在C檔案中調用彙編檔案中的asm_rng_available函數,聲明方式如下:
externint asm_rng_available() ;
2.SOURCE檔案的修改
由於Build命令不會自動關聯彙編檔案的目標檔案,為了將編譯後的彙編目標檔案和C目標檔案進行連結,可以在SOURCE檔案的TARGETLIBS宏中進行指定。具體方法如下:
TARGETLIBS=.\instr_32.obj
這樣就可以使用Build命令直接對所有目標檔案進行連結了。
3.64位和32位中一些系統調用的差異
64位DDK中的lib庫並沒有匯出KeInitializeSpinLock,KeQueryInterruptTime函數,因此不能直接調用,必須通過MmGetSystemRoutineAddress得到函數的指標,利用函數指標進行調用。
驅動中調用彙編函數
下面對整個過程進行完整的描述:
1.將彙編檔案和驅動程式的C檔案放在同一個目錄下(簡稱驅動目錄);
2.修改SOURCE檔案,在SOURCE檔案中添加TARGETLIBS = *.obj,其中*表示彙編檔案的檔案名稱(不加副檔名);
3.在驅動程式C檔案中聲明外部彙編檔案的函數名,如果是32位體繫結構,聲明時需強制指定彙編函數為__cdecl呼叫慣例;
4.編譯彙編檔案,在驅動目錄下產生obj目標檔案(編譯器可以採用nasm或者masm);
5.在DDK編譯環境下對整個驅動工程執行Build命令,從而產生.sys檔案。
OK...