[comp.sys.ibm.pc] problems trying to intercept msdos function requests

levy@ttrdc.UUCP (Daniel R. Levy) (02/14/89)

Hello again, and thanks to all the folks who replied to my earlier request
for info about talking PC software.

With just enough understanding of MS-DOS to be dangerous, I am now trying to
do something screwey, that is, intercept calls to the MS-DOS function
requests (that are made through interrupt 21h).  This is so that I can do
something even screwier (that is, to make a UNIX-structured floppy look to
programs running on the PC like a MS-DOS file system, as much as is possible
given the braindamage of the MS-DOS file system).  This is a research project
I've committed to for a class I am taking at Northwestern, so I can't back
out of it.

My problem is that I can't even seem to make a do-nothing intercept program do
what I want.  My code gets the interrupt vector for 21h, copies it to an
unused interrupt vector, replaces the interrupt vector at 21h with
a pointer to my intercept routine, then terminates while staying resident
(the interrupt for this final request being done through the formerly unused
vector).  Future interrupts to 21h should, I figure, call my routine.
I tried a do-nothing routine which just interrupts to the vector to which
I had copied the old vector at 21h, and then performs an iret.  This works
a little, but flakily.  DIR works okay after this, and I can execute some
programs in the current directory, but when I try to run a program where MS-DOS
must search PATH, the machine goes into an infinite loop and it's reboot time.
(This is on an AT&T PC6300.)

Could some MS-DOS guru please look at the assembly code below and tell me
what I'm missing?  It _must_ be something awfully simple, I just don't know
what it is :-).  Thanks much in advance!

(Yes, I have verified that 88h is an unused interrupt vector [contains
0000:0000], at least at the time I run this program.)

	.8087

CODE	segment
	assume	cs:CODE

; get the interrupt vector currently at 21h

START:	mov	al,21h
	mov	ah,35h
	int	21h

; at this point, ES contains the segment and BX contains the offset
; of the interrupt vector currently at 21h

; set the interrupt vector at 88h to be the same as the one at 21h

	mov	ax,es
	mov	ds,ax
	mov	ax,bx
	mov	dx,ax
	mov	al,88h
	mov	ah,25h
	int	21h

; Now (here's the trick) set the interrupt vector at 21h to be CATCH, below

	mov	ax,seg CATCH
	mov	ds,ax
	mov	ax,offset CATCH
	mov	dx,ax
	mov	al,21h
	mov	ah,25h
	int	21h	; note we must hereafter use 88h for subsequent
			; system calls that we don't want to be caught

; terminate this process but keep it

	mov	ax,128	; keep this many paragraphs
	mov	dx,ax
	mov	al,0	; exit code 0
	mov	ah,31h
	int	88h	; don't catch THIS call

; this is the system call intercept code

CATCH:

; make the real system call

	int	88h
	iret

CODE	ends

STACK	segment stack
	assume	ss:STACK
	dw	64 dup(?)
STACK	ends

	end	START
-- 
Daniel R. Levy             UNIX(R) mail:  att!ttbcad!levy
AT&T Bell Laboratories
5555 West Touhy Avenue     Any opinions expressed in the message above are
Skokie, Illinois  60077    mine, and not necessarily AT&T's.

vg55611@ihuxy.ATT.COM (Gopal) (02/15/89)

In article <3204@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
{stuff deleted]
>My problem is that I can't even seem to make a do-nothing intercept program do
>what I want.  My code gets the interrupt vector for 21h, copies it to an
>unused interrupt vector, replaces the interrupt vector at 21h with
>a pointer to my intercept routine, then terminates while staying resident
>(the interrupt for this final request being done through the formerly unused
>vector).  Future interrupts to 21h should, I figure, call my routine.
>I tried a do-nothing routine which just interrupts to the vector to which
>I had copied the old vector at 21h, and then performs an iret.  This works
>a little, but flakily.  DIR works okay after this, and I can execute some
>programs in the current directory, but when I try to run a program where MS-DOS
>must search PATH, the machine goes into an infinite loop and it's reboot time.
>(This is on an AT&T PC6300.)
>
>Could some MS-DOS guru please look at the assembly code below and tell me
>what I'm missing?  It _must_ be something awfully simple, I just don't know
>what it is :-).  Thanks much in advance!

{Code below deleted}

I think the main problem lies in the fact when an application calls int 21h,
it doesn't always return through an "iret" instruction.  This is so that
the flags can be modified (an "iret" will restore the flags).  Your
int 21h routine will call int 88h, but will not return the flags set to the
calling program.

Also note:  Int 21h calls itself..  there may lie the next problem you
run into.

Venu P. Gopal
UUCP:	att!ihuxy!vg55611
Internet: vg55611@ihuxy.att.com
BITNET: com%"vg55611@ihuxy.att.com"   or   com%"vg55611%ihuxy@research.att.com"
Save 500 million keystrokes a day; silence those silent letters forever.

jborza%burgundy@Sun.COM (Jim_Borza) (02/16/89)

In article <3204@ttrdc.UUCP>, levy@ttrdc.UUCP (Daniel R. Levy) writes:
> Hello again, and thanks to all the folks who replied to my earlier request
> for info about talking PC software.
> 
> With just enough understanding of MS-DOS to be dangerous, I am now trying to
> do something screwey, that is, intercept calls to the MS-DOS function
> requests (that are made through interrupt 21h).  This is so that I can do
> something even screwier (that is, to make a UNIX-structured floppy look to
> programs running on the PC like a MS-DOS file system, as much as is possible
> given the braindamage of the MS-DOS file system).  This is a research project
> I've committed to for a class I am taking at Northwestern, so I can't back
> out of it.
> 
> My problem is that I can't even seem to make a do-nothing intercept program do
> what I want. [...]
> 
> CATCH:
> 
> ; make the real system call
> 
> 	int	88h
> 	iret
> 
> CODE	ends
> 
> STACK	segment stack
> 	assume	ss:STACK
> 	dw	64 dup(?)
> STACK	ends
> 
> 	end	START
> -- 
> Daniel R. Levy   

Mr. Gopal (an earlier respondent) was correct in looking at the FLAGS
register as a potential source of your problem.  DOS returns significant
information in the FLAGS register.  The problem occurs because an int xx
instruction pushes the FLAGS register on the stack and then pushes the
seg:offset.  When the DOS call returns from its interrupt, your CATCH
routine overwrites the FLAGS register, restoring it to the value it
had prior to the int 21h call.  You will need to "capture" the value
returned in the FLAGS register before issuing your iret at the end of
the CATCH procedure.  The value you pushed for FLAGS will, at the con-
clusion of the int 88h, be at sp-6; the value returned by DOS will be in
FLAGS.

One way around this may be to manipulate the registers so that the FLAGS
returned by DOS is on the stack at the right place (sp-6) or another way
might be to code CATCH so it doesn't monkey with FLAGS on its return. An
example:

CATCH	proc	FAR
	int	88h
	ret	2
CATCH	endp

This should return to the point of interrupt with a FAR return rather
than an iret.  The only difference is the FLAGS register.  The value
of 2 in the ret instruction tells the 8086 to bump the stack pointer
by 2 in order to ignore the FLAGS word you pushed initially.  Of course,
since this is a "do nothing" routine, it's simple.  God help us all if
you really want to "do something"!  :-o <-- (Mr. Bill)

I think the iret from DOS will re-enable interrupts but you might want
to code an "sti" following the int 88h for safety.

I haven't tried this but I think it's a good place to start.



Jim Borza - Sun Microsystems
Disclaimer?  Sure, why not?

zu@ethz.UUCP (Urs Zurbuchen) (02/20/89)

In article <3204@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
>(Yes, I have verified that 88h is an unused interrupt vector [contains
>0000:0000], at least at the time I run this program.)
Verifying is one thing, being sure another :-)
Why do you use an interrupt vector to store the old vector, anyway. Just
get the old vector from DOS (AH=35h, AL=number, INT 21h) save it
somewhere in your program's memory space. Then set your entry point via
DOS (AH=25h,AL=number,INT 21h). You will then hopefully get called :-)

To chain to the original interrupt handler issue a far JMP (or CALL, but
I'd prefer JMP) indirect via the vector you stored in your program's
work space.

This way the original vector you saved doesn't get mungled up by some
other program (BASIC is a likely candidate for that).

Also, as others already pointed out, have a look at the FLAGS register
if you're trying to substitute MS-DOS functions.

		...urs

UUCP: ...!mcvax!cernvax!ethz!zu

lth@uoregon.uoregon.edu (Lars Thomas Hansen) (02/23/89)

In article <788@ethz.UUCP> zu@bernina.UUCP (Urs Zurbuchen) writes:
>Why do you use an interrupt vector to store the old vector, anyway. Just
>get the old vector from DOS (AH=35h, AL=number, INT 21h) save it
>somewhere in your program's memory space. Then set your entry point via
>DOS (AH=25h,AL=number,INT 21h). You will then hopefully get called :-)
>
>To chain to the original interrupt handler issue a far JMP (or CALL, but
>I'd prefer JMP) indirect via the vector you stored in your program's
>work space.

Have you considered that the DOS routine called via the FAR JMP/CALL will
issue an IRET (which pops three words off the stack; FLAGS, IP and CS) and
not a RET (which pops only IP and CS)?

I think this is a sticky issue. The scheme of putting the original interrupt
vector somewhere and doing a software interrupt to get at it might actually
be safer.


--lars

---------------------------------------------------------------------------
"Even if you win the rat race, you're still a rat"
---------------------------------------------------------------------------