[net.micro.pc] Weirdness in PC???

greenber@timeinc.UUCP (Ross M. Greenberg) (06/18/85)

It seemed simple enough:  I merely wanted to set a flag when there was
a DOS call being processed.  So I took over int21h and had it point to
a routine called 'myint'

myint:
	mov	flag, 1
	int	62h
	mov	flag, 0
	iret

And it didn't work from a terminate and stay resident program, although
it works in the debugger!  As soon as the terminate code is run I
get a whole bunch of "Insufficient disk spaces" error messages forever
and ever.  Time to reset.

So I figured that maybe dos cares about the stack displacement (sounds
reasonable, right?). okay:

myint:
	pop	[pop1]
	pop	[pop2]
	pop	[pop3]
	mov	flag, 1
	int	62h
	mov	flag,0
	push	[pop3]
	push	[pop2]
	push	[pop1]
	iret

No good --- same problem. So therefore it appears that dos is making
recurssive calls to itself and cares about the current "called from"
CS:IP on the stack?

What is going on here?  I know that I can play massive games and save
dos's stack and so forth, but why should it bomb out like it does?

Additionally, I made up a little terminate and stay resident piece
of code for a friend of mine to give him keyclicks. I futzed with
the timer to increase the sound/duration. Works like a charm
on my PC --- but the timer stuff seems to have no effect on his
PC-XT.  What are the weirdnesses betwixt the PC and XT?

And finally, what would cause a terminate and stay resident piece
of code to not give its memory back to dos upon final exit?

Is dos as wierd as it seems? Did Microsoft get paid by some
peculiar "strangness" factor (the stranger the system, the more you
get...).  Or am I missing something?

Mail to me, and I'll post.....

-- 
------------------------------------------------------------------
Ross M. Greenberg  @ Time Inc, New York 
              --------->{ihnp4 | vax135}!timeinc!greenber<---------

I highly doubt that Time Inc. they would make me their spokesperson.
------
"There's something wrong in the world. There's always been. Something no one
has ever named or explained" --- Francisco d'Anconia

pda@galbp.UUCP (Paul Anderson) (06/19/85)

In article <1483> you write:
>It seemed simple enough:  I merely wanted to set a flag when there was
>a DOS call being processed.  So I took over int21h and had it point to
>a routine called 'myint'
>
>myint:
>	mov	flag, 1
>	int	62h
>	mov	flag, 0
>	iret
>
>And it didn't work from a terminate and stay resident program, although
>it works in the debugger!  As soon as the terminate code is run I
>get a whole bunch of "Insufficient disk spaces" error messages forever
>and ever.  Time to reset.
>
>So I figured that maybe dos cares about the stack displacement (sounds
>reasonable, right?). okay:
>
>myint:
>	pop	[pop1]
>	pop	[pop2]
>	pop	[pop3]
>	mov	flag, 1
>	int	62h
>	mov	flag,0
>	push	[pop3]
>	push	[pop2]
>	push	[pop1]
>	iret
>
>------------------------------------------------------------------
>Ross M. Greenberg  @ Time Inc, New York 
>              --------->{ihnp4 | vax135}!timeinc!greenber<---------

Ross-

    I think that what you may find is happening is that your DS: register
has not been set up to correctly address 'flag' in your data segment.
If this is the case, you have two possible alternatives, as 
illustrated below:

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

myint:
	mov	cs:flag, 1
	int	62h
	mov	cs:flag, 0
	iret

----------------------------------
assume cs:code, ds:data

myint:
	push	ds
	push	ax		;save callers ds, ax
	mov	ax,seg flag	;then resolve ds register to address 'flag'
	mov	ds,ax
	mov	flag,1
	pop	ax
	pop	ds

	int	62h

	push	ds
	push	ax
	mov	ax,seg flag
	mov	ds,ax
	mov	flag,0
	pop	ax
	pop	ds
	iret

  The first case presumes that 'flag' has been declared to be within
the reach of your CS: register.  This is very likely, from your statement
about attempting to create a terminate a stay resident program.
If, however, you are using a large model program (.exe format), your
DS: and CS: registers do not address the same data region and you must
specifically initialize the DS: register to access your data.


> No good --- same problem. So therefore it appears that dos is making
> recurssive calls to itself and cares about the current "called from"
> CS:IP on the stack?

  Your second guess about stack-specific offsets is a good point to
be addressed.  You were correct about the fact that PCDOS does call
itself in a moderately re-entrant fashion-- but only moderately!  It seems
that the first 12 function calls that DOS supports does not cause 
DOS to activate its internal stack, but the remainder of calls to
DOS will cause it to load the SP with a fixed stack address.  So, DOS,
for some functions will call itself if it has to print a character
on the console, get a key, etc...


> What is going on here?  I know that I can play massive games and save
> dos's stack and so forth, but why should it bomb out like it does?

Hmm... interesting point to be made on stack swapping (saving dos'
stack in a buffer and then calling dos again).  DOS does have some
static variable storage-- main case in point is the fact that DOS
(although singlethreaded) maintains 'processes' for jobs running
in the system.  This process id is kept in static storage and changes
for every program invocation, death and 'shell' command.  The 
process id is mainly used to keep track of what job has what files
open in the system. As a result, a terminate and stay resident program
should not issue XENIX compatible file requests, BECAUSE it has 
'terminated' as an active job.  FCB requests are
valid- since DOS does not track their use on a process basis (on 
non-network systems).


> Additionally, I made up a little terminate and stay resident piece
> of code for a friend of mine to give him keyclicks. I futzed with
> the timer to increase the sound/duration. Works like a charm
> on my PC --- but the timer stuff seems to have no effect on his
> PC-XT.  What are the weirdnesses betwixt the PC and XT?

  Don't know.

> And finally, what would cause a terminate and stay resident piece
> of code to not give its memory back to dos upon final exit?

  The DOS manual gives just a short discourse on T & SR programs-
however, it is very lacking in depth.  It does state 
that a T & SR program is 'just like COMMAND.COM' and
'becomes part of the system code'.  Therefore, reading between
the lines, one finds the statement: 'System code, once loaded does
not exit.'  And then finally on the applications side-- when
the T & SR program issues a final termination (attempting to
release itself as a system resource), the system only knows that the active
process is terminating-- not necessarily your piece of code.  So
it is conceivable that you may 'kill' COMMAND.COM (or LOTUS, or BASIC,
etc...).  
  Another side note is that other jobs may have been loaded
at a later time than your T & SR. Those other jobs may have inter-
cepted int 21h as well- and generated a forward link in a similar
fashion.  To be completely terse: think what happens when you try
to unlink from the middle of a chain!


> Is dos as wierd as it seems? Did Microsoft get paid by some
> peculiar "strangness" factor (the stranger the system, the more you
> get...).  Or am I missing something?

Chortle.


-----------------------------------------------------------------------------
Paul Anderson	(akgua!galbp!pda)		The opinions expressed herein
						do not reflect the views of
"2 years, 5 mounts, and I still don't		My Employer. My avocado plant
understand it..."				thinks otherwise.	

jnw@mcnc.UUCP (John White) (06/22/85)

     When a program is executed in ms-dos 2.x it is given two blocks of
memory. One is the main block that starts at the begining of the 100h header
and contains the program, the other is the environment block whose starting
segment is given at offset 2Ch of the header. When the program terminates
these two blocks are freed. If the program terminates-and-stays-resident,
the environment block is not freed and the main block is shortened to the
length specified by the terminate call. I have written terminate-and-
stay-resident goodies that are removable. If the program is given the
"remove" switch then, instead of installing itself, it looks at the
interupt vector changed by a previous installation to find the address
of the installed versions main block. Then the old vector is loaded from
the appropriate offset in this block and the interupt vector is restored.
When the program installed itself it freed up its environment pointer
(using the dealloc dos call), so deallocing the main block of the
installed program now removes it completely. Memory segmentation can
still be a problem, so I usually remove my installed goodies in the
reverse order that I installed them. This isn't important unless there
is something installed that takes up a lot of memory (such as an
installable ramdisk). By the way, the extra code for doing the removal
is at the end of the program and is cut off by the terminate-and-stay-
resident dos call so it doesn't use up memory when installed.
Also, before removing the installed version, various offsets in the
suposed installed version are checked to make sure the interupt vector
is really pointing to an installed version.
- John N. White    {duke, mcnc}!jnw