![]() |
China DOS Union-- Unite DOS · Advance DOS · Grow DOS --Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum |
| Guest | Log in | Register | Members | Search | China DOS Union |
|
中国DOS联盟论坛 The time now is 2026-11-01 01:17 |
47,815 topics / 349,930 posts / today 0 new / 48,290 members |
| DOS开发编程 & 发展交流 (开发室) » Ask: In DJGPP, there is no FP_OFF and FP_SEG macros. How can I assign a value to sregs.ds? |
| Printable Version 2,182 / 13 |
| Floor1 troylees | Posted 2006-08-06 18:39 |
| 初级用户 Posts 19 Credits 54 | |
|
Hello everyone!!
When I use int86x(0x13, &in, &out, &sregs) to perform an extended 13 interrupt call, I need to implement the following assignments: in.x.si = FP_OFF(&DAP_package); sregs.ds = FP_SEG(&DAP_package); However, these two macros are not available under the DJGPP compiler, and the address is 32-bit. May I ask all the experts if there is any way to solve this problem?? Thank you!! |
|
| Floor2 GOTOmsdos | Posted 2006-08-06 20:49 |
| 铂金会员 Posts 1,827 Credits 5,154 | |
|
For your reference:
#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; // Packet size (16 bytes) unsigned char Reserved; // ==0 unsigned int BlockCount; // Number of data blocks to transfer (in sectors) unsigned long BufferAddr;// Transfer buffer address (segment:offset) unsigned long BlockNum;// Starting absolute block address on disk //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 (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); } } I tried it and it works, but I don't know if it will always work, Just to say it generally works. |
|
| Floor3 troylees | Posted 2006-08-07 00:53 |
| 初级用户 Posts 19 Credits 54 | |
|
Thanks for GOTOmsdos's reply.
I have tried it, and the read - write failed. Maybe it is because DPMI is loaded. [ Last edited by troylees on 2006 - 8 - 7 at 00:56 ] |
|
| Floor4 GOTOmsdos | Posted 2006-08-07 02:23 |
| 铂金会员 Posts 1,827 Credits 5,154 | |
|
I didn't load DPMI, and it's okay
|
|
| Floor5 troylees | Posted 2006-08-07 08:03 |
| 初级用户 Posts 19 Credits 54 | |
|
To:GOTOmsdos
Because the programs compiled by DJGPP use 32-bit addresses, so you must load DPMI to run them. |
|
| Floor6 troylees | Posted 2006-08-08 12:24 |
| 初级用户 Posts 19 Credits 54 | |
|
To: dear all
The problem is finally solved. Because traditional interrupt calls can only access memory with a low address of 1M, and the buffer address of a DOS program in protected mode under DPMI may exceed 1M. So the solution is to use the low-address buffer predefined by DJGPP. Its address is defined as "__tb", and then use the dosmemput and dosmemget functions to implement the data exchange operation between the low-address and high-address buffers. For details, please see here http://www.delorie.com/djgpp/v2faq/faq18_2.html |
|
| Floor7 troylees | Posted 2006-08-08 12:27 |
| 初级用户 Posts 19 Credits 54 | |
|
You can try the following code:
#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); } |
|
| Floor8 BSLTT | Posted 2006-08-12 02:39 |
| 初级用户 Posts 18 Credits 59 | |
|
Hello, LZ! May I ask if the extended int13 you wrote can obtain disk parameters??
I got an error when calling function number 48H! INT 13 AH=48H Thanks~! [ Last edited by BSLTT on 2006-8-12 at 04:30 ] |
|
| Floor9 troylees | Posted 2006-08-12 23:31 |
| 初级用户 Posts 19 Credits 54 | |
|
The above function cannot obtain disk parameters. I suggest you take a look at Brother GOTOmsdos's post http://www.cn-dos.net/forum/viewthread.php?tid=21754&fpage=1&highlight=, the program in it has this function. Thanks for your attention!
|
|
| Floor10 BSLTT | Posted 2006-08-13 02:05 |
| 初级用户 Posts 18 Credits 59 | |
|
Thanks! The problem has been solved~! thank you~!
|
|
| Floor11 GOTOmsdos | Posted 2007-02-24 10:09 |
| 铂金会员 Posts 1,827 Credits 5,154 | |
|
Who can explain:
Why is the address __tb + 512 * sectorNum? What is the relationship with the number of hard disk sectors to be read and written?? |
|
| Floor12 troylees | Posted 2007-03-01 09:44 |
| 初级用户 Posts 19 Credits 54 | |
|
After executing __dpmi_int(0x13, ®), the hard disk sector information will be read into the memory starting from __tb, with a length of 512 * sectorNum. Therefore, you must copy the DAP_package to the address behind __tb + 512 * sectorNum to leave space.
I'm sorry, because I went home for winter vacation, so I'm replying now. Thanks for everyone's attention! |
|
| Floor13 GOTOmsdos | Posted 2007-03-01 10:56 |
| 铂金会员 Posts 1,827 Credits 5,154 | |
|
However, with your code, I have no problem compiling and running it, but it writes 0 bytes... Although the file size is there.
In addition, I downloaded two source codes, one from a Chinese person and one from a foreigner. The experimental results are: The Chinese one still reads and writes 0 bytes. The foreign one succeeded... I don't know the reason... |
|
| Floor14 troylees | Posted 2007-03-01 12:07 |
| 初级用户 Posts 19 Credits 54 | |
|
This is my code, you can try it, I have run it without problems:
#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; /* Packet size (16 bytes) */ unsigned char Reserved1; /* Set to 0 */ unsigned char BlockCount; /* Number of data blocks to transfer (in sectors) */ unsigned char Reserved2; /* Set to 0 */ unsigned short BufferAddrOFF; /* Buffer offset address */ unsigned short BufferAddrSEG; /* Buffer segment address */ unsigned long long LBA; /* Absolute block address on disk start */ } DiskAddressPacket; #pragma pack(pop) /* Use extended 13 interrupt to read and write large hard drives */ 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 for no write check, 1 for with */ 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); /* Enter sector number */ result = ExInt13(0x42, 0x80, log_sector, 1, buf); /* Read disk sector */ if (result!= 0) /* Determine if operation is successful */ { perror("Read Disk Error"); /* If not successful, display error */ exit(1); } printf("Read OK\n"); /* If successful, display "ok" */ for (i=446; i<512; i++) /* Loop to read partition table */ { if(buf[i] < 0) /* Convert negative ASCII values to positive */ temp = buf[i] + 256; else temp = buf[i]; sprintf(s, "%x", temp); /* Convert partition table content to hexadecimal format */ if(temp < 16) printf("0%s", s); /* Output display */ else printf("%s", s); printf(" "); if((i==461)||(i==477)||(i==493)||(i==509)) printf("\n"); } getch(); return(0); } |
|
|
[ Contact the Union admin team -
中国DOS联盟 -
Standard version ] Sponsored by ifanr Inc | © 2001–2023 |