阅读:983回复:2
谁能帮我解答这个问题?
关于硬盘读写原理的疑惑
远在DOS年代,执行磁盘的读写操作归根结底都是通过如下的方式 mov ah,2(read)/3(write) mov al,要写的扇区数 mov cx,起始扇区 mov dx,80(硬盘)/0(floppy) int 13 当硬盘的空间一度增大到超过8.4G时,传统的BIOS int 13h已经不能访问到大于8.4的空间了。于是乎 Extention BIOS应运而出,新的扩展int 13h不再通过寄存器传参数而代之以一个参数包,包的大小可以大至10h字节不等,并以DS:SI的值指向这个包。于是就成了 mov ds,seg Package mov si,offset package mov ax,4200h(read)/4300h(write) int 13h 这样就解决了8.4G以上的硬盘不能识别的问题。但到此为至,所有的对硬盘的操作还是16位的。 到了windows win32时代,对硬盘的读写也变成了32位的,这样的传统的读/写盘中断int 13h又不能适应,于是又推出了win32环境下的32位的读/写盘方法。这就是为什么DOS下的关于拦截磁盘读写操作的TSR不能在win32 下工作的原因。当然你可以禁止(通过某些设置)这项功能而继续沿用老的16位磁盘操作。 但本人对32位环境下读/写磁盘的物理根本原理还没完全弄明白,首先:Windows对硬盘的读/写还是是通过调用BIOS的Int13h?还是有专门自己的服务函数? 知道的朋友还请不要保留,以解小弟之迷惑,谢谢!!! |
|
|
沙发#
发布于:2001-12-30 21:14
看你是在什么系统下使用。
如果是9x,Me,你应该使用Win32.vxd service. BOOL VOpenFile( /*OUT*/ HANDLE *phFile, /*IN */ const char * szFileName, /*IN */ BOOL bWriteMode //added by zdhe ) { ULONG ulMode; ulMode = bWriteMode ? 0x2022 : 0x2020; *phFile = NULL; _asm mov esi, szFileName _asm mov edi, esi _asm xor ecx, ecx _asm mov ebx, ulMode _asm mov edx, 0x1 _asm mov ax, 0x716c _asm push 0x21 VMMcall( Exec_VxD_Int ) _asm jb error_return _asm mov ebx, phFile _asm mov [ebx], eax return TRUE; error_return: return FALSE; } BOOL VReadFile( /*IN */ HANDLE hFile, /*OUT*/ void * pBuffer, /*IN */ USHORT wReadBytes, /*IN */ ULONG dwOffset ) { _asm mov ebx, hFile _asm lea eax, dwOffset _asm mov dx, [eax] _asm mov cx, [eax+0x2] _asm mov ax, 0x4200 _asm push 0x21 VMMcall( Exec_VxD_Int ) _asm jb error_return_move _asm mov ebx, hFile _asm xor ecx, ecx _asm mov cx, wReadBytes _asm mov edx, pBuffer _asm mov ax, 0x3f00 _asm push 0x21 VMMcall( Exec_VxD_Int ) _asm jb error_return_read _asm cmp ax, wReadBytes //ax != wReadBytes _asm jnz error_return_read return TRUE; error_return_move: DPRTINF(\"vreadfile move error\\n\"); return FALSE; error_return_read: DPRTINF(\"vreadfile read error\\n\"); return FALSE; } void VCloseFile( /*IN */ HANDLE hFile ) { _asm mov ebx, hFile _asm mov ax, 0x3e00 _asm push 0x21 VMMcall( Exec_VxD_Int ) } BOOL VCreateFile( /*OUT*/ HANDLE * phFile, /*IN */ const char * szFileName ) { *phFile = NULL; _asm mov edx, szFileName _asm mov ecx, 0 _asm mov ax, 0x3c00 _asm push 0x21 VMMcall( Exec_VxD_Int ) _asm jb error_return _asm mov ebx, phFile _asm mov [ebx], eax return TRUE; error_return: return FALSE; } BOOL VWriteFile( /*IN */ HANDLE hFile, /*OUT*/ void *pBuffer, /*IN */ USHORT wWriteBytes, /*IN */ ULONG dwOffset ) { HANDLE *phFile; phFile = &hFile; if (dwOffset == -1 ) //append mode { _asm mov ebx, phFile _asm mov ebx, [ebx] _asm mov dx, 0 _asm mov cx, 0 _asm mov ax, 0x4202 _asm push 0x21 VMMcall( Exec_VxD_Int ) _asm jb error_return_move }else //write to abs position { _asm mov ebx, phFile _asm mov ebx, [ebx] _asm lea eax, dwOffset _asm mov dx, [eax] _asm mov cx, [eax+0x2] _asm mov ax, 0x4200 _asm push 0x21 VMMcall( Exec_VxD_Int ) _asm jb error_return_move } _asm mov ebx, phFile _asm mov ebx, [ebx] _asm xor ecx, ecx _asm mov cx, wWriteBytes _asm mov edx, pBuffer _asm mov ax, 0x4000 _asm push 0x21 VMMcall( Exec_VxD_Int ) _asm jb error_return_write _asm cmp ax, wWriteBytes //ax != wWriteBytes _asm jnz error_return_write return TRUE; error_return_move: DPRTINF(\"******************************Move Faild \\n\"); return FALSE; error_return_write: DPRTINF(\"******************************Write Faild \\n\"); return FALSE; } 如果是WINNT/2000/XP,因该使用 InitializeObjectAttributes ZwCreateFile来进行文件输入输出访问。 |
|
板凳#
发布于:2001-12-31 09:17
非常感谢你抽空回答我的问题,让我得到了很大的启发,再一次感谢你,我的Email是 lydmusic@163.net,希望我们以后可以成为朋友!:)
你的回答让我得知,Win9x/Me下,磁盘的读/写是通过调用VxD Service来执行一个软件中断(Int21h),然后DOS中断Int21h的磁盘读/写服务实际上是BIOS Int13h的一个封装(DOS文件IO.sys封装了这些服务,并且MSDOS.sys IO.sys在2000下也存在),因此在DOS下,所有的通过调用Int21h的磁盘读/写操作最终都会调用Int13h。 所以我的一个悬而未决的疑问是在Win9x/Me,或者2000下,还有其它的操作系统(UNIX/Linux)等,它们的磁盘读/写的最终本质上会不会和DOS一样是通过调用BIOS Int13h来实现的 ? |
|
|