news:fcef42b6-10da-49d6...@p5g2000vbm.googlegroups.com...
> On Nov 10, 1:30 pm, "Rod Pemberton" <do_not_h...@noavailemail.cmm>
> wrote:
> > "James Harris" <
james.harri...@googlemail.com> wrote in message
> > > 7:41 am, "Rod Pemberton" <do_not_h...@noavailemail.cmm>
...
> > > Are you saying you run LIDT in real mode before switching
> > > to PM (or run LIDT in PM and switch back to RM)?
>
> > 1) Me, personally? No, I don't, or don't believe so.
>
> OK.
Correction. I found one program of mine that does ... :-) It was never
completed. I was trying to setup some PM stuff from RM. It looks like the
overrides aren't necessary.
> > 2) It's my understanding that both of those uses are valid though. AIR,
> > the reason LIDT is not a privileged instruction is to allow that.
>
> LIDT not privileged?
Sorry, I mean that it works in RM too ...
> > [quote]
>
> > That's the only explanation of the RM IVT in the 386 manual that I could
> > find ... I.e., post 386, the RM IVT is really a variant form of an IDT,
> > and no longer an IVT.
>
> Interesting research. Could it be nothing more than that Intel has
> been a bit sloppy with their terminology?
It could be. The older manuals are an "easier read," IMO. Maybe, they are
less precise too? But, hey, try to find something on 16-bit PM in a modern
manual, or a 286 TSS ...
> > I accept that as typical or standard or preferred usage.
> > I don't believe it's the only usage.
>
> I'm coming round to your view.
I think the underlying design is very "generic", at least originally.
However, usage in certain "standard" ways results in specific code
sequences.
> Since Intel specify the sequence there's no assurance that LIDT in RM
> will correctly set up the PM IDT descriptor on *all* x86-32 CPUs.
AIR, I attempted to follow both old and new manuals, and there are a number
of conflicting differences.
It would seem obvious that they found some type of incompatibility with the
switch to 32-bit PM. The "more precise" method is only recent manuals, yes?
However, they don't mention what cpu had a problem or what their rationale
is. E.g., it might not be one of their cpu's had an issue. It could
be Cyrix or Transmeta or NEC or AMD or ...
Since they don't mention the reason, it's also possible they intend to merge
instructions or perhaps eliminate some instructions in the future. E.g.,
maybe there is some problem with design changes for future cpu's. In which
case, the startup sequence may be more similar to what they suggest and
easier to fix. Or, it could just be a slight timing issue. Who knows?
> Yes, LIDT works in either mode but isn't the query whether the
> IDTR value loaded in one mode is valid in the other?
If the IDTR is loaded in one mode for use in another and the IDT is not used
until the correct mode for it is activated, what is the issue? Unreal mode
works by setting parts of registers not available in RM.
> In fact, to my mind the question is more demanding: will the IDTR
> loaded by LIDT in one mode correctly work in the other mode in
> all cases on all x86-32 CPUs?
>
> It might.
LIDT only sets the base and size, yes? The cpu mode selects how data
at that location is interpreted, yes? That's how I understand it. Maybe
that's wrong.
> I hadn't realised until checking this out but LGDT can
> apparently have an opsiz prefix. In fact it seems it *should*!
I have 66h (i.e., o32 or o16 for NASM) on some and not on others. I don't
think any of them are critical, i.e., none are above 1MB or 16MB ...
They're all probably fine without it. IIRC, I only did so to make sure that
the upper bits were loaded or cleared.
> my take. Can you tell me if I have it right or wrong? Nasm syntax but
> I'll include the object code so that it is relevant in other
> assemblers.
>
> 0F0116[0501] lgdt [mem]
>
> This, in real mode will, I think, load a 16-bit limit and only a 24-
> bit base.
Yes.
> It will load only five bytes setting the top byte of the
> base to zero.
(Loads six. Uses five. ?)
> Therefore it will work only when the GDT base is in the
> range 0 up to 2**24-1.
Yes.
> If the base of the GDT is at 2**24 or above the
> lgdt command will be unsuccessful.
Not sure. Does it just wrap? I.e., upper address bits are effectively
truncated since they aren't loaded or are cleared? That's my guess.
> On the other hand
>
> 660F0116[0501] o32 lgdt [mem]
>
> will, I think, load a 16-bit limit and a 32-bit base.
>
Yes.
> How does that look? Anywhere close?
It looks correct to me ... ;-)
I take it the brackets on the table location are yours. I.e., address
0x105, DOS .com file org 0x100.
> Nasm-specific question: Based on other tests it seems there should
> be a way to specify to Nasm that the operand at [mem] is six bytes
> instead of five but I can't find it. Ideal would be
>
> lgdt dword [mem]
o32
> as that is consistent with other instructions but the version of Nasm
> I have does not accept that form. I know dword in this case applies to
> the Base field and not to the whole six bytes. Is there a qualifying
> keyword to specify a six-byte piece of data - and a five-byte piece of
> data for going the other way? I doubt it.
For NASM:
Some instructions support multiple data sizes in the same processor mode.
That's when you need to select between 'byte' and 'word', or 'byte' and
'dword', etc. If you specify 'word' when only 'byte' and 'dword' are an
option, then NASM inserts an override prefix. Ditto for 'dword' when 'byte'
and 'word' are the mode corect options.
Other instructions only support one form in a specific mode. They select
data size purely via the size of the code or data segment. That's when you
explicitly use o16 or o32 to select the instruction for the other mode.
NASM inserts an override prefix because of o16 or o32.
So, in 16-bit RM code, LIDT specifies 16-bit form (5 bytes). In 16-bit RM
code, o32 LIDT specifies 32-bit form (6 bytes). In 32-bit PM code, LIDT
specifies 32-bit form (6 bytes). In 32-bit PM code, o16 LIDT specifies
16-bit form (5 bytes). o32 or o16 is used to select form from the other
mode. They don't support multiple forms in the same mode, without the
override.
> Keywords word and dword seem far more suitable as the 80386
> manual refers to the operand size as being 16 for 24-bit values.
You're a MASM user aren't you? I.e., I think that's the MASM solution to
the issue: 'byte', 'sbyte' 'tbyte', 'word', 'sword, 'dword', 'sdword',
'fword', 'tword', 'oword', 'qword', 'sqword', 'dqword', 'mmword', 'xmmword',
'ymmword', and all repeated with 'ptr' ... ;-)
IMO, NASM has the more clean solution by using what the instruction defines
and what the segment size is by default. I.e., far fewer 'keywords' to get
wrong. If you don't know already, try determining if you need 'dword ptr',
'fword ptr' or 'tword ptr' for LIDT or LGDT. Try to find it in the MASM
manual first. Then, try to find it with the assembler. You may need
NDISASM to find out what MASM actually compiles ...
> Notably, where many assemblers leave the programmer to hard-code the
> bytes for scenarios such as the above at least Nasm provides ways to
> code things with mnemonics. In this case the o32 or o16 keywords do
> the job. It's just that with other instructions Nasm allows data-size
> keywords which add the prefixes automatically.
...
> For example, with bits 16,
>
> FF36[0501] push word [mem]
'word' is not needed. It's the default code/data size for 'bits 16'.
> 66FF36[0501] push dword [mem]
'dword' is needed because you're pushing a value different from the default
code size. Since it's a memory operand, it only "knows" the default size:
16-bits. 'dword' is used to change the default size. If you did 'push
eax', it "knows" the size is 32-bits and inserts an override.
> 66FF36[0501] o32 push word [mem]
Apparently valid, but you're going around in circles ...
> The second example is equivalent to the third. It's just that push
> dword has added the o32 automatically. The same syntax does
> not seem to be available for the lgdt instruction.
This is all mixing of 16-bit and 32-bit code. IIRC, there is a similarly
titled section in one (or both) of the AMD and Intel manuals.
Some prefer a syntax or understanding where 'word' and 'dword' aren't needed
for LGDT. I do. I "see" 5 bytes as default for one mode and 6 bytes as
default for another. And, maybe the NASM designer's felt that dword should
be 32-bit and word should be 16-bits, not 32-bit/24-bit ...
> > Third, 14.3 (below) clearly indicates that LIDT is valid in RM, and
> > relocating the IVT in RM is valid too. Under normal situations, why
> > would RM code need to relocate the IVT from it's default location?
> > It wouldn't. It's uneeded. So, why provide the ability to relocate the
> > IVT while in RM? I.e., setup for PM.
>
> Do you really infer this? AIUI the IVT can be relocated and should
> work in real mode wherever it has been relocated to.
I understand that it can be relocated. In fact, I stated above that I do
use a relocated IVT in RM for a few programs. But, what "normal" RM code
needs to relocate the IVT? Why would you ever relocate it? The IVT was
established as being at location zero for many years prior to 386. No
"normal" RM code should need to relocate an IVT, shouldn't relocate it for
safety or compatibility with BIOS or DOS or CP/M, and shouldn't expect that
it's been moved. AFAICT, relocating the IVT is only needed for blocking or
prohibiting direct use of the IVT, i.e., forcing code to use a system call,
e.g., like DOS' calls to get/set IVT vectors, or monitoring if other code
changes the IVT. How often is that needed or used? I.e., it may have been
useful to develop v86 mode, but otherwise is only used, if ever, in software
that "protects" the PC, e.g., anti-virus. It seems unlikely they would
intentionally provide support for anti virus software long before it was a
problem. It could also be used by virii and malware to prevent normal
operation. Can that be intentional design? I think this goes back to
generic design.
> > 14.3
> > [quote]
>
> This just says that in RM it can be relocated and resized. I don't see
> this as suggesting that the reason for the ability to relocate/resize
> it is to set it up for PM.
>
Why is it needed in RM?
Well, I do know of one other reason, other than those I mentioned above.
Supposedly (unconfirmed), Intel designed their chips so that they could be
used in embedded environments that placed startup code at zero instead of at
the initial processor startup location. It's rumored that 0xFF 0xFF (i.e.,
bus pull-up read of location without memory or ROM) is a NOP on Intel's so
the processor execution can wrap to zero and begin executing code there
(zero). AMDs supposedly page fault on wrap-around. It's possible that if
it works that way, it's only a temporary instruction, until an actual opcode
is executed. If true, relocating the RM IVT from zero would be required for
such a setup.
> There still seems greater safety in loading the PM IDTR in PM
> because it is specified by Intel to work that way.
"specified" vs. "firmly suggested"
I agree that it is probably "safer" to only setup IDTR in the mode in which
it'll be used, but the idea that it's somehow safer is precautionary,
speculative, or possibly specious on my part. I think it's probably
perfectly safe either way. It's not like most of the x86 instructions have
strict interlocking rulesets which prohibit all but a few "valid" uses. For
the most part, they are generic. Some have very specific, mode specific
rules, e.g., ret.
Rod Pemberton