From: vincent@datmuc.UUCP (vincent)
Newsgroups: alt.msdos.programmer,comp.os.msdos.programmer
Subject: Re: my_tsr
Date: 19 Nov 92 09:43:35 GMT
Followup-To: alt.msdos.programmer,comp.os.msdos.programmer
Organization: DAT

In article <smithbm.722096804@craft.camp.clarkson.edu> smithbm@craft.camp.clarkson.edu (Azrak) writes:
>c.brennan@student.utas.edu.au (chris brennan) writes:
>
>>In article <smithbm.721597007@craft.camp.clarkson.edu>, smithbm@craft.camp.clarkson.edu (Azrak) writes:
>>> 
>>> vincent@datmuc.UUCP (vincent) writes:
>>> 

Lots of stuff deleted.

Look guys (Brian and Azrak included) when I posted my code with a problem in it,
Nobody got me any clue whatsoever about why it (still) doesn't work. The
problem was not about calling DOS or saving DS, (Brian did you ever looked at
the code generated for a declared _interrupt function), the original problem
was in the stack switching code, using in line assembly, durring an interrupt
since you don't know how much stack space you have, and that you also migth
be interrupted while running (if you write your intrerrupt function reentrant).

By the way I'm continuing debuging the rest of my code not switching stack.
(The original program is writen in c++)

It is recomended inside Andrew Schulman's book to spanwn a prosess instead
of going tsr, for debuging purpose. But my other interrupt is the multiplex
interrupt (INT 2F) and It have to be resident and passed the multiplex id
in the ax register. This is now completed. (T'was tricky to write in C, '++O )

P.S.	For those who didn't follow, here it is again (sorry for the band with)
	But I still can't figure out why it doesn't work. In the mean time I 
	think that saving DS before returning is not necesary, on return the
	code (transparent) will pop all (POPA) register, so it (the interrupt)
	only needs to restore the original stack.

P.P.S Nobody answered the P.Ss as the bottom either.

///////////////////////////////////////////////////////////////////////////

Subject: my_tsr
Newsgroups: alt.msdos.programmer,comp.os.msdos.programmer

This is a (re)repost I never got any replys, The Org. Q. was why this code
doesn't work?

Some people on the net said that it was uncommented (correct I comment
finish projects so my boss is happy). As to what the code does. Here we go.

I forge this sample tsr from the examples in Andrew Schulman's book
'Undocumented DOS':

The main part allocated a stack, frees the envirement, get and set the timer
interrupt, calculates the size of the tsr, shrink the program block accordingnly
and then go tsr.

The tsr should pop up durring timer interrupt, save forground stack and data
segment, set our stack and data segement, make base pointer relative to the
stack pointer, call the timer function (now only increments variable),
on return from it reset the stack and the data segment and then chain
the interrupt.

All data are in the code segment (for futur migth be a .COM file)

The compile flags turns off stack check, disable optimisation, use small
memory model, ... (maybe need to put #pragma (check_pointer off)

---------------------  snip snip -------------------------- makefile

CFLAGS = /Fc /Zi /f /Od /Gs /AS /W4 /nologo

main.exe : main.obj
	cl /Zi /Fm main.obj

.c.obj:
	cl /c $(CFLAGS) $(@B).c

---------------------  snip snip --------------------------- main.c

#include	<stdlib.h>
#include	<dos.h>
#include	<bios.h>

#define	CODESEG			_based(_segname("_CODE"))
#define MK_FP(seg,ofs)		((void _far *) ((((long)seg)<<16) + (long)ofs))
#define PARAGRAPHS(x)		((FP_OFF(x) + 15) >> 4)

typedef			void	(interrupt _far *INTVECT) ();

struct {
	INTVECT	old_timer;

	unsigned char _far * CODESEG tsrstack;

	int	oldSP,
		oldSS,
		oldDS,
		ds_save,
		seg_stack,
		off_stack,
		retadd,
		tick_me;
} CODESEG data;

void ctimer (void)
{
	data. tick_me++;
}

void _interrupt _far new_timer (void)
{
	_asm {
		mov	cs:data. oldSS, ss	; save forground stuff
		mov	cs:data. oldSP, sp
		mov	cs:data. oldDS, ds
				 		 ; Load new stack
		mov	ss, cs:data. seg_stack
		mov	sp, cs:data. off_stack
		mov	ds, cs:data. ds_save

		mov	bp, sp			; make bp relative to sp
						; why? I don't know

		call	ctimer			; do some proccessing

		mov	ss, cs:data. oldSS	; restore the forground stuff
		mov	sp, cs:data. oldSP
		mov	ds, cs:data. oldDS

		mov	bp, sp
	}
	_chain_intr (data. old_timer);		; jump to old function
}

void main ()
{
	unsigned int memtop, dumy = 0;

	data. tick_me = 0;				// init. variables

							// free envirement
	_dos_freemem (*(short _far *) MK_FP (_psp, 0x2c));

							// allocate a stack
	data. tsrstack = malloc (1024);
	data. tsrstack += 1024;				// go to the top of it

	data. seg_stack = FP_SEG (data. tsrstack);	// save the segment and
	data. off_stack = FP_OFF (data. tsrstack);	// the offset for latter

	_asm mov cs:data. ds_save, ds			// save the data segment

							// calculate the size
	memtop = data. ds_save + PARAGRAPHS (data. tsrstack) - _psp;

	_dos_setblock (memtop, _psp, &dumy);		// shrink the prog.

	data. old_timer = _dos_getvect (0x08);		// get and set the timer
	_dos_setvect (0x08, new_timer);			// interrupt

	_dos_keep (0, memtop);				// go tsr
}

---------------------------------------------------------------------

vincent@datmuc.dat.de

P.S. Well I hope this is better documented (my boss would be happy)

P.P.S. The problem is that on return to DOS (COMMAND) sucessive program
crash (window for example);

P.P.P.S. I will continue on my side like instead of allocating a stack,
have a fix buffer in the code segment. Also to date I'm not shure
if I need to save the DS since it is anyway restore at the interrupt.
Also in the inline asembly I might try to set ds to cs (for my data) and
also for the stack seg.. (I guess I do need my own stack). The only thing I know
about .COM is that LINK tell me that for tiny memory model I am not alowed
to have _far pointers.