Mail Archives: djgpp/1999/08/07/14:15:17
On Sun, 18 Jul 1999, Mark wrote:
>
> - Can this _dos_ds looked at as some kind of 'portal with guardsmen' that
> allow 0 to 1 MB addresses?
>
> - If so ... Are all _farnspokeb(), _farnspokel(), _farnspeekw() etc. codes
> using that same 'portal' defined once(?) in a porgram with
> _farsetsel(_dos_ds)?
>
> - Can I just use the same _dos_ds with all my _farpokeb() accesses to those
> addresses? Or does _my_ds come in here somewhere?
>
> - And what does the DS mean in _dos_ds?
_dos_ds is a selector pointing to the first megabyte of linear memory (The
one typically used by real-mode DOS programs, and the place where 0xA0000
is). This selector is provided because many protected mode programs want
to use that memory without having to go to the trouble of allocating it,
etc.; since it is always available to programs compiled with real-mode
compilers. Users of DJGPP say: "THATS NOT FAIR. I DON'T WANT TO GO THROUGH
ALL THAT S**T!" So DJ Delorie say okidoke, here ya go: _dos_ds.
Yes, _dos_ds is good for all _far* accesses. What I usually do is assign
it to a local variable... it's a function call that can be avoided.
And DS means data segment... in real mode, your DS in any program where
you have chosen a memory model with a seperate data segment is always 0
> >> - Why are there so many functions that look like they are far or near types
> >> ? The compiler is 32bit and in the FAQ stated that DJGPP doesn't even
> >> recognise the far and near types ?!?!
> >
> >Some compilers allow you to specify near and far as part of the pointer,
> >like `char far *p'. GCC (DJGPP's compiler) doesn't-- all pointers are
> >effectively near. These functions are provided to let you access memory
> >outside your segment anyway.
>
> I don't realy get this. Where will my pointers become far or remain near?
> If I were to declare:
> int i[100], *ptr;
> ptr=i;
> Is this within my program's segment or is it going to be far?
> If far, ... what would be near?
> And if I were to declare:
> unsigned char *double_buffer
> double_buffer = (unsigned char *)malloc(320*200);
> This 'double_buffer' is far, right?
> If there are any differences between the '*ptr' and the 'double_buffer',
> what are they?
Okay, here's the DJGPP pointer skinny: In the old skool real mode
programs, to get outside your silly 16-bit segment, you had to declare a
far * type pointer... to get access to 0xA000 for example. That makes the
pointer 32-bit, 16-bit segment, 16-bit offset. Right?
In DJGPP, all pointers you declare are 32-bit pointers, but in protected
mode, these pointers are near. Why near? Because you still have only
access to the memory pointed at by DS when the program is launched. (That
is what near means). For safety reasons, protected mode selectors (like
your DS) have a cap on which memory addresses can be referenced, and
0xA0000 is out of range. To get at it, you need a far pointer. For
compatibility with DJGPP and UNIX oriented gcc, there is no such thing as
a far pointer. In environments like UNIX, not being able to break out of
your memory space is a good idea. DJ Delorie spake: This will not do! DOS
users need a way to get out of near mode." So he added some far* functions
to do the dirty, incompatible work. These pointers are 48-bit, 16-bit
selector (like _dos_ds, for example) and a 32-bit offset. This allows you
to BREAK OUT and access stuff pointed at by those other segment selectors.
So no, int i[100], i[140342342], and *ptr are all near. You can actually
allocate arrays as big as you can imagine (well, until the DPMI server
complains). But to get out of the pen, you need those far* functions that
insert the Intel PC only code.
Note: Don't get cocky with far* functions. you can cause lots of General
Protect Faults if you aren't prudent with making sure your selectors are
valid and you're not accessing memory outside their limits. Case in point:
memory at the _dos_ds selector DOES NOT wrap around if your offset is past
0xFFFF. That's when your program goes down.
Finally, if you're really slick, you can try this trick. Instead of using
_far pokey functions, you can use the __djgpp_nearptr_enable() hack.
What does it do? It changes the segment limit of your normal DS (which all
your near pointers use) to 2 ^ 32, meaning all memory is accessible by any
near pointer... Be careful, ALL memory is now under your control and you
can easily bring down Windows or DOS or whatever you're in if you're not
careful.
To get access say to 0xA0000 with a regular 'ol array...
#include "dpmi.h" //dpmi_int, to get into video mode 0x13.
#include "sys/nearptr.h" //nearptr stuff, and __djgpp_conventional_base
void main (void)
{
__djgpp_nearptr_enable(); //YOWZERS! WHAT A DAREDEVIL!
char * videobuffer = 0xA0000 + __djgpp_conventional_base;
__dpmi_int(0x13);
for(int i = 0; i < 64000; i++)
videobuffer[i] = i; //Make a silly pattern
__djgpp_nearptr_disable(); //Dont forget to clean up.
}
That should fill your screen with some stupid colors.
But look! No far pointers!
_djgpp_conventional_base is a constant that makes the pointer point to the
"real zero" of your memory. Add any constant, and the pointer is pointing
to where you really want it to be. 0xA0000 is where your VGA screenbuffer
is... and so with that you can do whatever.
This is my favorite way of getting at low DOS memory, or VESA linear
framebuffers.
Just remember though, be careful. Don't be alarmed if a program you write
with this trick causes your system to reboot.
Educating PC hackers....
moogla
- Raw text -