|
DOSforever
金牌会员
积分 4639
发帖 2239
注册 2005-1-30
状态 离线
|
|
2006-7-2 05:30 |
|
|
qb45
高级用户
积分 677
发帖 194
注册 2003-9-13
状态 离线
|
『第
17 楼』:
Quote: | Originally posted by GOTOmsdos at 2006-6-30 07:45 PM:
成功了!
另:
我不懂QB,不知道QB能不能一次就把地址取出来?
,qb45的代码中:
MKI$变量是不是可以从buffdat$中取出一个地址值就可以了?
下頮.. |
|
我的程序只是从原理上演示一下,只想能实现扩展INT13的读写,并没有做优化什么的,如果要精简,只有把MKI$(d2%) 改为MKI$(SADD(buffdat$)) 实际上没有什么大的意义,但表面上看确实少了两个变量!
我觉得编程中,做硬盘小工具是很有意思的,而且很有价值。
在486的电脑上,BIOS很老,不支持扩展INT13,所以不能读写大硬盘,但是很有意思,我们可以利用IO端口在486电脑上来实现读写137G以内容量的硬盘。
希望大家能互相研究研究!
|
我(QB45)的照片与简历
http://www.programfan.com/club/showbbs.asp?id=197280
|
|
2006-7-2 17:47 |
|
|
qb45
高级用户
积分 677
发帖 194
注册 2003-9-13
状态 离线
|
|
2006-7-2 17:50 |
|
|
zyl910
中级用户
积分 282
发帖 126
注册 2006-5-17
状态 离线
|
『第
19 楼』:
Quote: | Originally posted by qb45 at 2006-7-2 17:50:
也不知道大家对端口读写硬盘感兴趣不 |
|
极有兴趣!
找这方面资料找了很久了
|
人类存在的目的就是试图理解人类为何存在 |
|
2006-7-2 18:16 |
|
|
darkradx
高级用户
积分 972
发帖 420
注册 2004-5-16
状态 离线
|
『第
20 楼』:
I/O方法, CIH里面似乎有用过
|
平生进退如飙风 |
|
2006-7-3 00:58 |
|
|
GOTOmsdos
铂金会员
C++启程者
积分 5154
发帖 1827
注册 2003-7-18
状态 离线
|
『第
21 楼』:
Quote: | Originally posted by DOSforever at 2006-7-2 05:30 AM:
我也不理解你的用意,既然 int13h 扩展调用不再使用CHS参数了,你怎么知道能读写1024个柱面呢?(应该说是第1024个柱面吧)难道你还换算过? |
|
对啊,这几天在研究硬盘读写,有以换算到极限进行测试的。。
|
|
2006-7-3 02:01 |
|
|
asbai
高级用户
积分 653
发帖 252
注册 2006-4-16
状态 离线
|
『第
22 楼』:
Quote: | Originally posted by DOSforever at 2005-6-30 00:00:
多谢楼上的解答,按照你的方法果然能够成功的读取了!
但是一开始我所得到的资料中确实是写 DI 的,而且在该文中不止一处提到。以下是我找到的 ... |
|
所以说这种技术规范一定要看官方标准的~~
|
|
2006-7-4 00:23 |
|
|
darkradx
高级用户
积分 972
发帖 420
注册 2004-5-16
状态 离线
|
|
2006-7-6 21:02 |
|
|
qb45
高级用户
积分 677
发帖 194
注册 2003-9-13
状态 离线
|
『第
24 楼』:
获得硬盘序列号(原程序)
这是一个用端口对硬盘编程例子
本程序在必须在DOS下运行,我在qb4.5版本下运行通过
主板上共有两个IDE接口,每个接口上又分主、从,所以可以接4个IDE设备,这4个端口号各不同,本程序用端口1F0-1F7是主板上的第一个IDE接口上的主接口,最常用的就是这个了。别的只是端口号不一样,编程方法原理一样。
'获得硬盘序列号的程序(非逻辑盘卷标,有的把C盘的卷标说成是硬盘序列号)
'代码:QBASIC,运行环境:DOS
OUT &H1F6, &HA0
OUT &h1F2,1
OUT &H1F3, 1
OUT &h1F4,1
OUT &h1F5,1
OUT &H1F7, &HEC '获得硬盘信息的命令
DO WHILE flag <> &H58
f lag = INP(&H1F7)
if inkey$=chr$(27) then '如果按ESC键,终止程序
print "无法获得硬盘序列号"
end
end if
LOOP
re$ = SPACE$(18)
FOR i% = 1 TO 18
READ a$
H$ = CHR$(VAL("&H" + a$))
MID$(re$, i%, 1) = H$
NEXT i%
duan% = varSEG(re$):offe% = SADD(re$)
DEF SEG = duan%
print "本硬盘的序列号为 ";
FOR i = 1 TO 16
CALL Absolute(r%, offe%) '调用在qb中的内嵌汇编机器码
r1% = r% AND &HFF
r2% = (r% AND &HFF00) / &H100
IF i > 9 AND i < 15THEN PRINT CHR$(r1%); CHR$(r2%);
NEXT i
DEF SEG
END
'此DATA中的数据为机器码,用于读端口字数据(qb中的端口语句只能按字节读写端口,不能按字读写)
DATA 55,89,e5,ba,f0,01,ed,86,e0,8b,5e,06,89,07,5d,ca,02 ,00
|
我(QB45)的照片与简历
http://www.programfan.com/club/showbbs.asp?id=197280
|
|
2006-7-9 10:56 |
|
|
GOTOmsdos
铂金会员
C++启程者
积分 5154
发帖 1827
注册 2003-7-18
状态 离线
|
|
2006-7-13 20:40 |
|
|
ninao99
新手上路
积分 12
发帖 5
注册 2007-9-11 来自 山西省太原市小店区
状态 离线
|
『第
26 楼』:
也编了个扩展int13 读硬盘程序(在win98 下测试通过)
//rdiskc.c
#include <stdio.h>
#include <math.h>
#include <alloc.h>
#include <string.h>
#ifndef NULL
#define NULL 0
#endif
typedef struct DiskAddressPacket{
char PacketSize;
char Reserved;
unsigned int BlockCount;
unsigned long BufferAddr;
int BlockNum[4];
}*DAP,DiskAddrPack;
extern void DREAD(DAP);
int main(int argc,char *argv[]){
int length,i=0,j=0,k=0,line=16;
unsigned char buffer[512];
DAP psi=(DAP)malloc(sizeof(DiskAddrPack));
if(argc==2&&!strcmp(argv[1],"/?")){
printf("\nbdexpen sector(0x,for 4 section) [line]\n\tline the line on show(must be 16 or 32)");
return 0;
}
if(argc!=5&&argc!=6)
return -1;
for(argv++,i=0;i<4;i++){
length=strlen(*argv);
if(length!=4)
return -2;
for(j=0;j<4;j++){
if((*argv)[j]>='0'&&(*argv)[j]<='9')
(*argv)[j]-='0';
else if((*argv)[j]>='a'&&(*argv)[j]<='f')
(*argv)[j]=(*argv)[j]-'a'+10;
else if((*argv)[j]>='A'&&(*argv)[j]<='F')
(*argv)[j]=(*argv)[j]-'A'+10;
else return -3;
}
psi->BlockNum[3-i]=(int)(*argv)[0]*16*16*16+(int)(*argv)[1]*16*16+(int)(*argv)[2]*16+(int)(*argv)[3];
argv++;
}
if(argc==6){
length=strlen(*argv);
for(j=0,k=0,line=0;j<length;){
if((*argv)[k]<48||(*argv)[k]>57)
return -4;
line+=((int)(*argv)[k++]-48)*(int)(pow(10,--length));
}
printf("%d\n",line);
if(line!=16&&line!=32)
line=16;
}
psi->PacketSize=16;
psi->Reserved=0;
psi->BlockCount=1;
psi->BufferAddr=(unsigned long)buffer;
DREAD(psi);
for(j=0;j<512/line;j++){
printf("%3x:",j*line);
for(k=0;k<line;k++){
printf("%4x",buffer[j*line+k]);
if(k==7||k==15&&line==32||k==23)
printf(" -");
}
printf("\t ");
for(k=0;k<line;k++){
if((buffer[j*line+k])<=128&&buffer[j*line+k]!='\n'&&buffer[j*line+k]!='\t')
printf("%c",buffer[j*line+k]);
else printf("\.");
}
printf("\n");
}
free(psi);
return 0;
}
//rdiska.asm
.model small
.data
.code
public _DREAD
_DREAD proc
push bp
mov bp,sp
push ds
push si
mov ah,42h
mov dl,80h
mov si,word ptr [bp+4]
int 13h
pop si
pop ds
pop bp
ret
_DREAD endp
end
编译连接后可以执行,可以像dos命令一样调用,不过没有写使用方法,大概就是把你要读的扇区的线性地址用16位分4段每段4位用空格隔开输入。另外还设置了一个16行/32行显示的切换开关第5个参数。
|
|
2008-10-27 19:13 |
|
|
netwinxp
高级用户
积分 741
发帖 366
注册 2007-7-25
状态 离线
|
『第
27 楼』:
Quote: | 在测试我的读写小硬盘的程序中,照理只能读写1023(3FF,1111111111)个柱面(0-1022)
但是,却能读写1024个柱面! |
|
对于支持INT13扩展的,只要最后的DAP地址是一样的,它们访问的就是同一个地方,CHS对它来说并没有多少实际意义,不支持的则会不一样,但问题是对于U盘来说,很多BIOS虽然报告支持INT13E,但事实上却是个假相(这也是U潘启动兼容性差的原因),这个问题的罪魁祸首是BIOS,其实符合ATA标准的硬盘真实的就是使用LBA地址来访问(不是古董型的硬盘真正的物理上不同柱面的扇区数不一样,CHS根本就没有意义)。
Quote: | 在486的电脑上,BIOS很老,不支持扩展INT13,所以不能读写大硬盘,但是很有意思,我们可以利用IO端口在486电脑上来实现读写137G以内容量的硬盘。 |
|
不可能的事,486的硬盘控制器芯片最多也就提供LBA28的地址,LBA48所需要的LBA地址是48位,所以无论如何也访问不了>137G的硬盘。
[ Last edited by netwinxp on 2008-11-5 at 17:46 ]
|
|
2008-10-29 16:04 |
|
|
0zwb
新手上路
积分 11
发帖 6
注册 2008-11-6
状态 离线
|
『第
28 楼』:
有没有最简单的修改硬盘号的工具?
|
|
2008-11-20 17:53 |
|