[comp.sys.ibm.pc] here is how to determine memory size before going TSR, SOURCE included

jchvr@ihlpb.ATT.COM (Schipaanboord) (09/25/88)

Here is some source code you can compile that shows how to determine the size
the program needs before calling the TSR routine, it should work for
any normal compiler which has a small memory model.

===== CUT HERE ===========
/*
   This program must be compiled and linked as SMALL memory model,
   As such it is a demo showing how to determine the memory needed by
   this program in case you want to go TSR.

   Submitted by: ihnp4!ihlpb!hvlpa!hvriets
   Use or abuse at your own risk!
*/

/*
	Generic Small memory model, known for MSC and Lattice-C:
	Where Small means: ONE segment for program code pointed to by CS
	and ONE segment for data (all kinds), pointed to by DS

	LOMEM

		+---------------+
		| PSP		| 256 bytes
		+---------------+
	CS ->	| program code  | knows as _TEXT in MSC
		+---------------+
		| Optional junk | in MSC called NULL
		+---------------+
	DS ->	| global data	| static data, in MSC: _DATA,CONST,_BSS
		+---------------+
		| local data	| in Lattice-C size given by extern int _stack
		|		| in MSC known as STACK
		+---------------+
		| malloc area	| created by calling malloc(), in MSC: HEAP
	ptr ->	+---------------+

	HIMEM


	Total size in paragraphs is basically (ptr-CS+PSP_SIZE) / 16
	provided that malloc gives increasing values.

	Every time you call malloc() the 'malloc area' is increased in size
	with N bytes, where N is 2 larger than the argument given to
	malloc(). These 2 bytes are used for a pointer to the next malloc block
	This however might differ in different compilers.

*/
#include	<stdio.h>
#include	<dos.h>		/* to define SREGS */

#define	PSP_SIZE	256	/* 0xFF bytes for PSP */
#define	PAR_SIZE	16	/* paragraph size */
#define	PAR_ROUND	15	/* vaue to round to next paragraph boundary */

#if LATTICE
extern	int _TSIZE;		/* Lattice-C value for memsize in paragraphs */
#endif

extern	char *malloc();
struct	SREGS	sregs;

main()
{	char	*ptr,*ptr2;
	int	malloc_overhead;
	int	size;

/* first determine value of ptr and malloc_overhead*/
	ptr = malloc(2);
	ptr2 = malloc(2);
	malloc_overhead = (int)ptr2 - (int)ptr -2;
	printf("\nMalloc overhead is %d bytes\n",malloc_overhead);
	if ( malloc_overhead < 0 ) {
		printf("Your malloc does not work as expected\n");
		exit(1);
	}

/* read value of CS and DS segments */
	segread(&sregs);
	printf("SS=%d ES=%d DS=%d CS=%d\n",sregs.ss,sregs.es,sregs.ds,sregs.cs);
	printf("SS=0x%x ES=0x%x DS=0x%x CS=0x%x\n",sregs.ss,sregs.es,sregs.ds,sregs.cs);

/* ds*PAR_SIZE converts paragraph address into real address */
/* +ptr adds offset to last data item */
/* +PAR_ROUND rounds it off to next paragraph boundary */
/* -malloc_overhead to correct for  malloc info */
/* +PSP_SIZE to leave room for PSP */
/* /PAR_SIZE to convert back into paragraphs */

	size = (sregs.ds*PAR_SIZE +(int)ptr +PAR_ROUND -malloc_overhead +
	     PSP_SIZE -sregs.cs*PAR_SIZE)/PAR_SIZE;
	printf("Size in paragraphs=%d 0x%x\n",size,size);

#if LATTICE
	printf("\nSize according to _TSIZE=%d 0x%x\n",_TSIZE,_TSIZE);
	printf("This size is one larger than our size, because we do\n");
	printf("NOT count the malloced() area, and LATTICE does\n");
#endif

	printf("\nAnd as subroutine: %d\n",parsize());
	printf("Please notice that when you call parsize()\n");
	printf("The memory gets larger, due to call to malloc()\n");
	printf("Since parsize() frees memory afterwards, this effect is\n");
	printf("NOT compounding, as you can see be the next call\n");
	printf("\nAnd as subroutine 2nd time: %d\n",parsize());

}/*main*/


/* as subroutine, ignoring malloc_overhead */
int	parsize()
{	struct SREGS	srg;
	char	*	ptr;
	int	res;

	ptr = malloc(2);
	segread(&srg);
	res = (srg.ds-srg.cs) + ( ((int)ptr+15) >> 4) +16;
	free(ptr);
	return(res);
}/*parsize*/


/* once you have allocated enough memory via malloc() for your program
   you can use the value of parsize(), as argument for the TSR call in INT21
   Good luck, but be aware that many library routines routinely still try
   to call malloc for more memory, once you have gone TSR, you cannot use
   these routines anymore, so be careful
*/

TSR()
{	union	REGS rg;	/* defined in dos.h */

	rg.x.ax = 0x3100;	/* int21 TSR function */
	rg.x.dx = parsize();	/* set size in pars. */
	intdos(&rg,&rg);	/* does not return */
	
}/*TSR*/