记住,int 21h是一个DOS服务,因而其在V86模式下是可用的,我们如何在VxD中调用一个V86中断?一个方法是使用Exec_Int服务。这个VMM服务把要调用的中断号放在eax中。它模拟指定的中断然后返回到调用的VM。然而,它必须在一个嵌套执行块中被调用。嵌套执行块被Begin_Nest_V86_Exec (或 Begin_Nest_Exec)和End_Nest_Exec包括起来。如果我们要调用int 21h功能2h,我们需要在嵌套执行块内转换Client_Byte_Reg_Struc结构的Client_ah和Client_Dl,然后把值21h放在eax中。当一切准备好了,就调用Exec_Int。 例子: 例子是一个动态VxD,它调用int 21h的功能2使PC喇叭发声。 .386p include /masm/include/vmm.inc include /masm/include/vwin32.inc include /masm/include/v86mmgr.inc VxDName TEXTEQU ControlName TEXTEQU VxDMajorVersion TEXTEQU <1> VxDMinorVersion TEXTEQU <0> VxD_STATIC_DATA_SEG VxD_STATIC_DATA_ENDS VXD_LOCKED_CODE_SEG ;---------------------------------------------------------------------------- ; Remember: The name of the vxd MUST be uppercase else it won't work/unload ;---------------------------------------------------------------------------- DECLARE_VIRTUAL_DEVICE %VxDName,%VxDMajorVersion,%VxDMinorVersion, %ControlName,UNDEFINED_DEVICE_ID,UNDEFINED_INIT_ORDER Begin_control_dispatch %VxDName Control_Dispatch W32_DEVICEIOCONTROL, OnDeviceIoControl End_control_dispatch %VxDName VXD_LOCKED_CODE_ENDS VXD_PAGEABLE_CODE_SEG BeginProc OnDeviceIoControl assume esi:ptr DIOCParams .if [esi].dwIoControlCode==1 Push_Client_State VMMCall Begin_Nest_V86_Exec assume ebp:ptr Client_Byte_Reg_Struc mov [ebp].Client_dl,7 mov [ebp].Client_ah,2 mov eax,21h VMMCall Exec_Int VMMCall End_Nest_Exec Pop_Client_State EndI: .endif xor eax,eax ret EndProc OnDeviceIoControl VXD_PAGEABLE_CODE_ENDS end 讲解 Push_Client_State 这没什么好讲解的。当一个VxD接收到一个DeviceIoControl消息,ebp已经指向了当前VM的客户寄存器结构。我们调用Push_Client_State宏在堆栈中存储客户寄存器结构的状态。然后用Pop_Client_State宏恢复客户寄存器。 VMMCall Begin_Nest_V86_Exec 通过调用Begin_Nest_V86_Exec开始嵌套执行块。 assume ebp:ptr Client_Byte_Reg_Struc mov [ebp].Client_dl,7 mov [ebp].Client_ah,2 改变在客户寄存器中的dl和ah寄存器的映象。这个改变的值将由中断使用。 mov eax,21h VMMCall Exec_Int Exec_Int要求在eax存有一个中断号。我们想使用int 21h。等会我们调用Exec_Int去模拟中断。 VMMCall End_Nest_Exec Pop_Client_State 当Exec_Int返回,我们完成了嵌套执行块,并且由堆栈中恢复了客户寄存器结构的值。 你将听到你的PC喇叭发出一声响。  
2/2 首页 上一页 1 2 |