阅读:2018回复:18
关于底层硬盘读写的问题
我用ATA指令对硬盘进行操作,对读出来的MBR扇区数据和用DEBUG读出来的比较,发现我的程序读出来的数据中每个WORD的高8位都丢掉了, 为什么会这样呢?我的程序是用inport函数读硬盘的16bit data register的,和DEBUG一样运行在98下的DOS session中。
有哪位做过相似的开发?是否要先设置一下寄存器的参数? 紧急!紧急!请高手不吝赐教! |
|
最新喜欢:![]() |
沙发#
发布于:2003-01-09 10:21
你是对port:1f0-1f6进行读写吧?
我也碰到过这种问题,目前没法解决 另外,我得程序在98下工作不太正常,有时候能工作,有时候不能工作 |
|
板凳#
发布于:2003-01-09 10:40
是呀, 我是读1f0端口的。
我想是有些地方没设置好吧,不然怎么DEBUG在同样的环境可以正常工作呢? |
|
地板#
发布于:2003-01-09 10:40
因为你用DEBUG命令是字节读写,而ATA指令的I/O是字读写,所以你在DEBUG下读出来的数据每个字都丢掉了高半个字。在程序中对与端口1F0H或170H一定要用字读写。
|
|
|
地下室#
发布于:2003-01-09 10:49
这位兄弟:能否把你的读MBR(用port)的代码贴出来?
我想跟我的比较比较(我的工作不正常) 谢谢 |
|
5楼#
发布于:2003-01-09 10:52
shyeagle:
你理解的和我说的好像相反了。我用DEBUG读出来的是正常的,但我用inport(字读写)读丢了高8位。我也用inportb(字节读写)试过,但是也发现每两个字节中有一个字节没有读出来,因为1FO寄存器认为读一次就把两个字节读走了。 |
|
6楼#
发布于:2003-01-09 10:56
如果你编一个写的程序就非常明显了
只能对某个sector的偶数字节能读写 |
|
7楼#
发布于:2003-01-09 11:22
rouzhen:
你想要的是正常的MBR数据是吧. 你可以在98的dos下用DEBUG进行查看: debug 回车 -d 5000 看5000地址有没有数据,如果有就换另外无数据的内存 -l 5000 2 0 1 把c盘逻辑0扇区读到5000地址中 -d 5000 查看5000内容就是MBR数据了, d 命令一次显示0x80个byte 所以你要连续敲d 回车,就可以查完余下的数据 (5000 - 5200, 512bytes) |
|
8楼#
发布于:2003-01-09 11:50
shyeagle: 抱歉,我是理解反了,我以为你在DEBUG下用I命令的。 你用的是TC吧,我在MSC6.0下用inpw是没问题的。只要地址和读写模式对了就应该没问题。 |
|
|
9楼#
发布于:2003-01-09 12:08
skyeagle:
我是在TC3下做的,也试过用INPW代替INPORT,但结果一样. 你做的开发在对硬盘读写前要先设置些什么吗? 谢谢! |
|
10楼#
发布于:2003-01-09 12:11
我也编写了程序
在VC下面,console程序 另外,在BC下面也编了一样的16bit程序 但是我的程序有时候工作正常,有时候不工作(无法写硬盘) 下面是我的代码(): unsigned short out_buffer[512]; int i; memset(out_buffer,\'\\0\',512 ); out_buffer[0]=0xA; out_buffer[1]=0xB; _outp(0x1f6,0xB0);//对ide0上的从盘进行写 _outp(0x1F2,0x1); _outp(0x1f3,0x3); _outp(0x1F4,0x0); _outp(0x1F5,0x0); _outp(0x1F7,0x30); do {} while((_inp(0x1F7))==8); for(i=0;i<512;i++) { _outp(0x1F0,out_buffer); } 我的代码抄自http://www.nondot.org/sabre/os/files/Disk/HD_PORTS.asm 这段代码在纯dos下运行没问题,在98下时好时怀 你们帮我看看吧 |
|
11楼#
发布于:2003-01-09 13:12
skyeagle: 就是设置地址、读写方式(LBA/CHS)和设备号。从你的情况来看应该不是设置的问题,是不是因为在98下才出现这样的问题?直接用MS-DOS方式启动试试。 |
|
|
12楼#
发布于:2003-01-09 13:20
在纯dos下没有问题
这让我很郁闷 据有人说,windows对ide端口进行了保护 不知道你们碰到过这种问题没有? |
|
13楼#
发布于:2003-01-09 13:23
这是我以前做的程序片段。
//Ata IO port #define IOBASE_IDE0 0x1F7 #define IOBASE_IDE1 0x177 #define ATAP_DATA 0 //I/O for data IO #define ATAP_ERR 1 //O for error output #define ATAP_FEATURES 1 //I for features set #define ATAP_SECCOUNT 2 //I/O for sector count #define ATAP_SECNUMBER 3 //I/O for sector number/LBA:a7-a0 #define ATAP_CYLINDERLOW 4 //I/O for cylinder:a0-a7/LBA:a15-a8 #define ATAP_CYLINDERHIGH 5 //I/O for cylinder:a8-a15/LBA:a23-a16 #define ATAP_DEVICE 6 //I/O D6: 0=CHS D3-D0:head number // 1=LBA D3-D0:LBA:a27-a24 // D4: device number #define ATAP_STATUS 7 //O for status output #define ATAP_COMMAND 7 //I for command issue //Ata IO port end #define ATAC_READ 0x20 #define ATAC_WRITE 0x30 //Ata struct typedef struct ATA_INFO { BYTE mode; //LBA or CHS BYTE funcmode; //if ata mode BYTE FuncNo; BYTE DeviceNo; WORD iobase; BYTE cylindershigh; BYTE cylinderslow; BYTE sectorspertrace; BYTE headspercylinder; }ATA_INFO; ATA_INFO Atainfo={ATAM_LBA,ATAC_IDENTIFY,ATA_DEVICE0,IOBASE_IDE0}; far WORD * DiskBuffer; ///////////////////////////////////////////////////////////////// //name: FuncHDRW //function: read sectors from of write sectors to harddisk //parameter: function number // device number 0 through 3 // address mode LBA or CHS // address of begin sector // sum of sectors to read or write //input: iobase+ATAP_DEVICE<=device number (d4) // iobase+ATAP_COMMAND<=function number //output: iobase+ATAP_DEVICE=>device number (d4) // iobase+ATAP_STATUS=>0x58 //return: return YES //error: return NO ///////////////////////////////////////////////////////////////// int FuncHDRW(BYTE theFunc,BYTE theDevice,BYTE theMode,DWORD theAddr,BYTE theSecSum) { long i,thesum; BYTE thech; Atainfo.FuncNo=theFunc; if(theDevice&0x01) Atainfo.DeviceNo=ATA_DEVICE1; else Atainfo.DeviceNo=ATA_DEVICE0; Atainfo.DeviceNo|=theMode; if(theDevice&0x02) Atainfo.iobase=IOBASE_IDE1; else Atainfo.iobase=IOBASE_IDE0; Atainfo.sectorspertrace=theAddr & 0x0f; theAddr >>= 8; Atainfo.cylinderslow = theAddr & 0x0f; theAddr >>= 8; Atainfo.cylindershigh = theAddr & 0x0f; theAddr >>=8; Atainfo.DeviceNo += theAddr; outp(Atainfo.iobase+ATAP_SECCOUNT,theSecSum); outp(Atainfo.iobase+ATAP_SECNUMBER,Atainfo.sectorspertrace); outp(Atainfo.iobase+ATAP_CYLINDERLOW,Atainfo.cylinderslow); outp(Atainfo.iobase+ATAP_CYLINDERHIGH,Atainfo.cylindershigh); outp(Atainfo.iobase+ATAP_DEVICE,Atainfo.DeviceNo; outp(Atainfo.iobase+ATAP_COMMAND,Atainfo.FuncNo); i=0; thech=YES; while(inp(Atainfo.iobase+ATAP_STATUS)!=0x58) { i++; if(i==256) thech=NO; } if(thech) { if(theSecSum==0) thesum=256; else thesum=theSecSum; thesun *= 256; if(theFunc=ATAC_READ) for(i=0;i<thesum;i++,DiskBuffer++) *DiskBuffer=inpw(Atainfo.iobase+ATAP_DATA); else if(theFunc=ATAC_WRITE for(i=0;i<thesum;i++,DiskBuffer++) outpw(Atainfo.iobase+ATAP_DATA,*DiskBuffer); } return thech; } |
|
|
14楼#
发布于:2003-01-09 13:25
在纯dos下没有问题 那就对了。以前做的东西基本上都是与操作系统无关的。98下得用驱动。 |
|
|
15楼#
发布于:2003-01-09 13:53
skyeagle:
果然象你说的,在纯DOS下读扇区的数据是正常的,无丢失的. DEBUG对磁盘的操作可能是比较高层的函数,如absread等来 读写扇区,所以可以是正常的. 可以知道你的信箱吗?我的是frankpan@21cn.com QQ:28483120. 多多指教 |
|
16楼#
发布于:2003-01-09 14:15
skyeagle: shyeagle2003@vip.sina.com 另外我的ID是shyeagle,不是skyeagle。 |
|
|
17楼#
发布于:2003-01-09 16:09
shyeagle:
你贴的那个程序是在dos下运行的么? 不能在win98下运行? |
|
18楼#
发布于:2003-01-09 16:25
shyeagle: 是的。 |
|
|