pcjs/pubs/docs/x86/ops/LOADALL/tspec_a3_doc.html

1276 lines
No EOL
38 KiB
HTML

<!DOCTYPE html PUBLIC "-//IETF//DTD HTML//EN">
<!-- saved from url=(0058)http://www.rcollins.org/articles/loadall/tspec_a3_doc.html -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="Author" content="Robert R. Collins">
<meta name="GENERATOR" content="Microsoft FrontPage 2.0">
<title>The LOADALL Instruction</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000EE" vlink="#551A8B" alink="#FF0000">
<table border="0" cellpadding="0" cellspacing="0" width="800"><tbody><tr><td>
<h1 align="center"><font color="#0000FF">The <i>LOADALL</i>
Instruction</font></h1>
<h1 align="center"><font color="#0000FF">by</font></h1>
<h1 align="center"><font color="#0000FF">Robert Collins</font></h1>
<hr>
<p>Of the few undocumented instructions in the 80286 and 80386
microprocessors, the <i>LOADALL </i>instruction is the most
widely known. Nevertheless, very few people understand how to use
it. Using <i>LOADALL </i>is not as simp)e as merely knowing the <i>LOADALL
</i>opcode and its format, because knowing how to use <i>LOADALL </i>requires
a knowledge of many aspects of the CPUs' behavior that are not
documented in their respective data sheets.</p>
<p>The 286 <i>LOADALL </i>is widely known because a 15-page lntel
confidential document describing its use was given to many
developers. 286 <i>LOADALL </i>is so commonly used in production
code that DOS 3.3 (and above) and OS/2 have provisions for using <i>LOADALL
</i>built in them. Every 386 and 486 BIOS emulates 286 <i>LOADALL
</i>and even Microsoft CODEVIEW recognizes the 286 <i>LOADALL </i>opcode
and disassembles it.</p>
<p>On the other hand, the 386 <i>LOADALL </i>is not widely known,
and very few developers even know it exists. In this article, I
will explain how to use both the 286 and 386 <i>LOADALL </i>instructions
and present source code to demonstrate the various aspects of CPU
behavior that become apparent, or can be proven, when using <i>LOADALL.</i></p>
<!-- Begin Master Table --><div align="center"><center>
<table border="0" cellpadding="8" cellspacing="0">
<tbody><tr>
<td valign="top" width="60%">Intel originally included <i>LOADALL
</i>in the CPU mask for testing purposes and In Circuit
Emulator (ICE) support. As its name implies, <i>LOADALL </i>loads
all of the CPU registers, including the
"hidden" software-invisible registers. At the
completion of a <i>LOADALL </i>instruction, the entire
CPU state is defined according to the <i>LOADALL </i>data
table. <i>LOADALL </i>loads all of the software-visible
registers such as <i>AX, </i>and all of the
software-invisible registers such as the <a href="http://www.rcollins.org/articles/loadall/tspec_a3_doc.html#SB1" name="SB1Ptr">segment descriptor caches</a>.<p>By
manipulating the descriptor cache base registers, you can
access the entire address space without switching to
protected mode. In other words, by using <i>LOADALL, </i>you
can access memory above 1Mb from real mode. Since the
alternative method for the 286 (switching to protected
mode, accessing the desired memory, then resetting the
CPU - the only way to get the 286 back to real mode) has
a significant performance penalty, <i>LOADALL </i>is most
significant to 286 programmers. <i>LOADALL </i>provides
them with a new capability that is not available by any
other means.</p>
<p><font color="#FF0000" size="5"><b><i>LOADALL </i></b><b>Details</b></font></p>
<p><i>LOADALL </i>is closely coupled with the CPU
hardware. Both the 286 and 386 have different internal
hardware and Intel implemented <i>LOADALL </i>using
different opcodes on the 286 and 386. 80286 <i>LOADALL </i>(opcode
0F05) produces an invalid opcode exception when executed
on the 386, and 80386 <i>LOADALL </i>(opcode 0F07)
produces an invalid opcode exception when executed on the
286.</p>
<p><i>LOADALL </i>loads all CPU registers (including <i>MSW,
GDTR, CSBASE, ESACCESS) </i>from a memory image. You can
execute <i>LOADALL </i>in real or protected mode, but
only at privilege level 0 (CPL=0). If you execute <i>LOADALL
</i>at any other privilege level, the CPU generates an
exception.</p>
<p>By directly loading the descriptor cache registers
with <i>LOADALL, </i>a program has explicit control over
the base address, segment limit, and access rights
associated with each memory segment. Normally, the CPU
loads these values each time it loads a segment register,
but <i>LOADALL </i>allows you to load these hidden
registers independently of their segment register
counterparts.</p>
<p>In real mode, <i>LOADALL </i>makes it possible to
access a memory segment that is not associated with any
segment register. Likewise in protected mode, you can
access memory that has no descriptor table entry.</p>
<p><i>LOADALL </i>performs no protection checks against
any of the loaded register values. When you execute it at
<i>CPL 0, LOADALL </i>can generate no exceptions. The
segment access rights and limit portions may be values
that would otherwise be illegal in the context of real
mode or protected mode, but <i>LOADALL </i>willingly
loads these values with no checks. Once loaded, however,
the CPU performs full access checks when accessing a
segment. For example, you can load a segment whose access
is marked "not present." Normally, this
condition would generate exception 11, "segment not
present", but <i>LOADALL </i>does not generate
exception 11. Instead, any attempt to access this segment
will generate exception 13.</p>
<p><i>LOADALL </i>does not check coherency between the
software-visible segment registers and the
software-invisible segment descriptor cache registers.
Any segment descriptor base register may point to any
area in the CPU address space, while the software-visible
segment register may contain any other arbitrary value.
The CPU makes all memory references according to the
descriptor cache registers, not the software-visible
segment registers. All subsequent segment register loads
will reload the descriptor cache register. Beware of
using values in CS that do not perfectly match a code
segment descriptor table entry, or a real mode code
segment - an interrupt return <i>(IRET) </i>may either
cause an exception or execution to resume at an
unexpected location. Likewise, pushing and subsequently
popping any segment register will force the descriptor
cache register to reload according to the CPU's
conventional protocol, thereby inhibiting any further
real mode extended memory references.</p>
<p><font color="#FF0000" size="5"><b>80286 </b><b><i>LOADALL</i></b></font></p>
<p>You encode the 80286 <i>LOADALL </i>as a two-byte
opcode, 0F05h. <i>LOADALL </i>reads its table from a
fixed memory location at 800h (80:0 in real-mode
addressing). <i>LOADALL </i>performs 51 bus cycles <i>(WORD
</i>cycles), and takes 195 clocks with no wait states. <a href="http://www.rcollins.org/articles/loadall/tspec_a3_doc.html#Tbl1">Table 1</a> shows the format you must
prepare at location 800h before executing the 286 <i>LOADALL
</i>instruction. All CPU register entries in the <i>LOADALL
</i>table conform to the standard Intel format, where the
least significant byte is at the lowest memory address. <a href="http://www.rcollins.org/articles/loadall/tspec_a3_doc.html#Tbl2a">Table 2</a> shows the 286 format of the
descriptor cache entries.</p>
<p><br>
</p>
<p><!-- Begin "Table 1" in column 1 of Master Table --> </p>
<div align="center"><center><table border="0" cellpadding="12" cellspacing="0">
<caption align="top"><a name="Tbl1"></a><strong>
Table 1 -- 80286 </strong><strong><i>LOADALL</i></strong><strong>
Table</strong></caption>
<tbody><tr>
<th valign="bottom">Physical Address</th>
<th valign="bottom">Description</th>
<th valign="bottom">Data Size</th>
<th valign="bottom">Data Value</th>
</tr>
<tr>
<td valign="top"><p align="center">[800] <br>
[802]<br>
[804]<br>
[806]<br>
[808]<br>
[80A]<br>
[80C]<br>
[80E]<br>
[810]<br>
[812]<br>
[814]<br>
[816]<br>
[818]<br>
[81A]<br>
[81C]<br>
[81E]<br>
[820]<br>
[822]<br>
[824]<br>
[826]<br>
[828]<br>
[82A]<br>
[82C]<br>
[82E]<br>
[830]<br>
[832]<br>
[834]<br>
[836]<br>
[83C]<br>
[842]<br>
[848]<br>
[84E]<br>
[854]<br>
[85A]<br>
[860]<br>
[866] </p>
</td>
<td valign="top">None<br>
None<br>
MSW<br>
None<br>
None<br>
None<br>
None<br>
None<br>
None<br>
None<br>
None<br>
TR_REG<br>
FLAGS<br>
IP<br>
LDT_REG<br>
DS_REG<br>
SS_REG<br>
CS_REG<br>
ES_REG<br>
DI<br>
SI<br>
BP<br>
SP<br>
BX<br>
DX<br>
CX<br>
AX<br>
ES_DESC<br>
CS_DESC<br>
SS_DESC<br>
DS_DESC<br>
GDT_DESC<br>
LDT_DESC<br>
IDT_DESC<br>
TSS_DESC<br>
ENT&nbsp;OF&nbsp;TABLE</td>
<td align="center" valign="top">DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DW<br>
DESC_CACHE286<br>
DESC_CACHE286<br>
DESC_CACHE286<br>
DESC_CACHE286<br>
DESC_CACHE286<br>
DESC_CACHE286<br>
DESC_CACHE286<br>
DESC_CACHE286<br>
</td>
<td align="center" valign="top">0<br>
0<br>
0<br>
?<br>
0<br>
0<br>
0<br>
0<br>
0<br>
0<br>
0<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
</td>
</tr>
<tr>
<td colspan="4"><pre><font size="4">DESC_CACHE286 STRUC
Addr_A15_A00 DW ?
Addr_A23_A16 DB ?
Access DB ?
Limit DW ?
ENDS</font></pre>
</td>
</tr>
</tbody></table>
</center></div><p><!-- End "Table 1" within column 1 of Master Table --> Intel recommends some guidelines for
proper execution following <i>LOADALL. </i>The stack
segment should be a read/write data segment; the code
segment can be execute on1y (access=95h), read/execute
(access=9bh), or read/write/execute (access=93h). Proper
protected mode operation also requires that the DPL of <i>CS
</i>and DPL of <i>SS </i>be equal. These attributes
determine the CPL of the processor. Also, the DPL fields
of <i>ES </i>and <i>DS </i>should be equal to 3 to
prevent <i>RETF </i>or <i>IRET </i>instructions from
zeroing these registers. </p>
<p>The code in <a href="http://www.rcollins.org/ftp/source/286load/286load.asm">listing 1</a>
demonstrates how to exp1ore the various operating modes
with 286 <i>LOADALL </i>and how to access extended memory
while in real mode. The <i>LOADALL </i>test performs
various functions that would be impossible to duplicate
without using <i>LOADALL.</i></p>
<p><font color="#FF0000" size="5"><b>80386 </b><b><i>LOADALL</i></b></font></p>
<p>The 386 LOADALL is encoded as a two-byte opcode
(0F07). Unlike the 286 LOADALL, this LOADALL instruction
reads its data from a table pointed to by ES:EDI. Segment
overrides are allowed, but apparently ignored. The 386
LOADALL performs 51 bus cycles (DWORD cycles) and takes
122 clocks with no wait states. Table 3 shows the 386
LOADALL format. However, <a href="http://www.rcollins.org/articles/loadall/tspec_a3_doc.html#Tbl3">Table 3</a> does
not show that prior to reading the LOADALL table, LOADALL
reads 10 DWORDs exactly 100h bytes beyond the beginning
of the table (ES:EDI+100h). This data is not used to load
any of the registers LOADALL does not load (CR2, CR3,
DRO-DR3, TR6, TR7), or the Numeric Processor eXtension
(NPX). At this time, the purpose of reading this data and
its destination is a mystery. Figure 1 shows an ICE trace
showing all the bus cycles associated with LOADALL's
execution.</p>
<p>As with the 286 LOADALL, all CPU register entries in
the LOADALL table are in the standard Intel format where
the least significant byte is at the lowest memory
address. The 386 descriptor cache entries have the format
shown in <a href="http://www.rcollins.org/articles/loadall/tspec_a3_doc.html#Tbl4">Table 4</a>.</p>
<p><a href="http://www.rcollins.org/ftp/source/386load/386load.asm">Listing
2</a> shows how to test 386 LOADALL. This test is more
comprehensive than the 286 LOADALL test because of the
expanded capabilities of the 386 microprocessor. This
test puts the CPU into various states that are illegal
and are impossible to duplicate through any other
software means.</p>
<p><font color="#FF0000" size="5"><b><i>LOADALL </i></b><b>Emulation</b></font></p>
<p>Due to the large number of systems programs that use
286 <i>LOADALL, </i>all 386 and 486 BIOS's must emu1ate
the 286 <i>LOADALL </i>instruction (opcode 0<i>F05). </i>On
the 386 and 486, the 286 <i>LOADALL </i>instruction
generates an invalid opcode exception. The BIOS traps
this exception and does its best to emulate the
functionality of the <i>LOADALL </i>instruction, but
perfect emulation is impossible without using <i>LOADALL </i>itself.
Using 386 <i>LOADALL </i>to emulate 286 <i>LOADALL </i>can
be done, but has its risks. First of all, the 486 does
not have a <i>LOADALL </i>instruction. Second, Intel has
threatened to remove <i>LOADALL </i>from the 386 mask.</p>
<p>Perfect emulation is possible on the 386 by using 386 <i>LOADALL
</i>to emulate 286 <i>LOADALL. </i><a href="http://www.rcollins.org/ftp/source/emuload/emuload.asm">Listing 3</a>
shows a TSR program that uses 386 <i>LOADALL </i>to
emulate 286 <i>LOADALL. </i>The program first tests that
you are a 386 before insta1ling itself. By using this
emu1ation program, you can guarantee perfect 286 <i>LOADALL
</i>emulation.</p>
<p><font color="#FF0000" size="5"><b>Conclusion</b></font></p>
<p><i>LOADALL </i>is a very powerful instruction, but the
features that make it so powerful also make it risky. For
example, <i>LOADALL </i>can put the processor in states
that are otherwise impossible to duplicate through any
other software means. Using <i>LOADALL </i>requires a
thorough understanding of how the CPU processes register
loads, the ramifications of those register loads, and
careful planning. The illegally induced processor states
can easily cause system crashes if not properly planned
for. The best way to avoid system crashes is to avoid
using <i>LOADALL </i>unless you are totally confident in
your understanding of the CPU and in your programming
skills.</p>
<p>The 286 <i>LOADALL </i>is described in a 15-page
Intel-confidential document The document describes in
detail how to use the instruction, and also describes
many of its possible uses. <i>LOADALL </i>can be used to
access extended memory while in real mode, and to emulate
real mode while in protected mode. Programs such as
RAMDRIVE, ABOVEDISC, and OS/2 use <i>LOADALL. </i>DOS 3.3
has provisions for using <i>LOADALL </i>by leaving a
102-byte 'hole' at 80:0. If you are a systems programmer
and have a need to know this information, Intel will
provide it, along with source code to emulate 286 <i>LOADALL
</i>on the 386 (without using 386 <i>LOADALL).</i></p>
<p>Unlike the 286 <i>LOADALL, </i>the 386 <i>LOADALL </i>is
still an Intel top secret. l do not know of any document
that describes its use, format, or acknowledges its
existence. Very few people at Intel wil1 acknowledge that
<i>LOADALL </i>even exists in the 80386 mask. The
official Intel line is that, due to U.S. Military
pressure, <i>LOADALL </i>was removed from the 80386 mask
over a year ago. However, running the program in
Listing-2 demonstrates that <i>LOADALL </i>is alive,
well, and still available on the latest stepping of the
80386.</p>
<hr>
<p align="left">View source code for 286 LOADALL:<br>
<a href="http://www.rcollins.org/ftp/source/286load/286load.asm">ftp://ftp.x86.org/source/286load/286load.asm<br>
</a><a href="http://www.rcollins.org/ftp/source/286load/loadfns.286">ftp://ftp.x86.org/source/286load/loadfns.286<br>
</a><a href="http://www.rcollins.org/ftp/source/286load/macros.286">ftp://ftp.x86.org/source/286load/macros.286<br>
</a><a href="http://www.rcollins.org/ftp/source/include/cpu_type.asm">ftp://ftp.x86.org/source/include/cpu_type.asm</a></p>
<p align="left">View source code for 386 LOADALL:<br>
<a href="http://www.rcollins.org/ftp/source/386load/386load.asm">ftp://ftp.x86.org/source/386load/386load.asm<br>
</a><a href="http://www.rcollins.org/ftp/source/386load/loadfns.386">ftp://ftp.x86.org/source/386load/loadfns.386<br>
</a><a href="http://www.rcollins.org/ftp/source/386load/macros.386">ftp://ftp.x86.org/source/386load/macros.386<br>
</a><a href="http://www.rcollins.org/ftp/source/include/cpu_type.asm">ftp://ftp.x86.org/source/include/cpu_type.asm</a></p>
<p align="left">View source code for EMULOAD (286 LOADALL
emulation using 386 LOADALL):<br>
<a href="http://www.rcollins.org/ftp/source/emuload/emuload.asm">ftp://ftp.x86.org/source/emuload/emuload.asm<br>
</a><a href="http://www.rcollins.org/ftp/source/include/cpu_type.asm">ftp://ftp.x86.org/source/include/cpu_type.asm</a></p>
<p align="left">Download entire source code archive for 286LOAD,
386LOAD, and EMULOAD:<br>
<a href="http://www.rcollins.org/ftp/dloads/LOADALL.ZIP">ftp://ftp.x86.org/dloads/LOADALL.ZIP</a></p>
</td>
<!-- End column 1 in Master Table --><!-- Begin Column 2 in Master Table --> <td valign="top" width="40%">
<!-- Begin Sidebar 1 -->
<!--#exec cmd="/usr/www/users/rcollins/cgi-bin/include.cgi -i/usr/www/users/rcollins/articles/loadall/tspec_a3_sb1.html" -->
<!-- End Sidebar 1 --> <hr>
<!-- Begin "Table 2(a)" --> <p></p>
<div align="center"><center><table border="1" cellpadding="2" cellspacing="0" width="100%">
<caption align="top"><a name="Tbl2a"></a><strong>
Table 2 (a) -- 80286 Descriptor Cache Entry Formats </strong></caption>
<tbody><tr>
<td align="center"><font size="4"><b>Offset</b></font>
</td>
<td><font size="4"><b>Description</b></font></td>
</tr>
<tr>
<td align="center">0-2</td>
<td>24-bit physical address of the segment in
memory. These bytes are stored in standard Intel
format with the least significant byte at the
lowest memory address.</td>
</tr>
<tr>
<td align="center">3</td>
<td>Access rights. The format of this byte is the
same as that in the descriptor table. This access
byte is loaded in the descriptor cache register
regardless of its validity. Therefore the
"present" bit in the access rights
field becomes a "descriptor valid" bit.
When this bit is cleared, the descriptor is
considered invalid, and any memory reference
using this descriptor generates exception 13,
with error code 0. The Descriptor Privilege Level
(DPL) of the SS and CS descriptor caches
determines the Current Privilege Level (CPL). The
CS descriptor cache may be loaded as a read/write
data segment.</td>
</tr>
<tr>
<td align="center">4-5</td>
<td>Segment limit. The standard 16-bit segment
limit stored in standard Intel format.</td>
</tr>
</tbody></table>
</center></div><p><!-- End "Table 2(a)" --> <br>
<br>
<!-- Begin "Table 2(b)" --> </p>
<div align="center"><center><table border="1" cellpadding="2" cellspacing="0" width="100%">
<caption align="top"><a name="Tbl2b"></a><strong>
Table 2 (b) -- 80286 GDT and IDT Descriptor Cache
Entry Formats</strong></caption>
<tbody><tr>
<td align="center"><font size="4"><b>Offset</b></font></td>
<td><font size="4"><b>Description</b></font></td>
</tr>
<tr>
<td align="center">0-2</td>
<td>24-bit physical address of the segment in
memory.</td>
</tr>
<tr>
<td align="center">3</td>
<td>Should be 0.</td>
</tr>
<tr>
<td align="center">4-5</td>
<td>Segment limit.</td>
</tr>
</tbody></table>
</center></div><p><!-- End "Table 2(b)" --> </p><hr>
<!-- Begin "Table 3" --> <p></p>
<div align="center"><center><table border="0" cellpadding="8" cellspacing="0">
<caption align="top"><a name="Tbl3"></a><strong>
Table 3 -- 80386 </strong><strong><b><i>LOADALL</i></b></strong><strong>
Table </strong></caption>
<tbody><tr>
<th valign="bottom">Offset</th>
<th valign="bottom">Description</th>
<th valign="bottom">Data Size</th>
<th valign="bottom">Data Value</th>
</tr>
<tr>
<td valign="top"><p align="center">[00] <br>
[04]<br>
[08]<br>
[0C]<br>
[10]<br>
[14]<br>
[18]<br>
[1C]<br>
[20]<br>
[24]<br>
[28]<br>
[2C]<br>
[30]<br>
[34]<br>
[38]<br>
[3C]<br>
[40]<br>
[44]<br>
[48]<br>
[4C]<br>
[50]<br>
[54]<br>
[60]<br>
[6C]<br>
[78]<br>
[84]<br>
[90]<br>
[9C]<br>
[A8]<br>
[B4]<br>
[C0]<br>
[CC] </p>
</td>
<td valign="top">CR0<br>
EFLAGS<br>
EIP<br>
EDI<br>
ESI<br>
EBP<br>
ESP<br>
EBX<br>
EDX<br>
ECX<br>
EAX<br>
DR6<br>
DR7<br>
TR_REG<br>
LDT_REG<br>
GS_REG<br>
FS_REG<br>
DS_REG<br>
SS_REG<br>
CS_REG<br>
ES_REG<br>
TSS_DESC<br>
IDT_DESC<br>
GDT_DESC<br>
LDT_DESC<br>
GS_DESC<br>
FS_DESC<br>
DS_DESC<br>
SS_DESC<br>
CS_DESC<br>
ES_DESC<br>
LENGTH&nbsp;OF&nbsp;TABLE</td>
<td align="center" valign="top">DD<br>
DD<br>
DD<br>
DD<br>
DD<br>
DD<br>
DD<br>
DD<br>
DD<br>
DD<br>
DD<br>
DD<br>
DD<br>
REG_STRUC<br>
REG_STRUC<br>
REG_STRUC<br>
REG_STRUC<br>
REG_STRUC<br>
REG_STRUC<br>
REG_STRUC<br>
REG_STRUC<br>
DESC_CACHE<br>
DESC_CACHE<br>
DESC_CACHE<br>
DESC_CACHE<br>
DESC_CACHE<br>
DESC_CACHE<br>
DESC_CACHE<br>
DESC_CACHE<br>
DESC_CACHE<br>
DESC_CACHE<br>
</td>
<td align="center" valign="top">?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
?<br>
&lt;?&gt;<br>
&lt;?&gt;<br>
&lt;?&gt;<br>
&lt;?&gt;<br>
&lt;?&gt;<br>
&lt;?&gt;<br>
&lt;?&gt;<br>
&lt;?&gt;<br>
&lt;?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
&lt;?,?,?&gt;<br>
</td>
</tr>
<tr>
<td valign="top" colspan="2"><pre><font size="4">REG_STRUC STRUC
REG_VAL DW ?
DW 0
ENDS</font></pre>
</td>
<td colspan="2"><pre><font size="4">DESC_CACHE STRUC
DB 0
_Type DB ?
DB 0
DB 0
_Addr DD ?
_Limit DD ?
ENDS</font></pre>
</td>
</tr>
</tbody></table>
</center></div><p><!-- End "Table 3" --> </p><hr>
<!-- Begin "Table 4(a)" --> <p></p>
<div align="center"><center><table border="1" cellpadding="3" cellspacing="0" width="100%">
<caption align="top"><a name="Tbl4"></a><strong>
Table 4 (a) -- 80386 Descriptor Cache Entries </strong></caption>
<tbody><tr>
<td align="center"><font size="4"><b>Offset</b></font>
</td>
<td><font size="4"><b>Description</b></font></td>
</tr>
<tr>
<td align="center">0-3 </td>
<td>Access rights. The access rights dword
consumes 11 bits of this 32-bit field. See <a href="http://www.rcollins.org/articles/loadall/tspec_a3_doc.html#Fig2b" name="F2Ptr">figure 2</a> for a
complete description of this field.</td>
</tr>
<tr>
<td align="center">4-7 </td>
<td>32-bit base address of the segment in
memory..</td>
</tr>
<tr>
<td align="center">8-11 </td>
<td>32-bit base address of the segment in memory.</td>
</tr>
</tbody></table>
</center></div><p><!-- End "Table 4(a)" --> <br>
<br>
<!-- Begin "Table 4(b)" --> </p>
<div align="center"><center><table border="1" cellpadding="3" cellspacing="0" width="100%">
<caption align="top"><strong>Table 4 (b) -- 80386 GDT
and IDT Descriptor Cache Entry Formats </strong></caption>
<tbody><tr>
<td align="center"><font size="4"><b>Offset</b></font>
</td>
<td><font size="4"><b>Description</b></font></td>
</tr>
<tr>
<td align="center">0-3 </td>
<td>Should be 0.</td>
</tr>
<tr>
<td align="center">4-7 </td>
<td>32-bit base address of GDTR or IDTR.</td>
</tr>
<tr>
<td align="center">8-11 </td>
<td>32-bit limit of GDTR or IDTR.</td>
</tr>
</tbody></table>
</center></div><p><!-- End "Table 4(b)" --> </p>
<hr>
<!-- Begin "Figure 1" -->
<div align="center"><center>
<table border="0" cellpadding="3" cellspacing="0">
<caption align="top"><strong>Figure 1 -- In-Circuit-Emulator
Trace of 80386 </strong><em><strong>LOADALL</strong></em><strong>
Instruction</strong></caption>
<tbody><tr>
<td valign="top"><font size="2"><strong>Frame</strong></font></td>
<td valign="top" colspan="3"><font size="2">The FRAME
number is like a clock count for the CPU. At every CPU
clock, the ICE takes a picture. When a valid cycle
occurs, the ICE records its occurance. Therefore, it is
possible to determine how many CPU clocks a sequence of
instructions takes to execute by reading this
information.</font></td>
</tr>
<tr>
<td valign="top"><font size="2"><strong>Type</strong></font></td>
<td valign="top" colspan="3"><font size="2">Cycle type.
Shown here are F=Fetch, R=Read, and X=eXecute.</font></td>
</tr>
<tr>
<td valign="top"><font size="2"><strong>Address</strong></font></td>
<td valign="top" colspan="3"><font size="2">The 32-bit
physical address asserted on the CPU address bus during
each cycle.</font></td>
</tr>
<tr>
<td valign="top"><font size="2"><strong>Data</strong></font></td>
<td colspan="3"><font size="2">The data asserted on the
CPU data bus during each cycle.</font></td>
</tr>
<tr>
<td><font size="2"><strong>BE3#<br>
BE2#<br>
BE1#<br>
BE0#</strong></font></td>
<td colspan="3"><font size="2">Byte enable pins on the
CPU. These pins determine which bytes of the 32-bits of
data are valid. These pins are active low, so 8-bits of
data are valid for each '0.'</font></td>
</tr>
<tr>
<td><font size="2"><strong>W/R#</strong></font></td>
<td><font size="2">Write/Read.</font></td>
<td><font size="2">Write = 1</font></td>
<td><font size="2">Read = 0</font></td>
</tr>
<tr>
<td><font size="2"><strong>D/C#</strong></font></td>
<td><font size="2">Data/Code.</font></td>
<td><font size="2">Data = 1</font></td>
<td><font size="2">Code = 0</font></td>
</tr>
<tr>
<td><font size="2"><strong>M/IO#</strong></font></td>
<td><font size="2">Memory/IO</font></td>
<td><font size="2">Memory = 1</font></td>
<td><font size="2">IO = 0</font></td>
</tr>
</tbody></table>
<table border="0" cellpadding="5" cellspacing="0">
<tbody><tr>
<td align="center" valign="bottom"><pre><font size="2"><tt>Frame
Dec</tt></font><font face="Courier New"> </font></pre>
</td>
<td align="center" valign="bottom"><pre><font size="2" face="Courier New">Type</font><font face="Courier New"> </font></pre>
</td>
<td align="center" valign="bottom"><pre><font size="2" face="Courier New">Address
(Hex)</font><font face="Courier New"> </font></pre>
</td>
<td align="center" valign="bottom"><pre><font size="2" face="Courier New">Data
(Hex)</font><font face="Courier New"> </font></pre>
</td>
<td align="center" valign="bottom"><pre><font size="2" face="Courier New">BBBB
EEEE
3210
####</font><font face="Courier New"> </font></pre>
</td>
<td align="center" valign="bottom"><pre><font size="2">WDM
///
RCI
O
###</font></pre>
</td>
<td valign="bottom"><pre><font size="2">Comments</font></pre>
</td>
</tr>
<tr>
<td align="center" valign="top"><pre><font size="2"><tt>5
8
011
013
015
017
019
021
023
025
027
029
031
033
035
037
039
041
043
045
047
049
051
053
055
057
059
061
063
065
067
069
071
073
075
077
079
081
083
085
087
089
091
093
095
097
099
101
103
105
107
109
111
113
115
117
119
121
123
125
127
129
131</tt></font></pre>
</td>
<td align="center" valign="top"><pre><font size="2">F
X
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R</font></pre>
</td>
<td align="center" valign="top"><pre><font size="2">0000DE40
executed
0000D8F0
0000D8F4
0000D8F8
0000D8FC
0000D900
0000D904
0000D908
0000D90C
0000D910
0000D914
0000D7F0
0000D7F4
0000D7F8
0000D7FC
0000D800
0000D804
0000D808
0000D80C
0000D810
0000D814
0000D818
0000D81C
0000D820
0000D824
0000D828
0000D82C
0000D830
0000D834
0000D838
0000D83C
0000D840
0000D844
0000D848
0000D84C
0000D850
0000D854
0000D858
0000D85C
0000D860
0000D864
0000D868
0000D86C
0000D870
0000D874
0000D878
0000D87C
0000D880
0000D884
0000D888
0000D88C
0000D890
0000D894
0000D898
0000D89C
0000D8A0
0000D8A4
0000D8A8
0000D8AC
0000D8B0
0000D8B4
0000D8B8</font></pre>
</td>
<td align="center" valign="top"><pre><font size="2">B490070F
2bytes
01010101
02020202
03030303
04040404
05050505
06060606
07070707
08080808
09090909
0A0A0A0A
7FFFFFE0
00000002
00000133
66666666
77777777
55555555
88888888
22222222
44444444
33333333
11111111
FFFF0FF0
0000D402
xxxx0000
xxxx0000
xxxx5555
xxxx4444
xxxx2222
xxxx6666
xxxx1111
xxxx3333
00008900
00070000
00000800
00000000
00000000
000003FF
00000000
00000000
00000000
00008200
00090000
00000088
00008300
00050000
0000FFFF
00009300
00040000
0000FFFF
00009300
00020000
0000FFFF
00009300
00060000
0000FFFF
00009B00
0000DD30
0000FFFF
00009300
00030000
00FFFFFF</font></pre>
</td>
<td align="center" valign="top"><pre><font size="2">0000
at
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
1100
1100
1100
1100
1100
1100
1100
1100
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000</font></pre>
</td>
<td align="center" valign="top"><pre><font size="2">001
DE40L
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011
011</font></pre>
</td>
<td valign="top"><pre><font size="2">LOADALLfetched
LOADALLbeginsexecution
\</font><font size="2" face="Courier New">
\
\ The10"mystery"
\ reads,exactly
\ 100hbytesbeyond
/ thebeginningof
/ theLOADALLtable.
/
/
/
CR0
EFLAGS
EIP
EDI
ESI
EBP
ESP
EBX
EDX
ECX
EAX
DR6
DR7
TRRegister
LDTRegister
GSRegister
FSRegister
DSRegister
SSRegister
CSRegister
ESRegister
TSSDescriptorCache
IDTDescriptorCache
GDTDescriptorCache
LDTDescriptorCache
GSDescriptorCache
FSDescriptorCache
DSDescriptorCache
SSDescriptorCache
CSDescriptorCache
ESDescriptorCache
</font></pre>
</td>
</tr>
</tbody></table>
</center></div>
<!-- End "Figure 1" -->
</td>
</tr>
</tbody></table>
</center></div>
<hr>
<p align="left"><a href="http://www.rcollins.org/articles/articles.html#LOADALLPtr">Back to
Books and Articles home page</a></p>
<!--#exec cmd="/usr/www/users/rcollins/cgi-bin/StdDisclaimer.cgi" -->
</td></tr></tbody></table>
</body></html>