WEB开发网
开发学院软件开发汇编语言 汇编教程:VxD程序设计入门 阅读

汇编教程:VxD程序设计入门

 2008-12-27 09:35:54 来源:WEB开发网   
核心提示:如果你用CreateFile来加载一个动态VxD,那么这个动态VxD必须处理w32_DeviceIoControl 消息,汇编教程:VxD程序设计入门(2),当你的动态VxD第一次被CreateFile函数加载的时候,VWIN32 向你的VxD发出这个消息,所以我想MASM6.14修正了这个bug,但是为了安全起见,你

如果你用CreateFile来加载一个动态VxD,那么这个动态VxD必须处理w32_DeviceIoControl 消息。当你的动态VxD第一次被CreateFile函数加载的时候,VWIN32 向你的VxD发出这个消息。你的VxD响应这个消息,返回时eax中的值必须为零。当应用程序调用DeviceIoControl API来与一个动态VxD通讯时,w32_DeviceIoControl消息也被发送。我们会在下一章讲到DeviceIoControl接口。

一个动态VxD在初始化时收到一个消息:

Sys_Dynamic_Device_Init
   在结束时也收到一个控制消息:

Sys_Dynamic_Device_Exit

动态VxD不会收到Sys_Critical_Init, Device_Init和Init_Complete控制消息,因为这些消息是在系统虚拟机初始化时发送的。除了这三个消息,动态VxD能收到所有的控制消息,只要它还在内存里。它可以做静态VxD可以做的所有事情。简单的说,动态VxD除了加载机制和接收到的初始化/结束消息跟静态VxD不同以外,它能做静态VxD所能做的一切。

其它系统控制消息

当VxD在内存里的时候,除了接收和初始化及结束相关的消息外,它还要收到许多别的控制消息。有些消息是关于虚拟机管理器的,有的是关于各种事件的。例如,关于虚拟机的消息如下:

Create_VM
VM_Critical_Init
VM_Suspend
VM_Resume
Close_VM_Notify
Destroy_VM

选择地响应你所感兴趣的消息是你自己的责任。

在VxD内创建函数

你要在一个段里面定义你的函数。你应该首先定义一个段,然后把你的函数放进去。例如,如果你要把你的函数放到一个可调页段中。你应该先定义一个可调页段,像这样:

VxD_PAGEABLE_CODE_SEG

(你的函数写在这里)

VxD_PAGEABLE_CODE_ENDS

你可以在一个段里面插入多个的函数。作为一个VxD编写者,你必须决定每一个函数应该放到哪个段里面去。如果你的函数必须时刻存在于内存中,如某些硬件中断处理程序,就把它们放到锁定页面段里面,否则,你应该把它们放到可调页段。

你要用BeginProc和EndProc 宏来定义你的函数:

BeginProc 函数名

EndProc 函数名

使用BeginProc 宏还可以加上一些参数,想了解这些细节,你可以看看Win95 DDK的文档。大多数时候,你只用填写函数的名字就够了。

因为BeginProc-EndProc 宏比proc-endp 指令的功能要强,所以你应该用BeginProc-EndProc宏来代替proc-endp指令

VxD编程约定

寄存器的使用

你的VxD程序可以使用所有的寄存器,FS和GS。但是在改动段寄存器的时候一定要小心。尤其是,一定不要改动CS和SS的内容,除非你对将发生的事情有绝对的把握。你可以使用DS和ES,但一定要记住在返回时恢复它们初值。有两个特征位尤其重要:方向和中断特征位。不要长时间的屏蔽中断。还有如果你要改动方向特征位,不要忘了在返回之前恢复它的初值。

参数传递约定

VxD服务函数有两种调用约定:寄存器法和堆栈法。调用寄存器法服务函数时,你通过各种寄存器来传递服务函数的参数。并且,在调用完成后检查寄存器的值来看操作是否成功。不要总是以为在调用服务函数后主要寄存器的值还和以前一样。当调用堆栈法服务函数时,你把要传递的参数压栈,在eax得到返回值。堆栈调用法的服务函数保存ebx,esi,edi和ebp的值。许多寄存器调用法服务函数都源于Windows3.x的时代。在大多数时候,你可以通过名字来区分这两种服务函数,如果一个函数的名字一下划线开头,如_HeapAllocate,它就是一个堆栈法的服务函数(除了少数从VWIN32.VxD导出的函数)。如果函数名不是一下划线开头,它就是一个寄存器法的服务函数。

调用VxD服务函数

你可以通过VMMCall和VxDCall 宏来调用VMM和VxD服务。这两个宏的语法是一样的。当你要调用VMM导出的VxD服务函数时,用VMMCall。当你要用其它VxD程序导出的VxD服务函数时,用VxDCall。

VMMCall service ; 调用寄存器法服务函数e

VMMCall _service, <argument list> ; 调用堆栈法服务函数

正如我在前面所讲的,VMMCall和VxDCall分解出一个跟着一个双字的20h中断,这样用起来很方便。当你调用堆栈法服务时,你必须用角括号把你的参数列括起来。

VMMCall _HeapAllocate, <<size mybuffer>, HeapLockedIfDP>

_HeapAllocate是一个堆栈法服务函数。它有两个参数,我们必须用角括号把它们括起来。由于第一个参数是一个这个宏不能正确解释的表达式,所以我们又要用一个角括号把它括起来。

Flat地址

在老的编译工具里,当你使用offset 操作符时,编译器和联接器会生成错误地址,所以VxD编写者用offset flat:来代替offset。imm.inc包括了一个使这更简单的宏:OFFSET32 来代替offset flat:。所以如果你要用地址操作时,用OFFSET32 来代替offset操作符。

注意: 当我写这篇教程的时候,我试了一下用offset 操作符。它可以生成正确的地址。所以我想MASM6.14修正了这个bug。但是为了安全起见,你还是应该用OFFSET32宏来代替offset。

上一页  1 2 

Tags:汇编 教程 VxD

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接