shenhui
驱动小牛
驱动小牛
  • 注册日期2006-05-11
  • 最后登录2023-02-10
  • 粉丝14
  • 关注11
  • 积分142分
  • 威望1314点
  • 贡献值1点
  • 好评度146点
  • 原创分0分
  • 专家分1分
  • 社区居民
阅读:2603回复:5

【总结】在Windows驱动中调用汇编文件中的函数

楼主#
更多 发布于:2008-11-17 14:43
本文介绍如何在驱动程序的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位驱动如何调用汇编语言”一贴的总结,写得不好,还请大虾小虾们多多指点。
其次我觉得论坛的目的就是让大家在讨论中提高,希望大家以后在讨论过后解决的问题也能分享一下,而不是仅仅说一句“解决了”就结贴了。
作一名真实,诚实,优秀的科技工作者!
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
沙发#
发布于:2008-11-17 15:54
不错,希望多发些相关经验的说明,方便后来者.
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
shenhui
驱动小牛
驱动小牛
  • 注册日期2006-05-11
  • 最后登录2023-02-10
  • 粉丝14
  • 关注11
  • 积分142分
  • 威望1314点
  • 贡献值1点
  • 好评度146点
  • 原创分0分
  • 专家分1分
  • 社区居民
板凳#
发布于: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来编译汇编代码。
作一名真实,诚实,优秀的科技工作者!
zhxiang999
驱动牛犊
驱动牛犊
  • 注册日期2007-04-27
  • 最后登录2010-11-30
  • 粉丝0
  • 关注0
  • 积分17分
  • 威望151点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2009-01-07 10:20
请教一下
我是做camera驱动
用了个jpeg解码的库,里面很多内嵌汇编
在32位平台编译没问题
移植到64位就不行,不支持-asm,mov等
我是要把这些内嵌汇编都做成单独的汇编子程序,然后放在一个独立的.asm文件中,供C函数调用?
但是感觉很繁琐,还有没有别的方法吗?
shenhui
驱动小牛
驱动小牛
  • 注册日期2006-05-11
  • 最后登录2023-02-10
  • 粉丝14
  • 关注11
  • 积分142分
  • 威望1314点
  • 贡献值1点
  • 好评度146点
  • 原创分0分
  • 专家分1分
  • 社区居民
地下室#
发布于:2009-01-07 23:03
目前只有这一个方法,64位不支持内嵌汇编的。其实就是一个习惯问题,也不繁琐
作一名真实,诚实,优秀的科技工作者!
zhxiang999
驱动牛犊
驱动牛犊
  • 注册日期2007-04-27
  • 最后登录2010-11-30
  • 粉丝0
  • 关注0
  • 积分17分
  • 威望151点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
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版上运行没问题,作了少量移植而来)
还望大虾出马,帮我把把脉
谢谢
游客

返回顶部