Files
2024-02-19 00:25:23 -05:00

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