[comp.os.msdos.programmer] huge-far pointer and Turbo C++ V1

stephenj@deblil.Eng.Sun.COM (Stephen Johnson) (02/19/91)

/* The following program should be compiled with:

tcc -mh <prog>.c

This program allocates a very large array of memory
and addresses using the "far" key word.  Unfortunately, the
address calculations rap around at 64k.  Does anyone know why
this happens?  Is this a bug in the Turbo C++ libraries?

I am using Trubo C++ V1.0 on a Dell 310 (386 box)
with 640k of DOS memory and 4 Meg of real memory.
thanks, Stephen Johnson
*/

#include <stdio.h>
#include <alloc.h>

#define ULONG unsigned long

ULONG far *zbuffer = NULL;

void z_buffer_init();
void z_buffer_test();

main()
{
    printf("Available memory: %lu\n", farcoreleft());
    printf("We will allocate: %lu\n", (ULONG)sizeof(ULONG) *
        (long)320 * (long)200);

    zbuffer = (ULONG far *)farmalloc((ULONG)sizeof(ULONG) *
        (ULONG)320 * (ULONG)200);

    z_buffer_init();
    z_buffer_test();
}

void
z_buffer_init()
{
    ULONG far 	*zbuf;
    long	nwords = (long)320 * (long)200;

    zbuf = zbuffer;
    while (--nwords) {
        *zbuf = (ULONG)(((ULONG)1 << (ULONG)24) - (ULONG)512);
        zbuf++;
    }
}

void
z_buffer_test()
{
    long	 nwords = (long)320 * (long)200;
    ULONG far    *zbuf;

    zbuf = zbuffer;

    while (--nwords) {
        if (*zbuf > (ULONG)10) {
            *zbuf = (ULONG)10;
	}
	else {
	    printf("nwords: %lu\n", nwords);
	    printf("value: %lx\n", *zbuf);
	    printf("start: %lx\n", (ULONG)zbuffer);
	    printf("addr: failed at %lx\n", (ULONG)zbuf);
return;
	}
	zbuf++;
    }
}

roy%cybrspc@cs.umn.edu (Roy M. Silvernail) (02/19/91)

stephenj@deblil.Eng.Sun.COM (Stephen Johnson) writes:

> This program allocates a very large array of memory
> and addresses using the "far" key word.  Unfortunately, the
> address calculations rap around at 64k.  Does anyone know why
> this happens?  Is this a bug in the Turbo C++ libraries?

As far as I'm aware, the problem is with the 'far ' keyword. Actually,
it's not a problem at all, as far calls are advertised to wrap at 64k
boundries.

I think you want the 'huge' keyword there.
--
Roy M. Silvernail --  roy%cybrspc@cs.umn.edu - OR-  cybrspc!roy@cs.umn.edu
Department of redundancy department, or "Take the long way home...":
main(){system("perl -e '$x = 1/50; print \"Still just my \\$$x!\n\"'");}
               [new year, new .sig, same ol' cyberspace]

berg@marvin.e17.physik.tu-muenchen.de (Stephen R. van den Berg) (02/19/91)

Stephen Johnson writes:
>This program allocates a very large array of memory
>and addresses using the "far" key word.  Unfortunately, the
>address calculations rap around at 64k.

>    ULONG far    *zbuf;

I suggest you use the 'huge' keyword instead of 'far'.
--
Sincerely,                 berg@marvin.e17.physik.tu-muenchen.de
           Stephen R. van den Berg.
"I code it in 5 min, optimize it in 90 min, because it's so well optimized:
it runs in only 5 min.  Actually, most of the time I optimize programs."

ISSHST@BYUVM.BITNET (02/21/91)

My understanding of TC++ is that a single data structure cannot be larger
than 64K.  To solve this, use an array of pointers and allocate each row
of the z-buffer separately.  Then you can use whatever of 640K is left.

teexnma@ioe.lon.ac.uk (Nino Margetic) (02/22/91)

In <91052.082658ISSHST@BYUVM.BITNET> ISSHST@BYUVM.BITNET writes:

>My understanding of TC++ is that a single data structure cannot be larger
>than 64K.  To solve this, use an array of pointers and allocate each row
>of the z-buffer separately.  Then you can use whatever of 640K is left.

***** Not quite. If you declare your pointer as huge, and use
farmalloc/farcalloc, then you can allocate ALL available RAM in just
one object. Since the farmallooc/farcalloc takes an unsigned long it
is NOT the same as malloc/calloc - not even in the large memory
models. BUT, you HAVE to use HUGE pointers - otherwise your far
pointer will wrap at the 64k boundary.
Hope this helps.

--Nino

-- 
Janet: nino@uk.ac.ucl.sm.mph                    \    Nino Margetic
Earn/Bitnet: nino@mph.sm.ucl.ac.uk               \   Dept. of Medical Physics
Internet: nino%mph.sm.ucl.ac.uk@nsfnet-relay.ac.uk\  University College London
Bang-path: ....!mcvax!ukc!ucl-mph!nino             \ Tel:+44-71-380-9300/x5313

quimby@madoka.its.rpi.edu (Tom Stewart) (02/25/91)

teexnma@ioe.lon.ac.uk (Nino Margetic) writes:

>>    <previous text about memory allocation>

>***** Not quite. If you declare your pointer as huge, and use
>farmalloc/farcalloc, then you can allocate ALL available RAM in just
>one object. Since the farmallooc/farcalloc takes an unsigned long it
>is NOT the same as malloc/calloc - not even in the large memory
>models. BUT, you HAVE to use HUGE pointers - otherwise your far
>pointer will wrap at the 64k boundary.
>Hope this helps.

An interesting situation occurs if you happen to try allocations
beyond 64k with 'new' -- it will allocate the requested amount, modulus
64k, and return a valid huge pointer to a <64k block.
  
Quimby
  
(mailer disfunctional, replies to: quimby@mts.rpi.edu, quimby@rpitsmts.bitnet)
 

dougs@videovax.tv.tek.com (Doug Stevens) (02/26/91)

In article <91052.082658ISSHST@BYUVM.BITNET>, ISSHST@BYUVM.BITNET writes:
> My understanding of TC++ is that a single data structure cannot be larger
> than 64K. 

This is not true; farmalloc() takes as an size argument an unsigned long,
allowing blocks larger than 64K to be malloc'd. If you then use huge pointer
arithmetic on the pointer returned, everthing will be OK (but a little slower
than accesses to a regular -- less than 64K -- block).