📄 vxd-e9.html
字号:
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Iczelion">
<meta name="GENERATOR" content="Mozilla/4.7 [en] (Win98; I) [Netscape]">
<title>Virtual 8086 Memory Manager</title>
</head>
<body text="#FFFFFF" bgcolor="#000080" link="#FFFF00" vlink="#8080FF" alink="#FF00FF">
<center>
<h1>
<font face="Tahoma"><font color="#FFFF99">Virtual 8086 Memory Manager</font></font></h1></center>
<font face="Tahoma"></font>
<p><br><font face="Tahoma"><font size=-1>In the previous tutorial, you
learn how to simulate V86 interrupt. However, there is one problem that
hasn't been addressed yet: exchanging data between VxD and V86 code. We
will learn how to use the <b><font color="#FFFF99">V86 Memory Manager</font></b>
to our advantage in this regard.</font></font>
<br><font face="Tahoma"><font size=-1>Download <a href="files/vxdlabel.zip">the
example</a>.</font></font>
<h3>
<font face="Tahoma"><font color="#FF99FF">Some Theory</font></font></h3>
<font face="Tahoma"><font size=-1>If your VxD works with some V86 routines,
it will be necessary sooner or later to pass large chunks of data to and
from the V86 program. Passing a large amount of data via registers is out
of question. Your next attempt might be to allocate a block of memory in
ring 0 and pass the pointer to the memory block via some register so the
V86 code can access the data. If you do so, it will probably crash your
system because V86 addressing mode requires segment:offset pair, not the
linear address.</font></font>
<br><font face="Tahoma"><font size=-1>There are many solutions to that
problem. However, I choose an easy way here to demonstrate services provided
by the <b><font color="#FFFF99">V86 Memory Manager</font></b>.</font></font>
<br><font face="Tahoma"><font size=-1>If somehow you can find a free memory
block in the V86 region that you can use as the communcation buffer, that
would solve one of the problems. However, the pointer translation problem
remains. You can solve both problems by using the <b><font color="#FFFF99">V86
Memory Mananger</font></b>'s services.</font></font>
<br><font face="Tahoma"><font size=-1>The <b><font color="#FFFF99">V86
Memory Manager</font></b> is the static VxD that manages memory for V86
applications. It also provides EMS and XMS services to V86 apps and<b><font color="#FFFF99">
API translation</font></b> services to other VxDs. <b><font color="#FFFF99">API
translation</font></b> is actually the process of copying the data from
ring-0 into a buffer in V86 region and then passing the V86 address of
the data to the V86 code. No magic here. The <b><font color="#FFFF99">V86
Memory Manager </font></b>maintains a translation buffer which is a block
of memory in the V86 region for copying data from VxD to V86 region and
vice versa. Initially this translation buffer is 4 kilobytes. You can increase
the size of this buffer by calling <b><font color="#FFFF99">V86MMGR_Set_Mapping_Info</font></b>.</font></font>
<br><font face="Tahoma"><font size=-1>Now that you know about the translation
buffer, how can we copy data to and from it? This question involves two
services: <b><font color="#FFFF99">V86MMGR_Allocate_Buffer</font></b> and
<b><font color="#FFFF99">V86MMGR_Free_Buffer</font></b>.</font></font>
<br><font face="Tahoma"><font size=-1>V86MMGR_Allocate_Buffer allocates
a block of memory from the translation buffer and optionally copies the
data from ring 0 into the allocated V86 block. <b><font color="#FFFF99">V86MMGR_Free_Buffer</font></b>
does the reverse: it optionally copies the data from the allocated V86
block into a ring-0 buffer and frees the memory block allocated by <b><font color="#FFFF99">V86MMGR_Allocate_Buffer</font></b>.</font></font>
<br><font face="Tahoma"><font size=-1>Note that the <b><font color="#FFFF99">V86
Memory Manager</font></b> maintains the allocated buffers as a stack. That
means the allocation/deallocation must observe the first in/first out rule.
So if you make two calls to <b><font color="#FFFF99">V86MMGR_Allocate_Buffer</font></b>,
the first <b><font color="#FFFF99">V86MMGR_Free_Buffer</font></b> will
free the buffer allocated by the second <b><font color="#FFFF99">V86MMGR_Allocate_Buffer</font></b>
call.</font></font>
<br><font face="Tahoma"><font size=-1>We can now proceed to examine <b><font color="#FFFF99">V86MMGR_Allocate_Buffer</font></b>
definition. It's a register-based service.</font></font>
<br><b><font face="Tahoma"><font color="#66FF99"></font></font></b>
<center><table BORDER CELLPADDING=5 WIDTH="72%" >
<tr>
<td><b>ebx</b></td>
<td><b><font face="Tahoma"><font color="#66FF99">Handle of the current
VM</font></font></b></td>
</tr>
<tr>
<td><b>ebp</b></td>
<td><b><font face="Tahoma"><font color="#66FF99">Pointer to the current
VM's client register structure</font></font></b></td>
</tr>
<tr>
<td><b>ecx</b></td>
<td><b><font face="Tahoma"><font color="#66FF99">Number of bytes to allocate
from the translation buffer</font></font></b></td>
</tr>
<tr>
<td><b>carry flag</b></td>
<td><b><font face="Tahoma"><font color="#66FF99">clear if you don't want
to copy data from ring-0 buffer to the allocated block. Set if you want
to copy data from ring-0 buffer to the allocated block</font></font></b></td>
</tr>
<tr>
<td><b>fs:esi</b></td>
<td><b><font color="#66FF99">selector:offset of the ring-0 memory block
that contains the data to be copied to the allocated buffer. Ignored if
the carry flag is clear.</font></b></td>
</tr>
</table></center>
<font face="Tahoma"><font color="#FFFFFF"><font size=-1></font></font></font>
<p><font face="Tahoma"><font size=-1><font color="#FFFFFF">If the call
is successful, the carry flag is clear and ecx contains the number of bytes
actually allocated in the translation buffer. This value can be less than
the value you requested so you should keep this value for use with </font><b><font color="#FFFF99">V86MMGR_Free_Buffer
</font></b><font color="#FFFFFF">call later. edi contains the v86 address
of the allocated block with the segment in the high word, the offset in
the low word. The carry flag is set if an error occurs.</font></font></font>
<br><font face="Tahoma"><font size=-1><b><font color="#FFFF99">V86MMGR_Free_Buffer</font></b><font color="#FFFFFF">
accepts exactly the same parameters as </font><b><font color="#FFFF99">V86MMGR_Allocate_Buffer</font></b><font color="#FFFFFF">.</font></font></font>
<br><font face="Tahoma"><font size=-1>What actually occurs when you call
<b><font color="#FFFF99">V86MMGR_Allocate_Buffer </font></b>is that you
allocate a block of memory in V86 region of the current VM and obtain the
V86 address of that memory block in edi. We can use these services to pass
data to and from V86 interrupts.</font></font>
<br><font face="Tahoma"><font size=-1>In addition to API translation, the
V86 Memory Manager also offers API mapping service to other VxDs. API mapping
is actually the process of mapping some pages in extended memory into V86
region of every VM. You can use <b><font color="#FFFF99">V86MMGR_Map_Pages</font></b>
to do API mapping. With this service, the pages are mapped into <b>the
same</b> linear address in <b>every</b> VM. This waste address space if
you want to work with only one VM. Also API mapping is slower than API
translation so you should use API translation as much as possible. API
mapping is required for some V86 operation that needs to access the same
linear address and must be present in all VMs.</font></font>
<h3>
<font face="Tahoma"><font color="#FF99FF"><font size=+1>The Example</font></font></font></h3>
<font face="Tahoma"><font size=-1>This example uses API translation with
int 21h, 440Dh minor code 66h, Get Media ID, to obtain the volume label
of your first fixed disk.</font></font>
<blockquote><b><tt>;---------------------------------------------------------------</tt></b>
<br><b><tt>;
VxDLabel.asm</tt></b>
<br><b><tt>;---------------------------------------------------------------</tt></b>
<br><b><tt>.386p</tt></b>
<br><b><tt>include \masm\include\vmm.inc</tt></b>
<br><b><tt>include \masm\include\vwin32.inc</tt></b>
<br><b><tt>include \masm\include\v86mmgr.inc</tt></b><b><tt></tt></b>
<p><b><tt>VxDName TEXTEQU <VXDLABEL></tt></b>
<br><b><tt>ControlName TEXTEQU <VXDLABEL_Control></tt></b>
<br><b><tt>VxDMajorVersion TEXTEQU <1></tt></b>
<br><b><tt>VxDMinorVersion TEXTEQU <0></tt></b><b><tt></tt></b>
<p><b><tt>VxD_STATIC_DATA_SEG</tt></b>
<br><b><tt>VxD_STATIC_DATA_ENDS</tt></b><b><tt></tt></b>
<p><b><tt>VXD_LOCKED_CODE_SEG</tt></b>
<br><b><tt>;----------------------------------------------------------------------------</tt></b>
<br><b><tt>; Remember: The name of the vxd MUST be uppercase else it won't
work/unload</tt></b>
<br><b><tt>;----------------------------------------------------------------------------</tt></b>
<br><b><tt>DECLARE_VIRTUAL_DEVICE %VxDName,%VxDMajorVersion,%VxDMinorVersion,
%ControlName,UNDEFINED_DEVICE_ID,UNDEFINED_INIT_ORDER</tt></b><b><tt></tt></b>
<p><b><tt>Begin_control_dispatch %VxDName</tt></b>
<br><b><tt> Control_Dispatch
W32_DEVICEIOCONTROL, OnDeviceIoControl</tt></b>
<br><b><tt>End_control_dispatch %VxDName</tt></b><b><tt></tt></b>
<p><b><tt>VXD_LOCKED_CODE_ENDS</tt></b><b><tt></tt></b>
<p><b><tt>VXD_PAGEABLE_CODE_SEG</tt></b>
<br><b><tt>BeginProc OnDeviceIoControl</tt></b>
<br><b><tt> assume esi:ptr DIOCParams</tt></b>
<br><b><tt> .if [esi].dwIoControlCode==1</tt></b>
<br><b><tt><font color="#66FF99"> VMMCall Get_Sys_VM_Handle</font></tt></b>
<br><b><tt><font color="#66FF99"> mov Handle,ebx</font></tt></b>
<br><b><tt><font color="#66FF99"> assume ebx:ptr cb_s</font></tt></b>
<br><b><tt><font color="#66FF99"> mov ebp,[ebx+CB_Client_Pointer]</font></tt></b>
<br><b><tt><font color="#66FF99"> mov ecx,sizeof MID</font></tt></b>
<br><b><tt><font color="#66FF99"> stc</font></tt></b>
<br><b><tt><font color="#66FF99"> push esi</font></tt></b>
<br><b><tt><font color="#66FF99"> mov esi,OFFSET32 MediaID</font></tt></b>
<br><b><tt><font color="#66FF99"> push ds</font></tt></b>
<br><b><tt><font color="#66FF99"> pop fs</font></tt></b>
<br><b><tt><font color="#66FF99"> VxDCall V86MMGR_Allocate_Buffer</font></tt></b>
<br><b><tt><font color="#66FF99"> pop esi</font></tt></b>
<br><b><tt><font color="#66FF99"> jc EndI</font></tt></b>
<br><b><tt><font color="#66FF99"> mov AllocSize,ecx</font></tt></b>
<br><b><tt><font color="#66FF99"> Push_Client_State</font></tt></b>
<br><b><tt><font color="#66FF99"> VMMCall Begin_Nest_V86_Exec</font></tt></b>
<br><b><tt><font color="#66FF99"> assume ebp:ptr Client_Byte_Reg_Struc</font></tt></b>
<br><b><tt><font color="#66FF99"> mov [ebp].Client_ch,8</font></tt></b>
<br><b><tt><font color="#66FF99"> mov [ebp].Client_cl,66h</font></tt></b>
<br><b><tt><font color="#66FF99"> assume ebp:ptr Client_word_reg_struc</font></tt></b>
<br><b><tt><font color="#66FF99"> mov edx,edi</font></tt></b>
<br><b><tt><font color="#66FF99"> mov [ebp].Client_bx,3 ; drive A</font></tt></b>
<br><b><tt><font color="#66FF99"> mov [ebp].Client_ax,440dh</font></tt></b>
<br><b><tt><font color="#66FF99"> mov [ebp].Client_dx,dx</font></tt></b>
<br><b><tt><font color="#66FF99"> shr edx,16</font></tt></b>
<br><b><tt><font color="#66FF99"> mov [ebp].Client_ds,dx</font></tt></b>
<br><b><tt><font color="#66FF99"> mov eax,21h</font></tt></b>
<br><b><tt><font color="#66FF99"> VMMCall Exec_Int</font></tt></b>
<br><b><tt><font color="#66FF99"> VMMCall End_Nest_Exec</font></tt></b>
<br><b><tt><font color="#66FF99"> Pop_Client_State</font></tt></b>
<br><b><tt><font color="#66FF99"> ;-------------------------------</font></tt></b>
<br><b><tt><font color="#66FF99"> ; retrieve the data</font></tt></b>
<br><b><tt><font color="#66FF99"> ;-------------------------------</font></tt></b>
<br><b><tt><font color="#66FF99"> mov ecx,AllocSize</font></tt></b>
<br><b><tt><font color="#66FF99"> stc</font></tt></b>
<br><b><tt><font color="#66FF99"> mov ebx,Handle</font></tt></b>
<br><b><tt><font color="#66FF99"> push esi</font></tt></b>
<br><b><tt><font color="#66FF99"> mov esi,OFFSET32 MediaID</font></tt></b>
<br><b><tt><font color="#66FF99"> push ds</font></tt></b>
<br><b><tt><font color="#66FF99"> pop fs</font></tt></b>
<br><b><tt><font color="#66FF99"> VxDCall V86MMGR_Free_Buffer</font></tt></b>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -