[comp.lang.c] Microsoft C far pointer dereferencing

julian@uhccux.uhcc.Hawaii.Edu (Julian Cowley) (08/16/90)

Ok, I've read the articles concerning the use of (void far *) in
Microsoft C, but I still can't figure out why the pointer in
following piece of code won't dereference.  What I'm trying to
do is access the MCGA screen at A000:0000, in case there is a
better way to do this...

PutPixel (int x, int y, unsigned char c)
{
  unsigned char far *mem;

  FP_SEG (mem) = 0xa000;
  FP_OFF (mem) = 320 * y + x;

  *mem = c;		/* <-- this line gives a run-time error */
}

julian cowley
university of hawaii at manoa
julian@uhccux.uhcc.hawaii.edu
julian@uhccux.bitnet

julian@uhccux.uhcc.Hawaii.Edu (Julian Cowley) (08/17/90)

In article <9031@uhccux.uhcc.Hawaii.Edu> I (Julian Cowley) wrote:
>Ok, I've read the articles concerning the use of (void far *) in
>Microsoft C, but I still can't figure out why the pointer in
>following piece of code won't dereference.

Oops, I forgot one crucial detail here: I'm using Quick C 2.01,
if that makes any difference (and I'm sure it might).

julian cowley
university of hawaii at manoa
julian@uhccux.uhcc.hawaii.edu
julian@uhccux.bitnet

mfinegan@uceng.UC.EDU (michael k finegan) (08/17/90)

julian@uhccux.uhcc.Hawaii.Edu (Julian Cowley) writes:

>Ok, I've read the articles concerning the use of (void far *) in
>Microsoft C, but I still can't figure out why the pointer in
>following piece of code won't dereference.  What I'm trying to
>do is access the MCGA screen at A000:0000, in case there is a
>better way to do this...

>PutPixel (int x, int y, unsigned char c)
>{
>  unsigned char far *mem;

>  FP_SEG (mem) = 0xa000;
>  FP_OFF (mem) = 320 * y + x;

>  *mem = c;		/* <-- this line gives a run-time error */
>}

If you look at the manual page again, it says the use of FP_*** is library
(i.e. memory model) dependent. For small and medium models, these macros
will only work if the pointer mem is in the default data segment. You have
it on the stack (subroutine automatic variables) - is that the problem ?

						- Mike
						  mfinegan@uceng.UC.EDU

julian@uhccux.uhcc.Hawaii.Edu (Julian Cowley) (08/17/90)

In article <5843@uceng.UC.EDU> mfinegan@uceng.UC.EDU (michael k finegan) writes:
>julian@uhccux.uhcc.Hawaii.Edu (Julian Cowley) writes:
>>PutPixel (int x, int y, unsigned char c)
>>{
>>  unsigned char far *mem;
>>
>>  FP_SEG (mem) = 0xa000;
>>  FP_OFF (mem) = 320 * y + x;
>>
>>  *mem = c;		/* <-- this line gives a run-time error */
>>}
>
>If you look at the manual page again, it says the use of FP_*** is library
>(i.e. memory model) dependent. For small and medium models, these macros
>will only work if the pointer mem is in the default data segment. You have
>it on the stack (subroutine automatic variables) - is that the problem ?

Unfortunately, no.  Moving the declaration outside of the
function body makes no difference in the behavior, even using
the large memory model.  I'm afraid that I have virtually no
knowledge of how Intel addressing works other than the
segment:offset concept, and even a quick scan through the
Microsoft manuals reveals none of the hocus-pocus assembly
language techniques that differentiate the memory models.
Since this is obviously moving outside the realm of comp.lang.c,
I'm going to repost to one of the comp.sys.ibm.pc.* groups.
Thanks to all who responded.

[ps. that was using quick c, not microsoft c proper...possible bug?]

julian cowley
university of hawaii at manoa
julian@uhccux.uhcc.hawaii.edu
julian@uhccux.bitnet

richardh@hpopd.HP.COM (Richard Hancock) (08/17/90)

/ hpopd:comp.lang.c / mfinegan@uceng.UC.EDU (michael k finegan) / 10:30 pm  Aug 16, 1990 /

>PutPixel (int x, int y, unsigned char c)
>{
>  unsigned char far *mem;

>  FP_SEG (mem) = 0xa000;
>  FP_OFF (mem) = 320 * y + x;

>  *mem = c;		/* <-- this line gives a run-time error */
>}

Why not use

  *((unsigned char far *)(0xA0000000L + 320*y + x)) = c;

mfinegan@uceng.UC.EDU (michael k finegan) (08/19/90)

julian@uhccux.uhcc.Hawaii.Edu (Julian Cowley) writes:

>In article <5843@uceng.UC.EDU> mfinegan@uceng.UC.EDU writes:
>>>PutPixel (int x, int y, unsigned char c)
>>>{
>>>  unsigned char far *mem;
>>>
>>>  FP_SEG (mem) = 0xa000;
>>>  FP_OFF (mem) = 320 * y + x;
>>>
>>>  *mem = c;		/* <-- this line gives a run-time error */
>>>}
>>
>>If you look at the manual page again, it says the use of FP_*** is library
>>(i.e. memory model) dependent. For small and medium models, these macros
>>will only work if the pointer mem is in the default data segment. You have
>>it on the stack (subroutine automatic variables) - is that the problem ?

>Unfortunately, no. 
~
~
~
>[ps. that was using quick c, not microsoft c proper...possible bug?]
They are certainly different libraries - but try using CL /AL to compile.
>julian@uhccux.bitnet

Funny, but the following works just fine on MSC v5.1 ... Did you select option
to recompile all libraries with latest code when you installed the compiler
(the idiots at MS should make it automatic, or send latest library precompiled!)
						    - Mike
						      mfinegan@uceng.UC.EDU
--------------------------------------------------------------------------------
#include <stdio.h>
#include <dos.h>

main(argc, argv)
int argc;
char **argv;
{
	int i, j;
	unsigned char value;
	union REGS inregs, outregs;

	if(argc == 2) {
	    value = argv[1][0];
	   /* set 320 by 200 by 256 graphics using assembler like interface */
	    inregs.x.ax = 0x0013;
	    int86(0x10,&inregs,&outregs);
	    for(i=0;i<200;i++)
	        for(j=0;j<320;j++)
		    putbyte(j, i, value);
	   /* restore 80 by 25 text using assembler like interface */
	    inregs.x.ax = 0x0003;
	    int86(0x10,&inregs,&outregs);
	}
}

unsigned char far *video_byte;

putbyte(x, y, value)
int x, y;
unsigned char value;
{
	FP_SEG(video_byte) = 0xa000;
	FP_OFF(video_byte) = 320*y + x;

	*video_byte = value;
}

tjr@cbnewsc.att.com (thomas.j.roberts) (08/20/90)

From article <7990017@hpopd.HP.COM>, by richardh@hpopd.HP.COM (Richard Hancock):
> / hpopd:comp.lang.c / mfinegan@uceng.UC.EDU (michael k finegan) / 10:30 pm  Aug 16, 1990 /
> 
>>PutPixel (int x, int y, unsigned char c)
>>{
>>  unsigned char far *mem;
> 
>>  FP_SEG (mem) = 0xa000;
>>  FP_OFF (mem) = 320 * y + x;
> 
>>  *mem = c;		/* <-- this line gives a run-time error */
>>}

In Turbo C, the FP_SEG(mem) = ...; statement gets "not an lvalue"
error. In Turbo C you should use:

	mem = MK_FP(0xA000,320*y+x);
	*mem = c;

Turbo C has the FP_SEG() and FP_OFF() macros as used above, and the
MK_FP() macto to create a far pointer; I assume Microsoft C does also,
but have no experience at all using Microsoft C.

Tom Roberts
att!ihlpl!tjrob