Node:Move structs, Next:, Previous:Xfer, Up:Low-level

18.5 How to move structs returned by real-mode services?

Q: My program uses the contents of a structure returned by a VBE function, but some of the struct members are garbled!

A: Most probably, this happens because of incorrect declaration of the structure in your program. Many people copy a declaration from some real-mode program, and that is exactly what gets them into trouble.

Here are some gotchas in this context:

For example, the following real-mode structure declaration:

 struct ncb {
   unsigned ncb_command;
   int ncb_status;
   char far *ncb_buffer;  /* a far pointer to a buffer */
   char ncb_name[32];
   int far (*ncb_dispatch)();  /* a pointer to a far function */
 };

should be converted to this in a DJGPP program:

 struct ncb {
   unsigned short ncb_command __attribute__((packed));
   short ncb_status __attribute__((packed));
   unsigned short ncb_buf_offset __attribute__((packed));
   unsigned short ncb_buf_segment __attribute__((packed));
   char ncb_name[32] __attribute__((packed));
   unsigned short ncb_dispatch_offset __attribute__((packed));
   unsigned short ncb_dispatch_segment __attribute__((packed));
 };

With the above declaration of struct ncb, the following real-mode code:

 int status = ncb.ncb_status;
 int value  = *(int far *)ncb.buf[3];

should read in DJGPP:

 short status, value;
 struct ncb ncb_struct

 /* Fetch the structure from the transfer buffer.  */
 dosmemget (__tb, sizeof (struct ncb), &ncb_struct);
 status = ncb_struct.ncb_status;
 value  = _farpeekw (_dos_ds,
                     ncb_struct.ncb_buf_segment*16
                     + ncb_buf_offset + 3);

In other words, you need to add code that moves the structure to and from the transfer buffer, and replace each pointer dereference with a call to an appropriate _farpeekX or _farpokeX function.