This section is for people who have used 16-bit DOS compilers before and are now using DJGPP. There are many things that you need to know about DJGPP, and 32-bit compilers in general, that are different from what you are used to. Here are some of them.
Integers (type int) are four bytes (32 bits) instead of two (16 bits). Type short is still two bytes and long is still four bytes, but now int is the same size as long instead of short. Math using "long" integers is as fast as (if not faster than) "short" integers, so you get big integers and fast performance.
All DJGPP programs are like "tiny" model. There is no such thing as a "far pointer" in DJGPP, but then most of the reasons for needing them have gone away also (since your "tiny" segment is 4Gb long). If you are used to programming with "far" keyword or the MKFP, FP_OFS or FP_SEG macros, you'll have to change your ways, because they just don't work in DJGPP. Note: You can emulate "far" pointers with the <sys/farptr.h> routines, but using them means porting your code.
Pointers are also four bytes (32 bits), but they are near pointers. A far pointer would be six bytes (two for the selector, and four for the offset), if they were supported that way. Many DPMI calls take both a 16-bit selector and a 32-bit offset.
You can't make a pointer to video memory by casting an int like 0xa0000000 to a pointer. It won't work. On the same token, you can't use 0x00400000 to access the BIOS data area, or 0x00000000 to access the interrupt table. Remember, pointers are four bytes, so when you cast these, you are getting a near pointer to your own program's data! Accessing these pointers will either corrupt or crash your program, and won't access the memory you expect. This is a good thing, in a way, because it prevents you from dereferencing "garbage" pointers and wiping out your computer. To access video and BIOS memory, use functions like dosmemget or those in <sys/farptr.h>.
You can't make pointers by shifting segments and adding offsets, because segments don't start every 16 bytes like they do in real mode. Segments can start anywhere, and often do. If you make up your own segment values, your program will almost definitely crash. There are DPMI functions that allocate and define segments if you need to do so.
You can't use pseudo-registers (like _AX = i) or inline assembler (like asm mov ax,i). For starters, it's unlikely that the code will do what you expect in a 32-bit environment, and also the syntax isn't supported in DJGPP. However, gcc supports a much more powerful inline assembler (the gcc manual desribes it), and its inline functions are usually as optimal as hand-assembler anyway.
You can't just call DOS by issuing a software interrupt (int86()) if the interrupt uses pointers to data. Why? Because you're running in 32-bit protected mode and DOS is running in 16-bit real mode, so it doesn't know what to do with your pointers. See the "Interacting with DOS" chapter in this guide for more info.
Interrupt calling and handling is completely different. More later.
If you try to dereference a NULL pointer, bad things happen. However, in DJGPP the bad things happen to your program's execution, not to your PC or its hard drive, like with other compilers. If you're running under a DPMI 1.0 server (or cwsdpmi), the DPMI server will detect this, stop your program, and tell you what happened. If not, your program will do strange things (or worse, act normally until the worst possible time). With 16-bit compilers, you're likely to corrupt your own program (or worse, in "large" model, you corrupt the interrupt table and your computer hangs).
|webmaster donations bookstore||delorie software privacy|
|Copyright © 2014 by root||Updated Oct 23 2014|