回 帖 发 新 帖 刷新版面

主题:怎样用QB读取硬盘分区表

用了很多时间也搜索了不少资料也没有理出个头绪来,所用的程序只能正确读出一个扇区的数据,但我想读出6个扇区的数据应该怎样修改程序,能读取一个扇区数据的源程序为:
SUB Xint13 (M%, HdNum%, StartNum AS DOUBLE, BlockNum%, buff$)
ax% = 0: bx% = 1: cx% = 2: dx% = 3: bp% = 4
si% = 5: di% = 6: flags% = 7: ds% = 8: es% = 9
'IF LEN(Buff$) < 512 THEN Buff$ = SPACE$(512)
DIM reg%(9)
SELECT CASE M%
     CASE 2
         dat$ = STRING$(BlockNum% * 512, 0)
         reg%(ax%) = &H4200
     CASE 3
         dat$ = buff$
         reg%(ax%) = &H4300
     CASE 8
         reg%(ax%) = &H4800
         reg%(ds%) = SSEG(buff$)
         reg%(si%) = SADD(buff$)
         reg%(dx%) = HdNum%
         CALL INT86XOLD(&H13, reg%(), reg%())
         EXIT SUB
END SELECT
DatSegment% = SSEG(dat$)
DatOffset% = SADD(dat$)
dap$ = CHR$(&H10) + CHR$(0) + MKI$(BlockNum%) + MKI$(DatOffset%) + MKI$(DatSegment%) + MKL$(StartNum) + MKL$(0)
reg%(ds%) = SSEG(dap$)
reg%(si%) = SADD(dap$)
reg%(dx%) = HdNum%
CALL INT86XOLD(&H13, reg%(), reg%())
buff$ = dat$
END SUB


另一个程序为(功能一样):
'$INCLUDE: 'qb.bi'
DIM SHARED ax, bx, cx, dx, es
buff$ = SPACE$(512) '设置磁盘缓冲区
bx = SADD(buff$)   '获得缓冲区的偏移地址
es = VARSEG(buff$) '获得缓冲区的段址
OPEN "savehd.dat" FOR BINARY AS #1
ax = &H201 
cx = 1
dx = &H80
int13     ' 调用13号中断       
PUT #1, , buff$ 
CLOSE #1
PRINT "硬盘主引导区已被成功的保存到SAVEHD.DAT文件中!"
END

SUB int13
DIM InRegs AS RegTypeX
DIM OutRegs AS RegTypeX
InRegs.ax = ax
InRegs.bx = bx
InRegs.cx = cx
InRegs.dx = dx
InRegs.es = es
INTERRUPTX &H13, InRegs, OutRegs
ax = OutRegs.ax
bx = OutRegs.bx
cx = OutRegs.cx
dx = OutRegs.dx
es = OutRegs.es
END SUB

请高手指正,如何能正确读出前6个扇区的数据,跟指定扇区的数据。

回复列表 (共7个回复)

沙发

调用子程序Xint13 (M%, HdNum%, StartNum AS DOUBLE, BlockNum%, buff$)
M%的值,2为读扇区,3为写扇区,8为硬盘信息
HdNum%的值如果是&h80为第一个硬盘,81第一个硬盘
StartNum 为开始的扇区号
BlockNum 为数量
buff 为数据缓冲区。

如果你想读第一块硬盘的第3个扇区
调用子程序如下
Xint13 2, &H80, 3, 1, DataBuff$
上面参数值的含义,2读;&H80第一硬盘;3为从第3个扇区开始读;1为读一个扇区,DataBuff$为返回数据数据。

如果你想从第一块硬盘的第3个扇区开始读,读6个扇区
调用子程序如下
Xint13 2, &H80, 3, 6, DataBuff$
上面参数值的含义,2读;&H80第一硬盘;3为从第3个扇区开始读;6为读六个扇区,DataBuff$为返回数据数据。

由于限制读入的数量不能超过32个或者64个别

你发的另一个程序只能读小容量硬盘。

板凳

1楼,但不知您对获得硬盘容量方面有了解吗,能指点一下吧。谢谢

3 楼

关于怎样读取硬盘分区表的问题已经解决。可以结贴了

4 楼

如何获得硬盘的容量呢?如果你看过扩展INT13的编程资料就很简单了。
引用上面你提供的这个模块,用几条代码就可以直接获得硬盘容量

buff$ = SPACE$(512) '开辟一个数据缓冲区,调用中断后获得的数据就保存在这里面
Xint13 8, 0, 1, buff$ '调用子程序获得硬盘数据
运行后硬盘的数据就保存在buff$中了,然后对这个数据包(缓存)进行分析就可以得出硬盘的容量了。

查询扩展INT13资料获得如下结论:
1. 数据类型约定
BYTE 1 字节整型 ( 8 位 )
WORD 2 字节整型 ( 16 位 )
DWORD 4 字节整型 ( 32 位 )
QWORD 8 字节整型 ( 64 位 )

3. 驱动器参数数据包 Drive Parameters Packet
驱动器参数数据包是在扩展 Int13H 的取得驱动器参数子功能调用中
使用的数据包. 格式如下:
struct DriveParametersPacket
{
WORD InfoSize; // 数据包尺寸:
//(固定值,等于26,即1AH,指本结构所占用的存储空间)
WORD Flags; // 信息标志
DWORD Cylinders; // 磁盘柱面数
DWORD Heads; // 磁盘磁头数
DWORD SectorsPerTrack; // 每磁道扇区数
QWORD Sectors; // 磁盘总扇区数
WORD SectorSize; // 扇区尺寸 (以字节为单位)

---------------------------------------------------
在DOS编程中,一个字符是一个字节,一个字是两个字节
---------------------------------------------------

WORD是一个字的意思,占两个字节
DWORD是双字,占4个字节
QWORD是4字,占8个字节

对应上面的资料,磁盘数据在buff的位置及长度如下:
WORD InfoSize; // 数据包尺寸: 从第1个字符开始,长度2个字符,函数MID(BUFF,1,2)
WORD Flags; // 信息标志;从第3个字符开始,长度2个字符,函数MID(BUFF,3,2)
DWORD Cylinders; // 磁盘柱面数;从第3个字符开始,长度4个字符,函数MID(BUFF,5,4)
DWORD Heads; // 磁盘磁头数;从第3个字符开始,长度4个字符,函数MID(BUFF,9,4)
DWORD SectorsPerTrack; // 每磁道扇区数;从第3个字符开始,长度4个字符,函数MID(BUFF,13,4)
QWORD Sectors; // 磁盘总扇区数;从第3个字符开始,长度4个字符,函数MID(BUFF,17,8)
WORD SectorSize; // 扇区尺寸 (以字节为单位);从第3个字符开始,长度4个字符,函数MID(BUFF,25,2)

根据上面的资料得出,buff$中的第一个字是数据包的尺寸,第2个字是信息标志,第3个是双字,代表着磁盘的柱面数,然后是磁头.........
这样就简单了,如果我想知道磁盘的柱面数,用MID函数从第4个字节开始读,读4个字符,就是柱面数,然后把数据转换一下就出来了
例如,读取柱面,用MID$(buff$, 5, 4)语句读,如果读出的值是R9?3,这个是字符,要转换成数值。
“R9?3”的ASC码值如下所示:
R=82
9=57
?=63
3=35
要知道内存的储存格式是低位在前,高位在后。
所以整理一下 数值是 35 63 57 82 ,还是换成16进制容易看:23 3F 39 52,转换成10进制就是591346002,所以得出硬盘的柱面值就是591346002,当然硬盘的实际柱面不可能是这个值,我只是举例子。

如果按上面所说的读出硬盘的头,柱,扇,再计算就可以得出硬盘的总容量了,当然你也可以直接读出硬盘的总扇区,这个是LBA模式,头,柱,扇是CHS模式,都可以读出硬盘的容量。所以你要做硬盘程序,就必须了解数据包的格式。


实际上我也可以直接给代码你,我打这么多字实在是很辛苦,而给代码的话只需要复制,粘贴就可以了,而且代码也不长,但是“授人以鱼不如授人以渔 ”,还有一个原因,有些东西必须自己去研究才有乐趣,因为这个资料弄懂的话,你用C或者是汇编或者是其它什么语言来做都是一样的。

另外,你发的这个代码实际就是斑竹QB45写的,虽然能用,但是他写的并不严谨。正如你发的C代码,数据格式应该先定义,这样应该好一些,QB中也可以用下面的结构先定义。
TYPE  'DAP数据包结构
  ....
  '磁头数量
  '柱
  '扇区
  'LBA总扇区
......
END TYPE
QB当时在DOS也很强大,但是现在过时了,我认为是这样,详细的原理就这样了,很抱歉,我不能直接给你代码,所以也别直接找我要。

good luck!!!

5 楼

这是QB对中断调用的帖子
http://bbs.pfan.cn/post-20559.html

6 楼

真的很感谢TempReg的指点,一个话题只难加50分,没办法,经过您的指点我相信我已经明白了,其实就是一层纸,只是自己就在里面转来转去走不出这个误区。再次感谢您。

7 楼

加分不需要,我是看到你的帖子后,临时申请的一个ID,如果你的问题解决了,我也就废弃这个ID了,所以如果你成功了,请发帖说一声就好了,如果没有成功,愿意再交流和探讨。

还有一点要说明一下,我说斑竹QB45写的代码不严谨,不是轻视的意思,反正QB这个语言也就是这个风格,希望论坛里的粉丝别丢板砖。

建议你还是搜索一下斑竹QB45写的所有帖子(分2005年前和后的),仔细看看。就是抛开语言本身来说,有些帖子都是很有技术含量的。

我来回复

您尚未登录,请登录后再回复。点此登录或注册