|
DOSforever
金牌会员
     
积分 4639
发帖 2239
注册 2005-1-30
状态 离线
|
|
2006-7-2 05:30 |
|
|
qb45
高级用户
   
积分 677
发帖 194
注册 2003-9-13
状态 离线
|
『第 17 楼』:
使用 LLM 解释/回答一下
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以内容量的硬盘。
希望大家能互相研究研究!
Originally posted by GOTOmsdos at 2006-6-30 07:45 PM:
It worked!
Also:
I don't know QB, I don't know if QB can get the address at once?
In the code of qb45:
Can the MKI$ variable take out an address value from buffdat$?
Next...
My program is just a demonstration in principle, just wanting to realize the read and write of extended INT13, and has not done optimization or something. If you want to simplify, only change MKI$(d2%) to MKI$(SADD(buffdat$)). Actually, there is no great significance, but it does seem to have two fewer variables on the surface!
I think in programming, making hard disk utilities is very interesting and very valuable.
On a 486 computer, the BIOS is very old and does not support extended INT13, so large hard disks cannot be read and written, but it is very interesting. We can use IO ports on 486 computers to realize reading and writing of hard disks with a capacity of 137G or more.
Hope everyone can study each other!
|

我(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 楼』:
使用 LLM 解释/回答一下
Originally posted by qb45 at 2006-7-2 17:50:
也不知道大家对端口读写硬盘感兴趣不
极有兴趣!
找这方面资料找了很久了
Originally posted by qb45 at 2006-7-2 17:50:
I don't know if everyone is interested in port reading and writing to the hard disk
Extremely interested!
I've been looking for information on this for a long time
|

人类存在的目的就是试图理解人类为何存在 |
|
2006-7-2 18:16 |
|
|
darkradx
高级用户
   
积分 972
发帖 420
注册 2004-5-16
状态 离线
|
『第 20 楼』:
使用 LLM 解释/回答一下
I/O方法, CIH里面似乎有用过
I/O methods, it seems that CIH has used them
|

平生进退如飙风 |
|
2006-7-3 00:58 |
|
|
GOTOmsdos
铂金会员
       C++启程者
积分 5154
发帖 1827
注册 2003-7-18
状态 离线
|
『第 21 楼』:
使用 LLM 解释/回答一下
Originally posted by DOSforever at 2006-7-2 05:30 AM:
我也不理解你的用意,既然 int13h 扩展调用不再使用CHS参数了,你怎么知道能读写1024个柱面呢?(应该说是第1024个柱面吧)难道你还换算过?
对啊,这几天在研究硬盘读写,有以换算到极限进行测试的。。
Originally posted by DOSforever at 2006-7-2 05:30 AM:
I also don't understand your intention. Since the extended call of int13h no longer uses CHS parameters, how do you know that you can read and write 1024 cylinders? (It should be the 1024th cylinder) Did you also convert it?
Yeah, I've been researching hard disk reading and writing these days, and there are tests with conversion to the limit.
|
|
2006-7-3 02:01 |
|
|
asbai
高级用户
   
积分 653
发帖 252
注册 2006-4-16
状态 离线
|
『第 22 楼』:
使用 LLM 解释/回答一下
Originally posted by DOSforever at 2005-6-30 00:00:
多谢楼上的解答,按照你的方法果然能够成功的读取了!
但是一开始我所得到的资料中确实是写 DI 的,而且在该文中不止一处提到。以下是我找到的 ...
所以说这种技术规范一定要看官方标准的~~ <img src="images/smilies/face-wink.png" align="absmiddle" border="0">
So this kind of technical specification must be looked at the official standards~~ ;)
|
|
2006-7-4 00:23 |
|
|
darkradx
高级用户
   
积分 972
发帖 420
注册 2004-5-16
状态 离线
|
|
2006-7-6 21:02 |
|
|
qb45
高级用户
   
积分 677
发帖 194
注册 2003-9-13
状态 离线
|
『第 24 楼』:
使用 LLM 解释/回答一下
获得硬盘序列号(原程序)
这是一个用端口对硬盘编程例子
本程序在必须在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
Obtaining the Hard Drive Serial Number (Original Program)
This is an example of programming the hard drive using ports
This program must run under DOS and I have run it successfully under QB4.5 version
There are two IDE interfaces on the mainboard, and each interface is divided into master and slave, so 4 IDE devices can be connected. The port numbers of these 4 are different. This program uses ports 1F0 - 1F7, which are the master interface on the first IDE interface of the mainboard, and this is the most commonly used one. The others just have different port numbers, and the programming method and principle are the same.
'Program to obtain the hard drive serial number (not the logical disk volume label, some people say the volume label of drive C is the hard drive serial number)
'Code: QBASIC, running environment: DOS
OUT &H1F6, &HA0
OUT &h1F2,1
OUT &H1F3, 1
OUT &h1F4,1
OUT &h1F5,1
OUT &H1F7, &HEC 'Command to obtain hard drive information
DO WHILE flag <> &H58
f lag = INP(&H1F7)
if inkey$=chr$(27) then 'If the ESC key is pressed, terminate the program
print "Failed to obtain the hard drive serial number"
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 "The serial number of this hard drive is ";
FOR i = 1 TO 16
CALL Absolute(r%, offe%) 'Call the embedded assembly machine code in 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
'The data in this DATA is machine code, used to read port word data (the port statements in QB can only read and write ports byte by byte, not word by word)
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 下测试通过)
使用 LLM 解释/回答一下
//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个参数。
```c
//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;
}*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;
DAP psi=(DAP)malloc(sizeof(DiskAddrPack));
if(argc==2&&!strcmp(argv,"/?")){
printf("\nbdexpen sector(0x,for 4 section) \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)>='0'&&(*argv)<='9')
(*argv)-='0';
else if((*argv)>='a'&&(*argv)<='f')
(*argv)=(*argv)-'a'+10;
else if((*argv)>='A'&&(*argv)<='F')
(*argv)=(*argv)-'A'+10;
else return -3;
}
psi->BlockNum=(int)(*argv)*16*16*16+(int)(*argv)*16*16+(int)(*argv)*16+(int)(*argv);
argv++;
}
if(argc==6){
length=strlen(*argv);
for(j=0,k=0,line=0;j<length;){
if((*argv)<48||(*argv)>57)
return -4;
line+=((int)(*argv)-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);
if(k==7||k==15&&line==32||k==23)
printf(" -");
}
printf("\t ");
for(k=0;k<line;k++){
if((buffer)<=128&&buffer!='\n'&&buffer!='\t')
printf("%c",buffer);
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
int 13h
pop si
pop ds
pop bp
ret
_DREAD endp
end
After compiling and linking, it can be executed and can be called like a DOS command. However, the usage method is not written. Probably, you input the linear address of the sector you want to read, divided into 4 segments of 4 bits each in 16 - bit hexadecimal, separated by spaces. In addition, there is a switch to switch between displaying 16 lines/32 lines as the 5th parameter.
```
|
|
2008-10-27 19:13 |
|
|
netwinxp
高级用户
   
积分 741
发帖 366
注册 2007-7-25
状态 离线
|
『第 27 楼』:
使用 LLM 解释/回答一下
在测试我的读写小硬盘的程序中,照理只能读写1023(3FF,1111111111)个柱面(0-1022)
但是,却能读写1024个柱面!
对于支持INT13扩展的,只要最后的DAP地址是一样的,它们访问的就是同一个地方,CHS对它来说并没有多少实际意义,不支持的则会不一样,但问题是对于U盘来说,很多BIOS虽然报告支持INT13E,但事实上却是个假相(这也是U潘启动兼容性差的原因),这个问题的罪魁祸首是BIOS,其实符合ATA标准的硬盘真实的就是使用LBA地址来访问(不是古董型的硬盘真正的物理上不同柱面的扇区数不一样,CHS根本就没有意义)。
在486的电脑上,BIOS很老,不支持扩展INT13,所以不能读写大硬盘,但是很有意思,我们可以利用IO端口在486电脑上来实现读写137G以内容量的硬盘。
不可能的事,486的硬盘控制器芯片最多也就提供LBA28的地址,LBA48所需要的LBA地址是48位,所以无论如何也访问不了>137G的硬盘。
Last edited by netwinxp on 2008-11-5 at 17:46 ]
In the program I tested for reading and writing small hard drives, theoretically, it should only be able to read and write 1023 (3FF, 1111111111) cylinders (0-1022). However, it can read and write 1024 cylinders!
For those supporting INT13 extensions, as long as the final DAP address is the same, they are accessing the same place. CHS has little practical meaning to it. For those not supporting, it will be different. But the problem is that for USB flash drives, many BIOSes report supporting INT13E, but in fact, it's a false appearance (this is also the reason for the poor compatibility of USB flash drive booting). The culprit of this problem is the BIOS. Actually, hard drives conforming to the ATA standard truly use LBA addresses to access (it's not that the number of sectors in different cylinders of antique hard drives is truly different, and CHS is根本 meaningless).
On a 486 computer, the BIOS is very old and doesn't support extended INT13, so it can't read and write large hard drives. But interestingly, we can use I/O ports on a 486 computer to implement reading and writing of hard drives with a capacity of over 137G.
Impossible. The hard drive controller chip of a 486 at most provides LBA28 addresses. The LBA address required for LBA48 is 48 bits, so it can never access a hard drive with a capacity >137G.
Last edited by netwinxp on 2008-11-5 at 17:46 ]
|
|
2008-10-29 16:04 |
|
|
0zwb
新手上路

积分 11
发帖 6
注册 2008-11-6
状态 离线
|
『第 28 楼』:
使用 LLM 解释/回答一下
有没有最简单的修改硬盘号的工具?
Is there the simplest tool to modify the hard disk number?
|
|
2008-11-20 17:53 |
|
|