Node:NEAR and FAR, Next:, Previous:16-bit code, Up:Converting

17.7 What should I do with those "near" and "far" declarations?

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.