China DOS Union

-- Unite DOS · Advance DOS · Grow DOS --

Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum
DOS stands for freedom, openness and progress. Let us work hard, learn from the openness and GNU spirit of FreeDOS and Linux, and together build and grow a free GNU GPL world!

中国DOS联盟论坛
The time now is 2026-08-01 16:35
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » Ask: In DJGPP, there is no FP_OFF and FP_SEG macros. How can I assign a value to sregs.ds? View 1,972 Replies 13
Original Poster Posted 2006-08-06 18:39 ·  中国 广东 广州 荔湾区 电信
初级用户
Credits 54
Posts 19
Joined 2006-07-31 11:15
20-year member
UID 59547
Status Offline
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!!
Floor 2 Posted 2006-08-06 20:49 ·  中国 广东 广州 教育网
铂金会员
★★★★
C++启程者
Credits 5,154
Posts 1,827
Joined 2003-07-18 00:00
23-year member
UID 7105
Gender Male
Status Offline
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.
Floor 3 Posted 2006-08-07 00:53 ·  中国 广东 广州 荔湾区 电信
初级用户
Credits 54
Posts 19
Joined 2006-07-31 11:15
20-year member
UID 59547
Status Offline
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 ]
Floor 4 Posted 2006-08-07 02:23 ·  中国 广东 广州 教育网
铂金会员
★★★★
C++启程者
Credits 5,154
Posts 1,827
Joined 2003-07-18 00:00
23-year member
UID 7105
Gender Male
Status Offline
I didn't load DPMI, and it's okay
Floor 5 Posted 2006-08-07 08:03 ·  中国 广东 广州 荔湾区 电信
初级用户
Credits 54
Posts 19
Joined 2006-07-31 11:15
20-year member
UID 59547
Status Offline
To:GOTOmsdos
Because the programs compiled by DJGPP use 32-bit addresses, so you must load DPMI to run them.
Floor 6 Posted 2006-08-08 12:24 ·  中国 广东 广州 番禺区 电信
初级用户
Credits 54
Posts 19
Joined 2006-07-31 11:15
20-year member
UID 59547
Status Offline
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
Floor 7 Posted 2006-08-08 12:27 ·  中国 广东 广州 番禺区 电信
初级用户
Credits 54
Posts 19
Joined 2006-07-31 11:15
20-year member
UID 59547
Status Offline
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, &reg);

if((reg.x.flags & 0x0001) == 0)
{
dosmemget(__tb, 512 * sectorNum, buf);
return 0;
}
else
return(reg.h.ah);
}
Floor 8 Posted 2006-08-12 02:39 ·  中国 广西 柳州 电信
初级用户
Credits 59
Posts 18
Joined 2005-12-25 08:50
20-year member
UID 47830
Status Offline
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 ]
Floor 9 Posted 2006-08-12 23:31 ·  中国 广东 广州 花都区 电信
初级用户
Credits 54
Posts 19
Joined 2006-07-31 11:15
20-year member
UID 59547
Status Offline
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!
Floor 10 Posted 2006-08-13 02:05 ·  中国 广西 柳州 电信
初级用户
Credits 59
Posts 18
Joined 2005-12-25 08:50
20-year member
UID 47830
Status Offline
Thanks! The problem has been solved~! thank you~!
Floor 11 Posted 2007-02-24 10:09 ·  中国 广东 广州 教育网
铂金会员
★★★★
C++启程者
Credits 5,154
Posts 1,827
Joined 2003-07-18 00:00
23-year member
UID 7105
Gender Male
Status Offline
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??
Floor 12 Posted 2007-03-01 09:44 ·  中国 广东 广州 番禺区 电信
初级用户
Credits 54
Posts 19
Joined 2006-07-31 11:15
20-year member
UID 59547
Status Offline
After executing __dpmi_int(0x13, &reg), 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!
Floor 13 Posted 2007-03-01 10:56 ·  中国 广东 广州 教育网
铂金会员
★★★★
C++启程者
Credits 5,154
Posts 1,827
Joined 2003-07-18 00:00
23-year member
UID 7105
Gender Male
Status Offline
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...
Floor 14 Posted 2007-03-01 12:07 ·  中国 广东 广州 番禺区 电信
初级用户
Credits 54
Posts 19
Joined 2006-07-31 11:15
20-year member
UID 59547
Status Offline
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, &reg);

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);
}
Forum Jump: