I have an odd question. Let's say I wanted to call a 16-bit procedure from a 32-bit one using an address type override. Once I am in that 16-bit procedure, how do I access portions of that segment above a 16-bit offset of 0FFFFh?
Okay, let's clear something up first. In order to call 16
bit code from a 32 bit segment (or vice versa), you must use
a gall cate. Simply using an override won't cut it.
So, assuming you're using a call gate to access a 16 bit
routine, you must remember that a 16 bit segment must in fact
be assembled -AS- a 16 bit segment (meaning you have to
specifically define a 16 bit segment, as opposed to the general
flat memory model).
Okay, assuming you're doing all of that, you should still be
able to access memory above 0FFFFh, although it's not
recommended that you try this. You should be able to use
32 bit pointers in a 16 bit segment, but if I remember
correctly, they won't access above 65535, no matter what the
actual value is. So, you have to include a 32 bit base address
(ie: mov ax,). Since 16 bit segments don't limit
you to only 16 bit registers, this command should assemble
correctly in either 16 or 32 bit code. Whether it will execute,
however, is a different matter.
This is an extremely difficult thing to do in any operating
system, and so I wouldn't recommend such a technique for a
beginner in Windows programming. =)
Heh, sorry. I meant to say a call gate, not gall cate. =)
Oh, I thought you could just use an address size override...how do you do this with call gate and what is a call gate?
You should probably read a good book on protected mode
programming, or Windows system programming to understand
the basics behind mixing 16 and 32 bit code. Explaining
it on this board in any amount of detail would take me
a long time, and probably raise a bunch of concerns by
the Windows programmers here. (Call gates are sometimes used
in VxDs, but can also be used by virus programmers, and other
drains on society. :)) But, here's a basic explanation
without getting too deep into it.
In an 286+ processor, there are two modes: real and protected.
When designing protected mode, Intel must've reached a problem.
How are you supposed to call a routine in a lower privilage
level? (A privilage level is also called a 'ring' in Windows
terminology). They answered this with the 'call gate'. Stored
in descriptor format in either the LDT or GDT, this allows you
to access a different privilage level, or even a different
format (16 or 32 bit) from your current segment. As I'm sure
you can already see, it's quite a complex task even without
Windows! :)
A good place to get information, and even ask questions about
this, is www.sandpile.org, but be warned: sandpile is a
totally CPU oriented place. They don't discuss any operating
systems, or even PC computers...only the processor itself.
Don't forget the mode "virtual 86"... when windows opens a dos prompt, the dos prompt is in what's called "virtual 86", the dos program actually thinks the processor is a 8086. The reason for this 3rd mode, is because you can't go from protected to real, without rebooting.
Just thought i would add that nice tidbit of info :)
"Don't forget the mode "virtual 86"... when windows opens a dos prompt, the dos prompt is in what's called "virtual 86", the dos program actually
thinks the processor is a 8086. The reason for this 3rd mode, is because you can't go from protected to real, without rebooting."
Wrong! This is only for the 286 processor (which conviently didn't
have a V86 mode). The 386 and above, which is required for
Windows 32 programming, allows you to set and reset the PE bit
of CR0 (bit 0) to enter and leave protected mode at will.
However, in a 286 processor, it is necessary to triple-fault the
CPU to go from protected to real mode. :)
I wasn't trying to argue anything, just throwing a fact about the x86 processors used today, and i'm fully aware that the 286 doesn't include virtual x86 mode.
I have no problems with people posting facts about the basic CPUs,
however I do have a problem when those facts are provided
incorrectly. The 'fact' about processors being unable to return
to real mode without rebooting is false. First, the term is
'triple-fault'. Reboot implies the entire computer must be reset,
whereas triple-faulting forces the CPU to clear all it's registers
and begin executing in real mode at F000:FFF0 (which you change in
order to make it execute where you want it to). Secondly, this
is only for 286 processors, which, although a good trivia tidbit,
is rather useless to post on a Win32 forum. :)
Another inconsistancy is with the V86 mode. Yes, V86 mode was
designed for real mode, but it does not make the CPU think it's an
8086, just that it's in a virutal real mode. It was called
Virtual 8086 only because programmers would recognize the 8086
with real mode. If you don't believe me, open up a DOS prompt,
Debug, and type these bytes in at 100h (e 100):
0F 20 00 0C 01 0F 22 00 34 01 0F 22 00 CC
then use go. The program does nothing of interest, but uses
CR0 to enter and leave protected mode. V86 does not emulate
an 8086...merely real mode.
These are the facts for any who is truly interested. This is
not an attack on anyone, least of all you, Jon. I've often
asked for information on the CPU only to be given faulty,
inaccurate, or confused information, so I know how frustrating it
can be. I'm only trying to make sure that, anyone who wants this
information has the most accurate information they can.
How many modes are available on the 8086? Just one, "Real Mode", thus virtual 86 mode does trick the program into thinking it's an 8086 or "Real Mode". So my fact is correct, also, in my book "Master Class Assembly Language", it says that the processor can't go from protected to real, unless the processor is reset, thus rebooted. Write some code to go from protected->real... i would like to see you prove that book wrong.
Well, now let's not forget the indisputable 80186. Running most
of the PS/2s in the world, and I think PCjr, but don't quote me,
it also only had real mode.
Oh, and by the way, here's the program that PROVES how easy it
is to leave protected mode in a 386:
mov eax,cr0
or al,1
mov cr0,eax
xor al,1
mov cr0,eax
As Emeril Lagassee would say, BAM! However, this may not
suit your requirements to m, so here's a MUCH better example.
It's an entire program which runs specifically from a boot
sector.
0000: MOV AX,7D0
0003: MOV DS,AX
0005: LGDT QWORD PTR [0]
000A: MOV EAX,CR0
000D: OR AL,1
000F: MOV CR0,EAX
0012: JMP FAR 0008:0017
; in 16 bit protected mode
0017: XOR AL,1
0019: MOV CR0,EAX
001C: JMP FAR 07C0:0021
; in 16 bit real mode
0021: JMP 0021
...
0100: 10 00 00 7D 00 00 00 00
0108: FF FF 00 7C 00 9B 00 00
...
01FE: 55 AA
Granted the program does almost nothing of any great interest,
however it should in fact meet your requirements for proof, does
it not?
If you're still not convinced I actually DO know what I'm talking
about, email me and I'll send you the program, and even tell you
how to install and execute it. But I can assure you, it's no
longer necessary to triple-fault the CPU in order to go from
protected to real mode!
x86.org and sandpile.org would agree with me, so if you still don't
believe me, go there and present your facts, although don't be
surprised if they cut your facts down to reality, as I have.
At this point, yes it's a bit of a flame. I tend to get that way
when I'm challenged...so I apologize to anyone caught in the
crossfire, and I apologize to this ENTIRE web board. It's not
meant to cover the basics of protected mode programming, however
a person must always answer a challenge, especially if they can.
This message was edited by Racso, on 2/18/2001 10:49:13 PM
Going back to the original question......
Under general windows programming, i think you are a little confused...for instance
assume es: nothing
mov es,'any segment number'
call fword ptr es:[0]
will call a proc at the address es:[0]. If this is a 16bit segment. It will run as a 16bit segment, if its a 32bit segment, it will run as a 32bit segment.
But to add to this, there is two opcode prefixes 66h and 67h which override the operand size and the address size for an instruction.
;in a 32bit segment
BYTE 066h
mov eax,eax
;is actualy decoded as
mov ax,ax
;And in a 16bit segement
BYTE 066h
mov ax,ax
;is actualy decoded as
mov eax,eax
And to add to this, unless you are VxD programming, all this will mean little to you, because to my knowledge, its not 'normal' to get a 16bit segment in the address space of your app that will be running at ring3.Well, even so, that's risky. Assuming that
CALL FWORD PTR ES:[0]
will actually assemble, and assuming that it won't just call the
address at es:[0], then you still have to worry about the privilage
levels in EFLAGS, the selector, and in the descriptor. For
instance, if the EFLAGS privilage is 3 and the selector is 3,
but the descriptor is 2 or higher, you'll get an exception 0D,
or page fault.
But assuming everything is fine and is executed as you would
expect it to, then sure. That's a way to do it without a call
gate...but it's reliability is dubious to say the least. :)
Well it seems i stand corrected, i apologize. Anyways... if i run a dos protected mode program, why does it require i reboot?:(
There are a few reasons why Windows doesn't like protected mode
programs -other- than other Windows programs running. First,
protected mode can only exist if the programs are protected.
To Windows' way of thinking, a DOS protected mode program or
DPMI (though not all protected mode programs in DOS -ARE- DPMI)
or even VCPI, then it's not safe and thus, Windows wants as little
to do with it as possible. :)
The reason is that the control registers (CR0, CR3, etc...) and
the data (?) registers (DR0, DR6, DR7, etc.) have to be secure.
You don't want these registers to change without warning, and
without Windows being able to control it...or else all hell would
break loose! So, if Windows can't emulate these registers
effectively, the program is considered unstable, and execution
ceases quickly.
Most DOS protected mode programs, though, use DPMI or VCPI, and seem
to be very stable under Windows...at least under 95 and 98; under
Windows NT and 2000, they're probably far less stable. However,
even though they may be stable, Windows will still often inform
you that the program was meant for MS-DOS and may not run properly
in Windows. I usually ignore the message because the programs
seem to run fine. But, if they don't, you can try to limit the
amount of DPMI/VCPI memory the program has access to by right-
clicking on the program, selecting properties, and memory. If
the problem is in the control registers, though, this may not have
much effect.