![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-10-31 22:05 |
共 47,815 主题排行 / 349,930 发帖 / 今日 0 篇 / 48,290 会员排行 |
| DOS开发编程 & 发展交流 (开发室) » 请教:DJGPP中没有FP_OFF和FP_SEG宏,怎么可以给sregs.ds赋值呢? |
| 可打印版本 2,178 / 13 |
| 第1楼 troylees | 发表于 2006-08-06 18:39 |
| 初级用户 发帖 19 积分 54 | |
|
请教: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位的,请问各位高手有什么办法解决呢?? 谢谢!! |
|
| 第2楼 GOTOmsdos | 发表于 2006-08-06 20:49 |
| 铂金会员 发帖 1,827 积分 5,154 | |
|
共你参考:
#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); } } 我试过可以的,但不知道是不是永远可以, 只能说一般可以。。 |
|
| 第3楼 troylees | 发表于 2006-08-07 00:53 |
| 初级用户 发帖 19 积分 54 | |
|
感谢GOTOmsdos的回复
我试过了,读写失败,可能是由于加载了dpmi的原因吧 [ Last edited by troylees on 2006-8-7 at 00:56 ] |
|
| 第4楼 GOTOmsdos | 发表于 2006-08-07 02:23 |
| 铂金会员 发帖 1,827 积分 5,154 | |
|
我没有 加载 DPMI ,是可以的
|
|
| 第5楼 troylees | 发表于 2006-08-07 08:03 |
| 初级用户 发帖 19 积分 54 | |
|
To:GOTOmsdos
因为DJGPP编译的程序是使用32位地址的,所以一定要加载DPMI 才能运行的 |
|
| 第6楼 troylees | 发表于 2006-08-08 12:24 |
| 初级用户 发帖 19 积分 54 | |
|
To: dear all
问题终于解决了,是因为传统的中断调用只能访问低地址1M的内存,而DPMI下保护模式的DOS程序的缓冲区地址可能会超过1M,所以解决办法是,使用DJGPP预定义的低地址缓冲区,他的地址定义在“__tb”,然后用dosmemput和dosmemget函数实现低地址和高地址缓存区的数据交换操作。 详细看看这里http://www.delorie.com/djgpp/v2faq/faq18_2.html |
|
| 第7楼 troylees | 发表于 2006-08-08 12:27 |
| 初级用户 发帖 19 积分 54 | |
|
大家可以试试以下代码:
#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); } |
|
| 第8楼 BSLTT | 发表于 2006-08-12 02:39 |
| 初级用户 发帖 18 积分 59 | |
|
楼主你好!请问你所写的这个扩展int13是否可以获取磁盘参数
呢?? 我在调用工能号48H时出错! INT 13 AH=48H 谢谢~! [ Last edited by BSLTT on 2006-8-12 at 04:30 ] |
|
| 第9楼 troylees | 发表于 2006-08-12 23:31 |
| 初级用户 发帖 19 积分 54 | |
|
以上这个函数不可以获取磁盘参数,我建议你看看GOTOmsdos兄的帖子
http://www.cn-dos.net/forum/viewthread.php?tid=21754&fpage=1&highlight= 里面的程序有这个功能,谢谢关注!! |
|
| 第10楼 BSLTT | 发表于 2006-08-13 02:05 |
| 初级用户 发帖 18 积分 59 | |
|
谢谢!问题已解决~! thank you~!
|
|
| 第11楼 GOTOmsdos | 发表于 2007-02-24 10:09 |
| 铂金会员 发帖 1,827 积分 5,154 | |
|
谁能解释一下:
地址为什么是 __tb + 512 * sectorNum ? 跟要读写的硬盘扇区的个数有什么关系?? |
|
| 第12楼 troylees | 发表于 2007-03-01 09:44 |
| 初级用户 发帖 19 积分 54 | |
|
__dpmi_int(0x13, ®)执行以后就会把硬盘扇区信息读出到__tb开始的内存,长度为512 * sectorNum,所以,你必须把DAP_package复制到__tb + 512 * sectorNum地址后面以留出空间。
不好意思,因为寒假回家了,所以现在才回复,多谢大家的关注!! |
|
| 第13楼 GOTOmsdos | 发表于 2007-03-01 10:56 |
| 铂金会员 发帖 1,827 积分 5,154 | |
|
可是,你的这个代码,我编译,运行都没问题,可是,写的是0字节...尽管文件大小是有的
另外,下了两个源码,一个国人的,一个老外的,实验结果是: 国人的仍然是读写成0字节 老外的成功了... 不知道什么原因... |
|
| 第14楼 troylees | 发表于 2007-03-01 12:07 |
| 初级用户 发帖 19 积分 54 | |
|
这是我的代码,你试试吧,我运行过没问题的:
#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); } |
|
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |