Advocacy for Protected Mode Programming

Why use protected mode?

Why not? Protected Mode was designed by Intel to deal with the inadequacies of the 16-bit segemented architecture, mainly, the 1MB limit. Apparently 640KB wasn't enough for Bill Gates (Windows 95 runs very slowly on only 8MB of RAM), so why should it be enough for us? For those of you with BP7.0, you will understand this. Going from 640KB to 16MB of memory is a wonderful step.

Speed Considerations

Contrary to popular belief, Protected Mode is not faster than Real Mode. Loading segment registers is painfully slow, and some of the instructions are slower in PM (due to the protection mechanism and privilege level verification). Is this enough of a reason not to use Protected Mode? Of course not. Balance the ability to have 16MB of memory immediately accessable versus having to swap it in and out using XMS or EMS. Obviously PM wins out in this case.

16-bit Segmentation

So you think segmentation is evil? Well, consider this: You've been writing a game in Borland Pascal that directly accesses the screen. You load up ES with SegA000, load DI with your offset. You can directly access all of a Mode 13h screen with just DI. You know where screen memory is; you know how to access it. Now you decide to switch to Watcom C, which touts a powerful 32bit DOS extender. Quick, is EDI loaded with 0a000h, 0a00h, or 0a0000h? Okay, that took you four seconds to figure out. Now implement a keyboard handler that grabs interrupt 9 and dumps keys into a buffer you have allocated. Is that code going to run in a 32-bit segment or a 16-bit segment? Is that buffer accessable from Real Mode? Well, with Borland Pascal it is simple to redirect an interrupt, since the compiler knows that you are running in 16-bit PM (or RM). The Interrupt vector is readily available for you to do with as you please, and that buffer is located within the data segment. You've gotten used to 16-bit programming, segmentation, et al. Use this to your advantage.

Why Borland Pascal 7.0? Why not Delphi?

I'll answer the second question first. Do *you* want to perpetuate a curse that has been forced upon the naive consumer, namely Windoze? Borland Pascal is a DOS program; Delphi runs only under Windows. DOS may have flaws, but it is a comfortable programming platform with little (no?) intrusion from the OS. Borland Pascal is a wonderful programming environment with a blindingly fast compiler that only has a few drawbacks. One of these drawbacks is the 64KB limit. However, Borland accidently produced the perfect compiler. In Protected Mode each segment has a limit. By default that limit is 64KB (due to the fact that BP7.0 cannot do 32-bit addressing). If you allocate 256KB of memory, BP automatically allocates multiple contiguous 64KB segments. Why is this great? Because if you allocate memory [using a function such as GlobalAlloc] BP returns a THandle. A Thandle is the 16-bit selector of the memory (ie, load ES with the THandle, and use DI as the offset). The offset always starts at 0. This is useful because you can change the selector limit from 64KB to 4GB (gigabytes). With a little inline assembly you can use ES:[EDI] to access the memory. Yes, that is a 48-bit pointer, 16-bit selector, 32-bit offset. How many of your friends that use C can allocate multiple 4-gigabyte pointers? Not many, I presume. Make sure you gloat, especially to the ones that tried to convert you to C. How to implement and use 48-bit pointers is discussed in more detail later.

Disadvantages

Protected Mode is a little more difficult to program for. You will take a speed hit from accessing segment registers. You will also take a one cycle penalty for each 32-bit instruction you use (because you are running in a 16-bit code segment). Your code may stop looking like clean code and more of a mess. Here is a sample piece of code from my Zelda scrolling engine:
 for ty:=0 to 10 do
  for tx:=0 to 15 do
   PlayingField^.Putimage(tx*SprWidth,ty*SprHeight,ptr48(MapSprites,SprSize*
              ReadMem32b(ptr48(Map,longint(RealY+ty)*MapWidth+(RealX+tx)))));

(Please don't comment on how I could optimize this piece of code... I am well aware that the indexing could be done more efficiently outside of the procedure call. It is for example purposes only.).
-----------------------------
Previous PageUp one levelNext Page