A CRASH COURSE IN PROTECTED MODE By Adam Seychell After my release of DOS32 V1.2 a lot of people were asking for basic help in protected mode programming. If you already know what a selector is then there is probably no need for you to read this file. Ok you know all about the 8086 ( or a 386 in real mode ) architecture and what to know about this fantastic protected mode stuff. I'll start off saying that I think real mode on the 386 is like driving a car that is stuck in first gear. There is the potential of a lot of power but it is not being used. It really degrades the 386 processor and was not designed to normally operate in this mode. Even the Intel data book states "Real mode is required primarily to set up the processor for Protected Mode operation". SEGMENTATION OF THE INTEL 80x86 A segment is a block of memory that starts at a fixed base address and has a set length. As you should already know that *every* memory reference by the CPU requires both a SEGMENT value and a OFFSET value to be specified. The OFFSET value is the location relative to the base address of the segment. The SEGMENT value contains the information for the segment. I am going to explain very basically how this SEGMENT value is interpreted by the 80386 to give the parameters of segments. In protected mode this SEGMENT value is interpreted completely different than in real mode and Virtual 86 mode. The SEGMENT values are now called "selectors". You'll see why when finished reading this file. So whenever you load a segment register you are loading it with a selector. The Selector is word length and contains three different fields. Bits 0..1 Request Privilege level ( just set this to zero ) Bit 2 Table Indicator 0 = Global Descriptor Table 1 = Local Descriptor Table Bits 3..15 The INDEX field value of the desired descriptor in the GDT This index value points to a descriptor in the table. The GLOBAL DESCRIPTOR TABLE (GDT) The Global Descriptor Table ( GDT ) is a table of DESCRIPTORS and it's stored in memory. The address of this table is given in a special register of the CPU and is called the global descriptor table register. There always must be a GDT when in protected mode because it is in this table where all of the segments are defined. Each DESCRIPTOR ( stored in the GDT ) contains the complete information about a segment. It is a description of the segment. Each Descriptor is 64 bits long and contains many different fields. I'll explain the fields later. The INDEX field ( stored in bits 3..15 of any segment register ) selects a descriptor to use for the type of segment wanted. So the only segments the programmer can use are the available descriptors in the GDT. Example code: Suppose you what to access location 012345h in your data segment and you were told that the descriptor for your data segment is descriptor number 6 in the Global Descriptor Table. Assume that the Global Descriptor Table has already been set up and built for you ( example, as in DOS32). Solution: We need to load a segment register (SS,DS,FS,GS,ES) with a value so that it will select (or index ) descriptor number 6 of the GDT. Then reference the address with a instruction that will use this loaded segment register. The segment register (FS,DS,GS,SS,CS or ES) must be loaded with the following three fields, Request Privilege level ( Bits 0..1 ) = 0 (always) Table Indicator ( bit 2 ) = 0 Index ( bits 3..15 ) = 6 mov ax,0000000110000b ;load DS with the selector value mov ds,ax mov byte ptr DS:[ 012345h ],0 ; Using the DS segment register The 386 has hardware for a complete multitasking system. There are several different types of descriptors available in the GDT for managing multitasking. You don't need to know about all the different descriptors just to program in protected mode. Just the info above is enough. All you need to know to program in protected mode is what descriptors are available to you and what are the selector values of these descriptors. Also the base address of the segment may be need to be known. See the file DOS32.DOC for obtaining the selector values. There are two groups of descriptors 1) CODE/DATA descriptors which are used for any code and data segments. 2) SYSTEM descriptors are used for the multitasking system of the 386. These type of descriptors will never need to be used for programming applications. Format of a code and data descriptor BITS description if the field ---------------------------------------------------------------- 0..15 SEGMENT LIMIT 0...15 16..39 SEGMENT BASE 0..23 40 (A) accessed bit 41..43 (TYPE) 0 = SEE BELOW 44 (0) 0 = code/data descriptor 1 = system descriptor 45..46 (DPL) Descriptor Privilege level 47 (P) Segment Present bit 48..50 SEGMENT LIMIT 16..19 51..52 (AVL) 2 bits available for the OS 53 zero for future processors 54 Default Operation size used by code descriptors only 55 Granularly: 1 = segment limit = limit field *1000h 0 = segment limit = limit field 56..63 SEGMENT BASE 24..31 format of TYPE field bit 2 Executable (E) 0 = Descriptor is data type 1 Expansion Direction (ED) 0 = Expand up 1 = Expand up 0 Writeable (W) W = 0 data segment is read only W = 1 data segment is R/W bit 2 Executable (E) 1 = Descriptor is code type 1 Conforming (C) ( I don't understand ) 0 Readable (R) R = 0 Code segment execute only R = 1 Code segment is Readable I'd better stop here, I am confusing myself. As you can see there is more to a segment that just it's base address and limit. The three descriptors that are avalible in DOS32 all have limits of 0ffffffffh (4GB). This means that the offsets can be any value. For example, the instruction XOR EAX,ES:[0FFFFFFFFh] in allowed. If you happen to load an invalid selector value into one of the segment registers then the 386 will report an General Protection exception ( interrupt 13 ). In protected mode this exception is also used for many other invalid settings. This was only meant to be a rough introduction to the protected mode segmentation mechanism of the 80386+. I hope I did not make this sound too complicated so that you've been put off with the whole idea of protected mode programming. If you want to know more then I suggest you buy a book on the 80386. The "Intel Programmers Reference guide" is the most detailed book around. Please note that DOS32 does *ALL* of the setting up needed for protected mode. This includes the descriptors in the GDT. So you don't have to know about any stupid things like the descriptor format, selector index fields, privilege levels ,ect , ect. What you do need to know are the selector values for all the descriptors that are available to your program. Then the segment registers can simply be loaded with these known selector values. DOS32 uses only 3 descriptors ( or segments ) as described in DOS32.DOC.