Node:NEAR and FAR,
Next:Pseudo-registers,
Previous:16-bit code,
Up:Converting
Q: I have this program that I need to port to DJGPP, but it is full
of pointers and functions declared with the "near" and "far"
keywords which GCC doesn't grok. What shall I do?
Q: A program written for a 16-bit compiler uses the MK_FP or _MK_FP
macro, but DJGPP doesn't seem to have it. How should I port it?
Q: How do I compute a segment and an offset of a protected-mode
address?
A: In DJGPP you use a flat address space with no segmentation (it is a kind of tiny model, since CS = DS = SS, but with a very large segment), so you don't need far pointers in the sense they are used in 16-bit code. Just define away those keywords and you will be fine:
#define far #define near #define huge #define _far #define _near #define _huge
Alternatively, you could add suitable -D
switches to the GCC
command line, like this:
gcc -Dfar= -Dnear= -Dhuge= -c myprog.c
Macros that create far pointers from the segment and offset (usually
called MK_FP
or _MK_FP
) are mostly used in 16-bit code to
access certain absolute addresses on memory-mapped peripheral devices,
like the video RAM. These chores are done differently in DJGPP. Here's
one possible way to express MK_FP
in DJGPP (courtesy of Charles Sandmann):
#include <sys/nearptr.h> #include <crt0.h> void * MK_FP (unsigned short seg, unsigned short ofs) { if ( !(_crt0_startup_flags & _CRT0_FLAG_NEARPTR) ) if (!__djgpp_nearptr_enable ()) return (void *)0; return (void *) (seg*16 + ofs + __djgpp_conventional_base); }
The above uses the DJGPP nearptr
facility, which effectively
disables memory protection and doesn't work on some systems (e.g. NT);
if you prefer to use farptr
functions (which are safer and work
with all known DPMI hosts), you will need to rewrite the code that uses
these macros, so don't bother writing a replacement for the MK_FP
macro itself. The details are described in Accessing absolute addresses, below.
Macros that extract the segment and the offset from a far pointer
(called FP_SEG
and FP_OFF
) are required in 16-bit code to
pass addresses in registers when calling real-mode DOS or BIOS services,
like functions of interrupt 21h. See How to call real-mode interrupt functions, which describes how that should be done in DJGPP; here, too,
you won't need to port the macros but instead rewrite the code that
calls the DOS or BIOS service. In particular, you cannot
compute a real-mode segment and offset of a protected-mode address,
because real-mode addresses can only access the first 1MB of memory,
whereas the variables of DJGPP programs all live above the 1MB mark.