How to infect DOS32 protected
mode .EXE files
A pure research virus
Dark Fiber [NuKE] 8th November 1995
Whats DOS32
Who uses DOS32? Never heard of it!!
Where can I get DOS32
Basics of using PMODE
Slight differences to DOS & DOS32
Simple DOS32 virus guidelines
Anti-Virus strategies on DOS32 files
Some notes about DOS32
DOS32 File Header structure
Crash course in PMODE by Adam Seychell
A VERY detailed tech spec for PMODE by Yann Stephen
[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]-[*]
Whats DOS32
DOS32 is a DOS Extender, what that is, is a really cool program
designed to run in protected mode, and it offers programs a flat
memory layout, that is, no 64kb segments & 16bit code size,
its a pure 32bit enviroment, with some reflection in 16bit
mode.
<< Lifted from the DOS32 manual ^_^ >>
The 80386 has been around since 1987 and to this day DOS is
still running in real mode. Since nobody has bothered to design a
protected mode DOS, programs called 'DOS extenders' were written. A
DOS extender is basically a program that will switch the CPU into
protected mode so that it can then execute a protected mode
application under DOS. If you don't know the difference between
real mode and protected mode then have a go at reading the file
PMODE.DOC or better still get a proper book before reading to much
further. I think that it is much easier to program in protected
mode than it is to on real mode ( Intel 8086 architecture ) because
you can use only one big segment for the entire application.
You could say a DOS extender is a separate program that
handles all the setting up needed for protected mode under DOS. You
let the DOS extender worry about all of the protected mode
initialising. So you write programs in plain and pure protected
mode.
Since DOS runs in real mode ( or V86 mode ) a protected
mode program can no longer execute DOS calls directly. The DOS
extender should have services that allow protected mode programs to
call real mode code and will either enter V86 mode or return to
real mode when doing so. Usually a DOS extender has many more
services than just real mode calls. For example, setting interrupt
vectors, memory allocation, disk I/O routines and possibly a
debugger.
Who uses DOS32? Never heard of it!!
I'm not surprised :) I've been using it for about a year.
The only people who tend to use it are the demo coders,
just like their they only people who use Trans PMODE.
Your chances of finding DOS32 files are few and far between,
but they do exist.
Where can I get DOS32
ftp.cdrom.com /demos/code/pmode/dos32v33.zip
Basics of using PMODE
ACK! Thats really too much to explain, if you dont know
jack shit about pmode...... Theres lots of good .DOCS
that comes with DOS32 zip.
Slight differences to using DOS32 and DOS
File functions like
DOS DOS32
mov ds,segment mov ah,040h
mov ah,040h mov ecx,really big length
mov cx,length mov edx,really long offset
mov dx,offset code int 21h
int 21h
The main differences are for things such as offsets.
You use extended 32bit registers, not pissy little 16bit ones.
And ofcourse, it uses selectors instead of segments....
Simple DOS32 virus guidelines
This will just be a step by step thing
total_executable_size is the size of the executable code
as well as the size of all the relocations
executable_code_size this is the size of the executable code
only.
stubloader_size this is the size of the
1. You need to find the DOS32 header.
Because DOS32 files are just standard overlays,
tacked onto the extender stub or a loader stub,
the standard overlay technique still works,
Assume there is an .EXE file header in BUFFER
;; Calculate the overlay offset using the MZ header file size
movzx eax,word ptr [BUFFER + 4]
movzx edx,word ptr [BUFFER + 2]
or dx,dx
je $+3
dec ax
shl eax,9
add edx,eax
EDX now points to the overlay offset within the .EXE file.
This address needs to be saved in order to make modifications
here later onwards.
2. Read in and check for a valid DOS32 header
3. Check to see if the DOS32 exec is compressed
4. Check to see if the DOS32 file contains an overlay.
Formula for calculating a DOS32 overlay length is
total_file_size - stubloader_size - total_executable_size == 0
or
total_file_size - stubloader_size == total_executable_size
the total_executable_size is at offset 08h within the DOS32
header.
eg:
mov ax,04202h
xor edx,edx
int 21h
;eax = total size
sub eax,dword ptr [stubloader_size]
cmp eax,dword ptr [BUFFER + 08h]
je no_overlay_present
5. Remove the relocations from the end of the file
To find the offset to the relocations the formula is
executable_code_size - stubloader_size - header_size = reloc_offset
eg:
mov ax,04200h
mov edx,dword ptr [BUFFER + 010h]
add edx,dword ptr [stubloader_size]
add edx,header_size
int 21h
6. Append the virus
7. Append the relocations
8. Calculate the new header values
To calculate a new EIP, its equal to the current
executable_code_size
ESP must be > than your (EIP + total_virus size)
the new stack MUST be on a DWORD boundary.
You now need to patch in the amount of memory required to
run the program, the total_executable_size, and the
executable_code_size.
This is as easy as adding the total virus size onto them.
9. Write the new header back
Anti Virus strategies for DOS32 files.
Whats to say. NO anti virus programs scan dos32 files,
proably because there so few and far between, and secondly
probably because its an OMF format.
Some notes about DOS32
Ummm, well, DOS32 files can be compressed, and this virus
cant infect those ones.....
DOS32 is an OMF format, and has its own linker, DLINK.
You can TASM the code, but TLINK will just barf.
DOS32 File Header structure
File format of a DOS32 executable (.EXE file produced from DLINK)
Offset Size Description
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
0 n A stub loader or DOS32.EXE of n bytes {no stub in DLL}
n+0 4 Signature "Adam" { ="DLL " for DLL files }
n+4 2 Minimum DOS32 version required (packed BCD)
n+6 2 DLINK version in packed BCD format
n+8 4 Number of bytes remaining after the stub file. The
entire .EXE file size (after linking) will be equal
to this value plus the stub file size.
n+0Ch 4 Start of 32bit executable image relative to the
'Adam' signature.
n+10h 4 Length of executable image ( see below ).
n+14h 4 Initial memory required for application. This value
must be larger than the size of the 32bit executable
image.
n+18h 4 Initial EIP { public varible address for DLL file }
n+1Ch 4 Initial ESP { ignored in DLL header }
n+20h 4 Number of entries in fixup table. Each entry in the
table contains a 32bit offset relative to the start
of the executable image of a 16bit WORD that must be
set to the programs data selector at load time. The
table immediately follows the executable image.
n+24h 4 Flags ( function active when bit is set )
bit 0 = executable image is compressed
bit 1 = display DOS32 logo when executed
bits 2..31 reseved.
The 32bit executable image (application binary data) can start
anywhere after this point (i.e >= offset n+28h in the .EXE file).
A Crash course in PMODE by Adam Seychell
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/or 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 is stored in memory. The address of this table
is given in a special 386 register 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: 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.
One of the segment registers (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 to these descriptors. The base address of the
segment may also 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 available 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] is
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 illegal operations.
The LINEAR ADDRESS and PHYSICAL ADDRESS
All the address translations described above is done by the
386 segmentation unit. The segmentation unit looks up the
descriptor tables, segment selectors, offsets and then outputs a
32bit linear address. This linear address is calculated by the
segmentation unit in the following manner.
Linear address = base address of segment + offset. The segment base
address is found in the Base address field ( bits 16..39 & 56..63 )
of a descriptor which is located in the Global Descriptor Table.
The index field ( bits 3..15) of the segment register selects the
descriptor to use.
An example of the linear address of the instruction.
MOV EAX, ES:[EDX*8+012345678h]
where EDX = 100h and ES equals a selector wich points to a
descriptor with the base field equal to 02000000h.
The linear address = 2000000h + ( 100h*8 + 012345678h ) = 014345E78h
Just to make things even more complicated the 386 has an
second memory managing unit called the Paging Unit. The linear
address calculated above may still not be the physical RAM location
the 386 is addressing. This linear address has yet to go through
another stage, the paging unit. If you are having trouble with what
I've said so far then you may want to take a coffee break before
continuing because this is even worse.
The 32bit linear address is directed to the paging unit. The
paging unit divides the linear address into three sections.
bits 0..12 Offset in a page
bits 13..23 Points to the page entry in the page table
bits 24..31 Points to the directory entry in the page directory table
The page table contains 1024 double word entires. In each of these
entries is the physical address of a 4KB page. The page directory
also contains 1024 double word entries. Each of these directory
entries hold a physical address of a page table. See intel
Documentation for the exact format of the page table entries and
directory table entries. The physical base address of the
DIRECTORY TABLE is in control register 3 ( CR3 )
This means if every entry in the directory table is used then
there would be 1024 page tables available. Because each page table
hold 1024 page addresses then there would be a total of 1024*1024
4KB pages. The addresses in the page tables are all physical
addresses. i.e the output of the CPU address bus pins. The paging
unit can be enabled or disabled depending on wether bit 31 of CR0
is set. If the paging in disabled then the linear address simply
equals the physical address. If paging is enabled the the linear
address is translated by the paging unit to form a physical
address. Please note that it is possible to set up the page tables
and directory such that the linear address equals the physical
address. This is what DOS32 does for the first 1MB of linear
address space. If you can not understand my hopeless attempt of
describing the paging unit then the diagram below might help.
The 32 bit linear address from the segmentation unit
-------------------------------------------------------------------------
| BITS 0..12 | BITS 13..23 | BITS 24..31 |
| | | |
-------------------------------------------------------------------------
| | |
|------------------------ | |
| | |
| | |
| | |
A Page in memory (4KB) | | |
-------------------------- | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | <------- | |
| | | |
| | | |
| | | |
|---> ------------------------- | |
| | |
| | |
| | |
| PAGE TABLE Offset | |
| -------------------------- | |
| | | 4092 | |
| -------------------------- | |
| . . | |
| . . | |
| . . | |
| -------------------------- | |
| | | 12 | |
| -------------------------- | |
|---<| address of page | 8 <--------- |
-------------------------- |
| | 4 |
-------------------------- |
| | 0 |
|--> -------------------------- |
| |
| |
| |
| |
| |
| DIRECTORY TABLE Offset |
| -------------------------- |
| | | 4092 |
| -------------------------- |
| . . |
| . . |
| . . |
| -------------------------- |
|---<| address of page table | 12 <-----------------------------
--------------------------
| | 8
--------------------------
| | 4
--------------------------
| | 0
|--> --------------------------
|
|
|
| ----------------------------------------------
--------<-| CR3 |
----------------------------------------------
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 have 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. The info here is
only meant to give you an idea of how protected mode works. Please
note that DOS32 does *ALL* of the setting up needed for protected
mode. Don't worry if you couldn't understand half the stuff I was
talking about. You don't have to know about any stupid things like
the descriptor format, selector index fields, privilege levels
,paging, tables, 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.
A VERY detailed tech spec for PMODE by Yann Stephen
PROTECTED MODE ( A more detailed approch )
Written by Yann Stephen
Global Descriptor Table Register (GDTR) :
The contents of the global table register define a table in the
80386DX's physical memory address space called the Global
Descriptor Table (GDT). This global descriptor table is one
important element of the 80386DX's memory management system.
GDTR is a 48-bit register that is located inside the 80386DX. The
lower two bytes of this register, which are identified as LIMIT,
specify the size in byte of the GDT. The decimal value of LIMIT is
one less than the actual size of the table. For instance, if LIMIT
equals 00FFh the table is 256 bytes in length. Since LIMIT has 16
bits, the GDT can be up to 65,536 bytes long. The upper four bytes
of the GDTR, which are labelled BASE, locate the beginning of the
GDT in physical memory. This 32-bit base address allows the table
to be positioned anywhere in the 80386DX's address space.
The GDT provides a mechanism for defining the characteristics of
the 80386DX's global memory address space. Global memory is a
general system resource that is shared by many or all software
tasks. That is, storage locations in global memory are accessible
by any task that runs on the microprocessor. This table contains
what are called system segment descriptors. It is these descriptors
that identify the characteristics of the segments of global memory.
For instance, a segment descriptor provides information about the
size, starting point, and access rights of a global memory segment.
Each descriptor is eight bytes long, thus our earlier example of a
256-byte table provides enough storage space for just 32
descriptors. Remember that the size of the global descriptor table
can be expanded simply by changing the value of LIMIT in the GDTR
under software control. If the table is increased to its maximum
size of 65,563 bytes, it can hold up to 8,192 descriptors.
Question 1.1 : How many descriptors can be stored the global
descriptor table when the size of LIMIT is 0FFFh.
The value of the BASE and LIMIT must be loaded into the GDTR before
the 80386DX is switched from real mode of operation to the
protected mode. Special instruction are provided for this purpose
in the system control instruction set of the 80386 DX. Once the
80386DX is in protected mode, the location of the table is
typically not changed.
Interrupt Descriptor Table Register (IDTR) :
Just like the global descriptor table register, the interrupt
descriptor table register (IDTR) defines a table in physical
memory. However, this table contains what are called interrupt
descriptors, not segment descriptors. For this reason it is known
as the Interrupt Descriptor Table (IDT).This register and table of
descriptors provide the mechanism by which the microprocessor
passes program control to interrupt and exception routines.
Just like the GDTR, the IDTR is 48 bits in length. Again,
the lower two bytes of the register (LIMIT) define the table size.
That is, the size of the table equals LIMIT+1 bytes. Since two
bytes define the size, the IDT can also be up to 65,536 bytes long.
But the 80386DX only supports up to 256 interrupts and exceptions;
therefore, the size of the IDT should not be set to support more
than 256 interrupts. The upper three bytes of IDTR (BASE) identify
the starting address of the IDT in physical memory. The type of
descriptor used in the IDT are what are called interrupt gates.
These gates provide a means for passing program control to the
beginning of an interrupt service routine. Each gate is eight bytes
long and contains both attributes and a starting address for the
service routine.
Question 1.2 : What is the maximum value that should be assigned to
the limit in the IDTR?
This table can also be located anywhere in the linear address space
addressable with the 80386DX's 32-bit address. Just like the GDTR,
the IDTR needs to be loaded before the 80386DX is switched from the
real mode to protected mode. Special instructions are provided for
loading and saving the contents of the IDTR. Once the location of
the table is set, it is typically not changed after entering the
protected mode.
Question 1.3 : What is the address range of the last descriptor in
the interrupt descriptor table defined by base address 00011000h
and limit 01FFh
Local Descriptor Table Register (LDTR) :
The Local Descriptor Table Register (LDTR) is also part of the
80386DX's memory management support mechanism. Each task can have
access to its own private table descriptor table in addition to the
global descriptor table. This private table is called the local
descriptor table (LDT) and defines a local memory address space for
use by the task. The LDT holds segment descriptors that provide
access space for use by the task. The LDT holds segment descriptors
that provide access to code and data in segments of memory that are
reserved for the current task. Since each task can have its own
segment of local memory, the protected-mode software system may
contain local descriptor tables. Whenever a selector is loaded into
the LDTR, the corresponding descriptor is transparently read from
global memory and loaded into the local descriptor table cache
within the 80386DX. It is this descriptor that defines the local
descriptor table. Assume that every time a selector is loaded into
the LDTR, a local descriptor table descriptor is cached and a new
LDT is activated.
Control Registers :
The protected-mode model includes the four system control
registers, identified as CR0 through CR3 :
31 23 15 7 0
-------------------------------------------------------
| Page Directory Base Register (PDBR)| Reserved | CR3
-------------------------------------------------------
| Page Fault Linear Address | CR2
-------------------------------------------------------
| RESERVED | CR1
-------------------------------------------------------
|P| |R|T|E|M|P| CR0
|G| RESERVED | |S|M|P|E|
-------------------------------------------------------
Notice that the lower five bits of CR0 are system control flags.
These bits make up what are known as the machine status word (MSW).
The most significant bit of CR0 and registers CR2 and CR3 are used
by the 80386DX's paging mechanism. Let us consider by examining the
machine status word bits of CR0. They contain information about the
80386DX's protected-mode configuration and status. The four bit
labelled PE, MP, EM and R are control bit that define the protected
mode system configuration. The fifth bit, TS, is a status bit.
These bits can be examined or modified through software.
The protected-mode enable (PE) bit determines if the
80386DX is in the real or protected mode. At reset, PE is cleared.
This enables the real mode of operation. To enter the protected
mode, we simply switch PE to 1 through software. Once in the
protected mode, the 80386DX can be switched back to real mode under
software control by clearing the PE bit. It can also be returned to
real mode by hardware reset.
The math present (MP) bit is set to 1 to indicate that a
numeric coprocessor is present in the microcomputer system. On the
other hand, if the system is to be configured so that a software
emulator is used to perform numeric operations instead of a
coprocessor, the emulate (EM) bit is set to 1.
Only one of these two bits can be set at a time. Finally, the
extension type (R) is used to indicate whether an 80387DX or 80287
numeric coprocessor is in use. Logic 1 in R indicates that an
80387DX is installed. The last bit in the MSW, task switched (TS),
automatically gets set whenever the 80386DX switched from one task
to another. It can be cleared under software control. The protected
mode software architecture of the 80386DX also supports paged
memory operation. Paging is turned on by switching the PG bit in
CR0 to logic 1. Now addressing of physical memory is implemented
with an address translation mechanism that consists of a page
directory and page table that are both held in the physical memory.
This register holds a 20-bit page directory base address that
points to the beginning of the page directory. A page fault error
occurs during the page translation process if the page is not
present in memory. In this case, the 80386DX saves the address at
which the page fault occurred in register CR2. This address is
denoted as page fault linear address.
Task Register (TR):
The task register is one of the key elements in the protected mode
task switching mechanism of the 80386DX microprocessor. This
register holds a 16-bit index value called a selector. The initial
selector must be loaded into TR under software control. This starts
the initial task. After this is done, the selector is changed
automatically whenever the 80386DX executes an instruction that
performs a task switching. TR is used to locate a descriptor in the
global descriptor table. Notice that when a selector is loaded into
TR, the corresponding task state segment (TSS) descriptor
automatically gets read from memory and loaded into on-chip task
descriptor cache. This descriptor defines a block of memory called
the task called the task state segment (TSS). It does this by
providing the starting address base (BASE) and the size (LIMIT) of
the segment. Every task has it own TSS. The TSS holds the
information needed to initiate the task, such as initial values for
the user-accessible registers.
Registers with Changed Functionality :
The segment registers are now called the segment selector register,
and instead of holding a base address they are loaded with what is
known as a selector. The selector does not directly specify a
storage location in memory. Instead, it selects a descriptor that
defines the size and characteristics of segment of memory.
15 8 2 0
-------------------------------------------------------
| INDEX |TI|RPL|
-------------------------------------------------------
SELECTOR
Bits Name Function
1-0 Requested Indicates selector privilege level desired
Privilege
Level (RPL)
2 Table Indicator TI = 0 use Global Descriptor Table (GDT)
(TI)
TI = 1 use Local Descriptor Table (LDT)
15-3 INDEX SELECT descriptor entry in table
TI bit select the table to be used when accessing a segment
descriptor, because two tables are active at the same time GDT and
LDT.
The index is used as a pointer to a specific descriptor entry in
the table selected by the TI bit.
Protected-Mode system control instruction set
Instruction Description Mode
LGDT S Load the global descriptor table register. S specifies Both
the memory location that contains the first byte of the
6 bytes to be loaded into the GDTR.
SGDT D Store the global descriptor table register. D specifies Both
the memory location that gets the first of the six bytes
to be stored from the GDTR.
LIDT S Load the interrupt descriptor table register. S specifies Both
the memory location that contains the first byte of the
6 bytes to be loaded into the IDTR.
SIDT D Store the interrupt descriptor table register. D specifies Both
the memory location that gets the first of the six bytes
to be stored from the IDTR.
LMSW S Load the machine status word. S is an operand to specify Both
the word to be loaded into MSW.
SMSW D Store the machine status word. D is an operand to specify Both
the word location or register where the MSW is to be
saved.
LLDT S Load the local descriptor table register. S specifies the Protec
operand to specify a word to be loaded into the LDTR.
SLDT D Store the local descriptor table register. D is an operand Protec
to specify the word location where the LDTR is to be saved.
LTR S Load the task register. S is an operand to specify a word Protec
to be loaded into TR (Task Register).
STR D Store the task register. D is an operand to specify the Protec
word location where the TR is to be stored.
LAR D,S Load access rights byte. S specifies the selector for the Protec
descriptor whose access byte is loaded into the upper byte
of the D operand. The low byte specified by D is cleared.
The zero flag is set if the loading completes successfully;
otherwise it is cleared.
LSL R16,S Load segment limit. S specifies the selector for the Protec
descriptor whose limit word is loaded into the word
register operand R16. The zero flag is set if the
loading completes successfully; otherwise it is cleared.
ARPL D,R16 Adjust RPL field of the selector. D specifies the selector Protec
whose RPL field is increased to match the PRL field in the
register. The zero flag is set if successful;otherwise it
is cleared.
VERR S Verify read access. S specifies the selector for the Protec
segment to be verified for read operation, If successful
the zero flag is set; otherwise it is reset.
VERW S Verify write access. S specifies the selector for the Protec
segment to be verified for write operation, If successful
the zero flag is set; otherwise it is reset.
CLTS Clear task switched flag. Protec
A few examples of these new instructions :
LGDT [INIT_GDTR]
Loads the GDTR with the base and limit pointed to by address
INIT_GDTR to create a global descriptor table in memory. This
instruction is meant to be used during system initialisation and
before switching the 80386DX to the protected mode. Once loaded the
current contents of the GDTR can be saved in memory by executing
the store global table (SGDT) instruction.
SGDT [SAVE_GDTR]
The instruction load machine status word (LMSW) and store machine
status word (SMSW) are provided to load and store the contents of
the machine status word (MSW), respectively. These are the
instructions that are used to switch the 80386DX from real to
protected mode. To do this we must set the least significant bit in
the MSW to 1. This can be done by first reading the contents of the
machine word , modifying the LSB (PE), and then writing the
modified value back into the MSW part of CR0. The instruction
sequence that follows will switch an 80386DX operating in real mode
to protected mode:
SMSW AX ;read from the MSW
OR AX,1 ;modify the PE bit
LMSW AX ;write to the MSW
Solution 1.1 : Each descriptor takes up eight bytes; therefore, a
4096-byte table can hold :
Descriptors = 4096/8 = 512
Solution 1.2 : The maximum number of interrupt descriptors than can
be used in an 80386DX microcomputer system is 256. Therefore, the
maximum table size in bytes is :
IDT (size) = 8*256 = 1000h bytes
LIMIT = 1000h-1 = 0FFFh (We start from zero)
Solution 1.3 : From the values of the base and limit, we find that
the table is located in the address range
IDT (start) = 00011000h IDT ( end ) = 000111FFh
The last descriptor in this table takes up the eight bytes of the
memory from address 000111F8h through 000111FFh.