在Windows驱动程序调用汇编文件导出的函数

在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...


你可能感兴趣的:(驱动开发学习)