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" ---------------------------------------------------------------------------