Node:Move structs,
Next:Fat DS,
Previous:Xfer,
Up:Low-level
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:
__attribute__((packed))
, to
prevent GCC from inserting gaps between some members to make them
properly aligned for faster access (see how gcc aligns structs). C programs can
declare the entire struct with the packed attribute, but C++
programs will need to declare each member with it, see __attribute__((packed)).
dosmemget
or one of the
_farpeekX
family of functions in conjunction with the
_dos_ds
selector, and don't forget to compute the linear address
as segment * 16 + offset
, where segment
and offset
are taken from the struct members converted from the far pointers in the
original real-mode code.
__dpmi_simulate_real_mode_procedure_retf
to call it
(don't forget to zero out the .x.ss
and .x.sp
members of
the __dpmi_regs
structure!). See real-mode functions.
int
s, whereas in DJGPP, an
int
is 32-bit wide. You need to change the declaration of all
struct members from int
to short
, and from unsigned
to unsigned short
.
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.