标题: 请教:DJGPP中没有FP_OFF和FP_SEG宏,怎么可以给sregs.ds赋值呢? 
[打印本页]
作者: troylees     
时间: 2006-8-6 18:39    
标题: 请教:DJGPP中没有FP_OFF和FP_SEG宏,怎么可以给sregs.ds赋值呢?
大家好!!
     我在用int86x(0x13,&in,&out,&sregs)执行扩展13中断调用的时候,要实现以下的赋值:
                in.x.si = FP_OFF(&DAP_package);
	sregs.ds =  FP_SEG(&DAP_package);
     但是,在DJGPP编译器下没有这两个宏,而且地址又是32位的,请问各位高手有什么办法解决呢??
谢谢!!
作者: GOTOmsdos     
时间: 2006-8-6 20:49
共你参考:
#include <dos.h>
#include <stdio.h>
void main(){
unsigned char buf[51200];
FILE *f;
unsigned int i=0;
union REGS in,out;
struct DiskAddressPacket
{
unsigned char PacketSize; // 数据包尺寸(16字节)
unsigned char Reserved; // ==0
unsigned int BlockCount; // 要传输的数据块个数(以扇区为单位)
unsigned long BufferAddr;// 传输缓冲地址(segment:offset)
unsigned long BlockNum;// 磁盘起始绝对块地址
//unsigned long ab;
}dap={16,0,100,0,16434490};
dap.BufferAddr=(unsigned long)buf;
in.h.ah = 0x42;
in.h.dl = 0x81;
in.x.si = &dap;
//磁盘地址数据包(Disk Address Packet)
f=fopen("int13ext.dat","wb+");
fclose(f);
for(;i<1000;i++)
{
int86(0x13,&in,&out);
f=fopen("int13ext.dat","ab+");
fwrite(buf,512,100,f);
fclose(f);
dap.BlockNum+=100;
printf("100 * %u\n",i);
}
}
我试过可以的,但不知道是不是永远可以,
只能说一般可以。。
作者: troylees     
时间: 2006-8-7 00:53
感谢GOTOmsdos的回复
   我试过了,读写失败,可能是由于加载了dpmi的原因吧
 Last edited by troylees on 2006-8-7 at 00:56 ]
作者: GOTOmsdos     
时间: 2006-8-7 02:23
我没有 加载 DPMI ,是可以的
作者: troylees     
时间: 2006-8-7 08:03
To:GOTOmsdos
   因为DJGPP编译的程序是使用32位地址的,所以一定要加载DPMI 才能运行的
作者: troylees     
时间: 2006-8-8 12:24
作者: troylees     
时间: 2006-8-8 12:27
大家可以试试以下代码:
#define HANDLE_PRAGMA_PACK_PUSH_POP 1
#pragma pack(push,1)
typedef struct 
{
unsigned char  PacketSize;          
unsigned char  Reserved1;            
unsigned char  BlockCount;           		 
unsigned char  Reserved2;            
unsigned short BufferAddrOFF;       
unsigned short BufferAddrSEG;     
 unsigned long long  LBA;          
}
DiskAddressPacket;
#pragma pack(pop)
int ExInt13(char cmd, char driveNum, unsigned long startSector, int sectorNum, char buf[])
{
	  __dpmi_regs  reg;
    DiskAddressPacket DAP_package;
    memset(&DAP_package, 0, sizeof(DiskAddressPacket));
    
    DAP_package.PacketSize = sizeof(DiskAddressPacket);
	  DAP_package.BlockCount = sectorNum;
	  DAP_package.BufferAddrOFF = __tb & 0x0F;
	  DAP_package.BufferAddrSEG = __tb >> 4;
    DAP_package.LBA = startSector;
    dosmemput(&DAP_package, sizeof(DiskAddressPacket), __tb + 512 * sectorNum);
    reg.h.ah = cmd;
    reg.h.dl = driveNum;
    reg.h.al = 0;                           
    reg.x.ds = (__tb + 512 * sectorNum) >> 4;
    reg.x.si = (__tb + 512 * sectorNum) & 0x0F;
    
    __dpmi_int(0x13, ®);
    if((reg.x.flags & 0x0001) == 0)
    {
       dosmemget(__tb, 512 * sectorNum, buf);
       return 0;
    }
    else
       return(reg.h.ah);
}
作者: BSLTT     
时间: 2006-8-12 02:39
楼主你好!请问你所写的这个扩展int13是否可以获取磁盘参数
呢??
我在调用工能号48H时出错!
INT 13  AH=48H
谢谢~!
 Last edited by BSLTT on 2006-8-12 at 04:30 ]
作者: troylees     
时间: 2006-8-12 23:31
作者: BSLTT     
时间: 2006-8-13 02:05
谢谢!问题已解决~! thank you~!
作者: GOTOmsdos     
时间: 2007-2-24 10:09
谁能解释一下:
地址为什么是 __tb + 512 * sectorNum ?
跟要读写的硬盘扇区的个数有什么关系??
作者: troylees     
时间: 2007-3-1 09:44
__dpmi_int(0x13, ®)执行以后就会把硬盘扇区信息读出到__tb开始的内存,长度为512 * sectorNum,所以,你必须把DAP_package复制到__tb + 512 * sectorNum地址后面以留出空间。
不好意思,因为寒假回家了,所以现在才回复,多谢大家的关注!!
作者: GOTOmsdos     
时间: 2007-3-1 10:56
可是,你的这个代码,我编译,运行都没问题,可是,写的是0字节...尽管文件大小是有的 
另外,下了两个源码,一个国人的,一个老外的,实验结果是:
国人的仍然是读写成0字节
老外的成功了...
不知道什么原因...
作者: troylees     
时间: 2007-3-1 12:07
这是我的代码,你试试吧,我运行过没问题的:
#include <stdio.h> 
#include <conio.h> 
#include <process.h> 
#include <bios.h> 
#include <dos.h>
#include <math.h> 
#include <dir.h> 
#include <stdlib.h> 
#include <string.h>                      
#include <unistd.h>                      
#include <sys/stat.h>
#include <sys/movedata.h>
#include <go32.h>
#include <dpmi.h>
#define HANDLE_PRAGMA_PACK_PUSH_POP 1
#pragma pack(push,1)
typedef struct 
{
		 unsigned char  PacketSize;           /* 数据包尺寸(16字节) */
		 unsigned char  Reserved1;            /* 置0 */
		 unsigned char  BlockCount;           /* 要传输的数据块个数(以扇区为单位) */
		 unsigned char  Reserved2;            /* 置0 */
		 unsigned short BufferAddrOFF;        /* 缓冲区偏移地址 */
		 unsigned short BufferAddrSEG;        /* 缓冲区段地址 */
		 unsigned long long  LBA;             /* 磁盘起始绝对块地址*/
}
DiskAddressPacket;
#pragma pack(pop)
/* 用扩展13中断,读写大硬盘 */               
int ExInt13(char cmd, char driveNum, unsigned long startSector, int sectorNum, char buf[])
{
	  __dpmi_regs  reg;
    DiskAddressPacket DAP_package;
    memset(&DAP_package, 0, sizeof(DiskAddressPacket));
    
    DAP_package.PacketSize = sizeof(DiskAddressPacket);
	  DAP_package.BlockCount = sectorNum;
	  DAP_package.BufferAddrOFF = __tb & 0x0F;
	  DAP_package.BufferAddrSEG = __tb >> 4;
    DAP_package.LBA = startSector;
    dosmemput(&DAP_package, sizeof(DiskAddressPacket), __tb + 512 * sectorNum);
    reg.h.ah = cmd;
    reg.h.dl = driveNum;
    reg.h.al = 0;                            /* 0 为无写校验,1为有 */
    reg.x.ds = (__tb + 512 * sectorNum) >> 4;
    reg.x.si = (__tb + 512 * sectorNum) & 0x0F;
    
    __dpmi_int(0x13, ®);
    if((reg.x.flags & 0x0001) == 0)
    {
       dosmemget(__tb, 512 * sectorNum, buf);
       return 0;
    }
    else
       return(reg.h.ah);
}
int main(void) 
{ 
   int  i, result, temp; 
   unsigned long log_sector;
   char buf[512]; 
   char s[5];
   scanf("%lu", &log_sector);                   /*输入扇区号*/
   result = ExInt13(0x42, 0x80, log_sector, 1, buf);    /*读磁盘扇区*/
   if (result!= 0)                              /*判断是否操作成功*/
   { 
      perror("Read Disk Error");                /*不成功显示出错*/
      exit(1); 
   } 
   printf("Read OK\n");                          /*成功显示"ok"*/
   for (i=446; i<512; i++)                       /*循环读出分区表*/
   {  
   	  if(buf[i] < 0)                             /*将ascii为负值的变为正值*/
   	     temp = buf[i] + 256;
   	  else
   	     temp = buf[i];
      sprintf(s, "%x", temp);                     /*将分区表内容格式转换为16进制*/
      
      if(temp < 16)        
         printf("0%s", s);                        /*输出显示*/
      else
         printf("%s", s);   
      printf(" ");
      
      if((i==461)||(i==477)||(i==493)||(i==509))
         printf("\n"); 
   } 
   
   getch(); 
   return(0); 
}