关于VXD 方面的问题?????

hk318 2000-05-20 08:35:00
各位软件高手:
小弟在开发一个VXD时,(使用VToolsD for 95/98)
在myDevice类中自定义一个函数
bool ReadDiskSector(LPSTR buffer)//读软盘物理第1扇区 到 buffer 中
在其中使用中断函数 int 13h
{
DWORD mm_buf=(DWORD)buffer;
__asm{
mov eax,201h
mov ebx,mm_buf
mov cx,0001h
mov dx,0000h
int 13h
}
.
.
.
}
但一执行中断就蓝屏,报告错误。 本人百思不得其解????!!!
不是说在Ring0级下的Vxd 文件中可以使用任意低级操作吗?(难道不包括int 13h??)
还望行家指点!!
另:关于传入的buffer参数,是在Win32程序中申请的内存缓冲(use new )
是否可以直接传给 Ebx 寄存器? 还是要做变动?( in Vxd )
因为:
used "C " in DOS mode
{
resg.x.ax=0x0201; /* 02 for Read, 03 for Write ,05 for Format */
reg.x.bx=FP_OFF(buffer);
reg.x.cx=0x0001 /* for boot sector */
reg.x.dx=0 ; /* for drive A *
sreg.es=FP_SEG(buffer);
int86x(0x13,®,®,&sreg);
}
...全文
92 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
shak 2001-09-01
  • 打赏
  • 举报
回复
我帮你推上去
DingBoy 2000-05-21
  • 打赏
  • 举报
回复
哈哈~~~~~~Ring0级别的int可不是这样用的!

--------------------------------------------------------------------
windows9x下绝对读写硬盘扇区的例程
由于win9x下由win32程序对硬盘的写操作被屏蔽,所以绝对硬盘的读写的思路在于
设法转入16位程序,因此有两种方法可以达到这种目的:使用THUNK机制调用16位DLL
或用VxD转到16位方式,我觉得用THUNK太麻烦,其实VxD挺好编的,而且用起来也方便,
当时也是出于学习目的,编了这么一个VxD,还是挺好用的,我看精华区对这个问题的讨
论好像没有什么结果,就把它贴出来,算是班门弄斧吧!
我是用DDK编的,主要是因为我当时是出于学习.

//这是程序的主要部分,其中有一些宏定义,从字面上就能知道是干什么的,我就不罗嗦
//了
DWORD _stdcall CVXD_W32_DeviceIOControl(LPDIOC lpDIOCParms,
CLIENT_STRUCT *pRegs)
{
DWORD dwRetVal = 0,retu;
DWORD *i;
PVMMCB hVM;
DIOC_REGISTERS *lpReg,*lpOutReg;
CLIENT_STRUCT saveregs;
DWORD PageNum;
WORD PageOff;
DWORD Address;
DWORD V86PageNum,MyPage;
WORD seg,offset;

hVM=Get_Cur_VM_Handle();
i=(DWORD *)(lpDIOCParms->lpvOutBuffer);
lpReg=(DIOC_REGISTERS *)(lpDIOCParms->lpvInBuffer);
lpOutReg=(DIOC_REGISTERS *)(lpDIOCParms->lpvOutBuffer);
switch(lpDIOCParms->dwIoControlCode)
{
.
.
.
case 2:
if(lpDIOCParms->cbInBuffer!=sizeof(DIOC_REGISTERS))
return dwRetVal=-1;

//保存当前虚拟机的寄存器状态
_asm push edi
_asm lea edi,saveregs
VMMCall(Save_Client_State);
_asm pop edi

//输入的参数,具体怎么用看INT13的说明吧
_ClientEAX=lpReg->reg_EAX;
_ClientEDX=lpReg->reg_EDX;
_ClientECX=lpReg->reg_ECX;
_ClientEFlags=lpReg->reg_Flags;

/* 以下这一段是编写这个VxD时要考虑的主要问题:把缓冲区的地址映射入虚拟86的地址
区,Win32中用的都是线性地址,先根据它求出页面号,再把缓冲区所在的页映射到虚拟86区
中去,下面程序中有一个Bug,它没有考虑到缓冲区所占页面大于一页时的情形,事实上,缓
冲区可能处在叶面的边界上,而且它的大小可能超过一页,这些都要根据上面参数中给出
的缓冲区大小计算,当时我嫌麻烦,随便应付了一下.用的时候要把这段代码改一下
*/
PageNum=(lpReg->reg_EBX)>>12;
PageOff=(lpReg->reg_EBX)&0xfff;
_asm{
push 0
push 1
push 10
push hVM
push PageNum
}
VMMCall(_LinMapIntoV86);
_asm add esp,14h
_asm mov retu,eax
_asm mov MyPage,edx //返回的页面号在edx寄存器中
if(retu==0) return 3;//这是我自己胡乱选的错误码,你可以自己定成
//其它值
Address=(MyPage<<12)+PageOff;//计算新的线性地址
seg=LOWORD(Address>>4); //把线性地址转化成传统的段:偏
offset=LOWORD(Address-(seg<<4)); //移量的形式
_ClientAltES=seg;//这里一定不能弄错了,在Win32 Ring3程序中用的
//是_ClientES,而虚拟86方式下用的段寄存器则在
//_ClientAltES中,所以要用它
_ClientBX=offset;

//xixi,好戏开始了
VMMCall(Begin_Nest_V86_Exec);//这一句使得系统转入虚拟86方式
_asm mov eax,13h
VMMCall(Exec_Int);//发出int 13h中断调用
//保存返回值
if(lpDIOCParms->cbOutBuffer==sizeof(DIOC_REGISTERS))
{
lpOutReg->reg_Flags=_ClientEFlags;
lpOutReg->reg_EAX=_ClientEAX;
lpOutReg->reg_EBX=_ClientEBX;
lpOutReg->reg_ECX=_ClientECX;
lpOutReg->reg_EDX=_ClientEDX;
}
End_Nest_Exec();//退出虚拟86方式

//轻轻地我走了,正如我轻轻地来,我挥一挥衣袖,不带走一片云彩
_asm push esi
_asm lea esi,saveregs
VMMCall(Restore_Client_State);
_asm pop esi
//这一段取消原来的映射
VMMCall(_GetNulPageHandle);
_asm mov PageNum,eax
_asm{
push 0
push 0
push 1
push 10
push hVM
push PageNum
}
VMMCall(_MapIntoV86);
_asm add esp,18h

//OK
return dwRetVal=0;
}
return dwRetVal;
}

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧