阅读:2603回复:5
【总结】在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代码无法引用汇编文件中的函数(链接器会报错:unresolved external asm_rng_available@xxx)。解决这一问题的方法是强制指定调用外部的汇编函数为__cdecl调用约定,即如果在C文件中调用汇编文件中的asm_rng_available函数,声明方式应如下: extern int __cdecl asm_rng_available() ; 强制指定__cdecl调用约定后可以保证C编译器生成的asm_rng_available函数名和汇编文件中生成的函数名是一样的。 64位体系结构中只有一个本机调用约定和一个__cdecl约定可以被编译器忽略,其他的调用约定都已经被清除,所以64位下的DDK编译器生成的函数名和汇编器生成的函数名是一致的,函数名不会带有后缀,因此不必修改。即如果在C文件中调用汇编文件中的asm_rng_available函数,声明方式如下: extern int 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文件。 本文是对“64位驱动如何调用汇编语言”一贴的总结,写得不好,还请大虾小虾们多多指点。 其次我觉得论坛的目的就是让大家在讨论中提高,希望大家以后在讨论过后解决的问题也能分享一下,而不是仅仅说一句“解决了”就结贴了。 |
|
|
沙发#
发布于:2008-11-17 15:54
不错,希望多发些相关经验的说明,方便后来者.
|
|
|
板凳#
发布于:2008-11-18 09:51
我后来有看了一下,微软的DDK提供了一种方法也可以。
在SOURCE文件中加入 i386_SOURCES = *.asm(*表示汇编文件名)或者AMD64_SOURCES=*.asm(64位平台下),同时在驱动工程目录下创建i386子目录,把汇编文件放进子目录中,这样仅用Build命令就可以编译链接从而生成.sys文件了,不过这种方法由于使用的是DDK的ml或ml64汇编器,所以要求汇编代码要用MASM来写,不知道能不能在SOURCE文件里面加入一些命令,比如加入nasm的编译命令,从而可以让DDK调用nasm来编译汇编代码。 |
|
|
地板#
发布于:2009-01-07 10:20
请教一下
我是做camera驱动 用了个jpeg解码的库,里面很多内嵌汇编 在32位平台编译没问题 移植到64位就不行,不支持-asm,mov等 我是要把这些内嵌汇编都做成单独的汇编子程序,然后放在一个独立的.asm文件中,供C函数调用? 但是感觉很繁琐,还有没有别的方法吗? |
|
地下室#
发布于:2009-01-07 23:03
目前只有这一个方法,64位不支持内嵌汇编的。其实就是一个习惯问题,也不繁琐
|
|
|
5楼#
发布于:2009-01-12 20:16
再次请教
我现在64位的SYS文件用2003 ddk amd64已经编译出来了 然后照着DDK 的例子写了个inf文件 然后手动加载该摄像头驱动 在vista的设备驱动中通过F8绕过数字签名,系统中显示该sys文件加载了 调用应用程序amcap, 不能捕捉到视频数据, 估计是哪里出了问题,该如何调试 为什么我的vista 很多调试工具都无法运行,dbgview, syser debug, bus hound (该SYS文件是在XP版上运行没问题,作了少量移植而来) 还望大虾出马,帮我把把脉 谢谢 |
|