157 lines
6.0 KiB
Plaintext
157 lines
6.0 KiB
Plaintext
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
ÄÄ´ This text comes from IMPHOBIA Issue IX - February 1995 ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
|
|
|
THE LOADALL INSTRUCTION
|
|
|
|
|
|
In Imphobia Issue #8, Walken/Impact
|
|
Studios wrote a nice article about
|
|
memory management. However, for some
|
|
reason he seems to like flat-real-mode
|
|
(FRM) which is in my belief a totally
|
|
wrong way of programming since FRM
|
|
requires a 'clean' boot. Anyway, the
|
|
discussion of the advantages and
|
|
disadvantages of using FRM as oposed
|
|
to true flat-model protected mode are
|
|
not at issue here. Besides, there's
|
|
too many coders who just blindly think
|
|
FRM or PMode is better whithout ever
|
|
having performed some serious tests.
|
|
For those who think PMode is better, I
|
|
strongly suggest checking the 386/486
|
|
references on segment management and
|
|
memory access. For those who think FRM
|
|
is better... just speed-test your
|
|
program on a Pentium <g>.
|
|
|
|
Some info about the LOADALL
|
|
instruction first. There's a 286
|
|
LOADALL instruction and a 386/486/Pen-
|
|
tium LOADALL instruction, they have
|
|
different opcodes, and work slightly
|
|
different. Since no-one wants to code
|
|
a 286 protected mode program nowadays,
|
|
I won't cover the 286 variant of the
|
|
LOADALL instruction. Strangely however
|
|
some of the BIOSes will 'emulate' the
|
|
286 variant, by hooking it into the
|
|
"bad opcode" interrupt. The LOADALL
|
|
instruction is not documented by intel
|
|
in their CPU reference guides. LOADALL
|
|
is used in the VDISK program by
|
|
Microsoft, OS/2 and Windows 95, and
|
|
supposedly also in Windows NT.
|
|
|
|
The 286 variant has opcode 0Fh, 05h.
|
|
The 386+ variant has opcode 0Fh, 07h.
|
|
As said before, any further reference
|
|
to LOADALL assumes the 386 variant
|
|
unless otherwise mentionned.
|
|
|
|
LOADALL loads a 204-byte table pointed
|
|
to by ES:EDI into the registers. Note
|
|
however, that ES:EDI must point to a
|
|
valid memory location layed out by the
|
|
current memory model, meaning. When
|
|
in real mode, ES points to a segment,
|
|
and EDI points to an offset within
|
|
that segment (thus, only the lower 16
|
|
bit offset is used). When in PMode,
|
|
ES is a selector, and EDI an offset
|
|
within that selector page. When in
|
|
FRM, ES is a segment, and EDI a 32-bit
|
|
offset within that segment.
|
|
|
|
The table layout is as follows.
|
|
|
|
Offset Size CPU register loaded
|
|
------ ---- ------------------------
|
|
0h 4 CR0
|
|
4h 4 EFLAGS
|
|
8h 4 EIP
|
|
Ch 4 EDI
|
|
10h 4 ESI
|
|
14h 4 EBP
|
|
18h 4 ESP
|
|
1Ch 4 EBX
|
|
20h 4 EDX
|
|
24h 4 ECX
|
|
28h 4 EAX
|
|
2Ch 4 DR6
|
|
30h 4 DR7
|
|
34h 4 TR (Task Register)
|
|
38h 4 LDT
|
|
3Ch 4 GS (zero-extended)
|
|
40h 4 FS (zero-extended)
|
|
44h 4 DS (zero-extended)
|
|
48h 4 SS (zero-extended)
|
|
4Ch 4 CS (zero-extended)
|
|
50h 4 ES (zero-extended)
|
|
54h 12 TSS descriptor cache
|
|
60h 12 IDT descriptor cache
|
|
6Ch 12 GDT descriptor cache
|
|
78h 12 LDT descriptor cache
|
|
84h 12 GS descriptor cache
|
|
90h 12 FS descriptor cache
|
|
9Ch 12 DS descriptor cache
|
|
A8h 12 SS descriptor cache
|
|
B4h 12 CS descriptor cache
|
|
C0h 12 ES descriptor cache
|
|
|
|
The descriptor cache entries are:
|
|
|
|
Byte 0 Must be 0
|
|
Byte 1 Access-rights byte,
|
|
like access-rights byte
|
|
in a descriptor
|
|
Bytes 2-3 Must be 0
|
|
Bytes 4-7 32-bit base address
|
|
of the segment
|
|
Bytes 8-11 32-bit segment limit
|
|
|
|
I suggest aliging the table on a page
|
|
boundary (16 bytes, or lower 4 bits of
|
|
the offset must be zero). While this
|
|
is not a requirement for the 386 and
|
|
486, it may be a requirement when
|
|
running on a Pentium (which is
|
|
probably why a pentium-patch was
|
|
issued for Windows 95 for running
|
|
DPMI-DOS programs).
|
|
Now... something the speed guru's
|
|
might be interested in... how fast is
|
|
LOADALL. Well. according to some
|
|
tests I've done, LOADALL clocks in at
|
|
about 105 clockcycles on a 386, and
|
|
125 on a 486 which is bad. But not so
|
|
bad if you take into account the usual
|
|
number of clocks it take to switch
|
|
from PMode to real and back.
|
|
|
|
RESTRICTIONS
|
|
|
|
LOADALL performs no checking on the
|
|
values loaded into the registers, so
|
|
no exception will occur even if an
|
|
illegal value is loaded. Thus, the
|
|
processor can potential be put into a
|
|
strange state. If an illegal
|
|
descriptor value is set, no exception
|
|
occurs from the execution of LOADALL.
|
|
An exception will occur, however, when
|
|
an access using that descriptor is
|
|
attempted.
|
|
|
|
LOADALL can be executed in protected
|
|
mode, but only at the most privileged
|
|
level (level 0). So when you would
|
|
want to use LOADALL when a memory
|
|
manager is installed, you would first
|
|
have to shut-down the memory manager
|
|
by issuing a VCPI call to request ring
|
|
0 privileges.
|
|
|
|
Tasmaniac / ACiD / HypernovA
|