[Prev][Next][Index][Thread]

Re: switching to real mode



>   Ok, I tried a simple test of this, based on the code in raw_real_int.c, but
> I get a ton of link-time error messages. Right now I'm linking to 0x3000000
> (like OSKit's netboot does) so I can use GDB. I relocate the 16bit boot code
> from 0x300000 to 0x7c00. (where an NBP image is supposed to go)
> 
>     do_16bit(KERNEL_CS, KERNEL_16_CS,
>              i16_raw_switch_to_real_mode();
>              _prnchr('#');			// a 16bit output routine
>              i16_raw_switch_to_pmode();
>         );

While I have don 16-bit x86 programming, I haven't done this before, so
take what I say with a grain of salt.

I am afraid that much of that code may have atrophied lately.  I did look
at getting the DOS stuff working again last summer, but there aren't
a lot of developers using 16-bit code for more than getting into 32-bit
mode (and that is usually all in assembly language).

A big part of the problem is the lack of better support from the
compiler/assembler.  The gcc/gas people don't care about compiling C
for a 16-bit enviroment.

> > Now a few words about the "at least in theory" above: all of the switching
> > code assumes that EIP < 65536 and ESP < 65536.  This basically means that
> > you are restricted to 64K.  This is not entirely true, as only the stack,
> > the switching code and all the 16 bit code needs to be below that line.
> > This can be achieved  by using the right order of object files when linking.
> 
>   So I assume this means I need to link to an address below 65536, even though
> that's where the 16 bit code is executed ?

Real mode uses segmented addresses, and can address only the first 1 MB of
memory: (segment << 4) + offset
You can address this entire amount, but you have to do it manually --
which confuses gcc/gas to no end.

You can link stuff wherever you like, but it will not ``just work'' if
the compiler cannot address it.  Also note that the macros involved in
do_16bit are very dependant on the assembler being able to do ``the right
thing'' with a .CODE16, and interoperate with gcc.  From what I understand
the semantics have changed a little with recent versions of gas.
So YMMV.

You can use any 64k segment, as long as you set up the segment registers
and use the offsets within the segment -- since only the offsets matter
with 16-bit addressing the segment can be anywhere in the low 1MB.
So it may look like it was linked at 0:1000, but it can be at 8000:1000,
as long as you set up the segment registers.  But like he mentioned,
that is not done automatically by the assembler & the macros.

I did write the smp support code, (oskit/smp/x86) which kicks a processor
from real mode to protected mode.  Not quite the same thing, but I did
it by allocating low memory, copying the code down there, and patching
the symbols manually.  This approach may be good enough (combined with
the guts of the macros to go to real mode) if you just need to run a
little bit of x86-assembly, but probably isn't what you want.

The OSKit's support came from a DOS Extender called MOSS (another project
at the University of Utah, by Bryan Ford).  You may want to look at that
for parts as well.  See http://www.cs.utah.edu/flux/moss/
It has probably bit-rotted, but the 16-bit code should be more intact
than it is in the OSKit.

Kevin Van Maren
University of Utah, CSL

Follow-Ups: