TOMIII@MTUS5.BITNET (Thomas Dwyer III) (12/18/90)
Hi there. Would some kind soul please tell me why my machine hangs when I run this TSR? What am I doing wrong? ------ Code Begins ------ INT_NUM equ 9h code segment org 0100h assume cs:code,ds:code,es:code start: mov ah,35h ; Get int vector mov al,INT_NUM int 21h mov word ptr [old_int+2],es ; Save old vector mov word ptr [old_int],bx mov ah,25h ; Set int vector mov al,INT_NUM mov dx,offset new_int int 21h mov dx,50h mov ax,3100h int 21h new_int proc far jmp short go old_int dd ? go: jmp [old_int] ; Jump to old int routine new_int endp code ends end start ----- Code Ends ------ Thank you, Thomas Dwyer III Email: tomiii@mtu.edu Network Programmer tomiii@mtus5.BITNET Computing Technology Services Voice: (906) 487-2110 Michigan Technological University Fax: (906) 487-2787
ekalenda@cup.portal.com (Edward John Kalenda) (12/18/90)
Thomas Dwyer write: > Hi there. Would some kind soul please tell me why my machine hangs when > I run this TSR? What am I doing wrong? The first problem that comes to mind is that your interrupt handling routine is doing a jump to a location pointed to by an area in your data segment. You should use JMP cs:[oldint] since the data segment at the time the interrupt occurs will be that of the program running, not your TSR. You're probobly jumping off into space somewhere based on the value of ds:[oldint] in the current program's frame of reference. Ed ekalenda@cup.portal.com
brandis@inf.ethz.ch (Marc Brandis) (12/18/90)
In article <90351.150210TOMIII@MTUS5.BITNET> TOMIII@MTUS5.BITNET (Thomas Dwyer III) writes: >Hi there. Would some kind soul please tell me why my machine hangs when >I run this TSR? What am I doing wrong? [some stuff deleted] > assume cs:code,ds:code,es:code .... > mov word ptr [old_int+2],es ; Save old vector > mov word ptr [old_int],bx Here, there is a rather unsafe assumption that ds points to the code segment after DOS has been called. You should better set ds explicitly to code (e.g. by push cs, pop ds) or use an segment prefix for cs. However, it is correct in this place that ds points to code, it is just unsafe. > mov ah,25h ; Set int vector > mov al,INT_NUM > mov dx,offset new_int Once again, it would be better to set ds explicitly to the code segment. .... >old_int dd ? > jmp [old_int] ; Jump to old int routine Here lies the real problem. As this code is called inside an interrupt, the assumption that ds points to code is wrong (!). You can either add a correct assume statement in front of this code, which would be assume cs:code, ds:nothing, es:nothing, ss:nothing or you can make it explicit that you want a segment prefix for this instruction and that you want a far call, which is actually what I would suggest. It is much better to make it explicit what is going on than to rely on the context given by the assume statements. So try the following statement (the ultra safe version) jmp dword ptr cs:[old_int] This should do what you want. Marc-Michael Brandis Computer Systems Laboratory, ETH-Zentrum (Swiss Federal Institute of Technology) CH-8092 Zurich, Switzerland email: brandis@inf.ethz.ch
schmidt@mars.jpl.nasa.gov (Kevin Schmidt) (12/19/90)
In article <90351.150210TOMIII@MTUS5.BITNET> TOMIII@MTUS5.BITNET (Thomas Dwyer III) writes: >Hi there. Would some kind soul please tell me why my machine hangs when >I run this TSR? What am I doing wrong? > >------ Code Deleted ------ > Code that was here got INT 9 vector and put it in old_int. It then set the INT 9 vector to point to new_int. > >new_int proc far > jmp short go > >old_int dd ? > >go: > jmp [old_int] ; Jump to old int routine >new_int endp > >----- Code Ends ------ > Everything looks fine except that the last jump (jmp [old_int]) has two problems. First the jump must include a segment override so that the data segment (ds) is not used in calculating the address of old_int. Second you must insure that it is a far jump. Thus the line should read: jmp far cs:[old_int] If you still can't get it to work, email me and I will send you a sample of how to attach to INT 9. _______________________________________________________________________________ _ ____ _ | | / / / _ \ / / | Kevin T. Schmidt | schmidt@mars.jpl.nasa.gov / / / /_/ / / / | Jet Propulsion Laboratory | schmidt@jems.jpl.nasa.gov _ / / / ____/ / / | 4800 Oak Grove Dr. | / /_/ / / / / /___ | M/S 301-355 | \____/ /_/ /______/ | Pasadena, CA 91109 |
valley@uchicago (Doug Dougherty) (12/19/90)
brandis@inf.ethz.ch (Marc Brandis) writes: >In article <90351.150210TOMIII@MTUS5.BITNET> TOMIII@MTUS5.BITNET (Thomas Dwyer III) writes: >>Hi there. Would some kind soul please tell me why my machine hangs when >>I run this TSR? What am I doing wrong? >[some stuff deleted] >> assume cs:code,ds:code,es:code >.... >> mov word ptr [old_int+2],es ; Save old vector >> mov word ptr [old_int],bx >Here, there is a rather unsafe assumption that ds points to the code segment >after DOS has been called. You should better set ds explicitly to code (e.g. >by push cs, pop ds) or use an segment prefix for cs. However, it is correct >in this place that ds points to code, it is just unsafe. Oh, come on. You can surely assume two things: 1) DS = CS on entry to a COM program 2) No DOS call is gonna change DS (unless explicitly stated in the documentation; I can't imagine that any do as of this writing) Yes, it is a good idea to be a little paranoid (maybe a lot paranoid) when doing assembly language programming, but you are taking it too far. But then again, you probably code in MASM or TASM or something like that, so it figures you'd be a little paranoid about segment registers...
stever@Octopus.COM (Steve Resnick ) (12/19/90)
In article <90351.150210TOMIII@MTUS5.BITNET> TOMIII@MTUS5.BITNET (Thomas Dwyer III) writes: >Hi there. Would some kind soul please tell me why my machine hangs when >I run this TSR? What am I doing wrong? > >------ Code Begins ------ > >INT_NUM equ 9h > >code segment > org 0100h > assume cs:code,ds:code,es:code [Init Code Deleted] >new_int proc far > jmp short go > >old_int dd ? > >go: > jmp [old_int] ; Jump to old int routine I'm not sure, but I think that this is DS relative. In other words, when your ISR is called, DS may be pointing elsewhere. >new_int endp > > >code ends > end start > >----- Code Ends ------ A much better (IMHO) way to do this, is to borrow the interrupt from the system, call the original ISR, do your own dirty work, and return. The way I do this in a couple programs is to save the old ISR address in the same way you have, but call it differently. new_int proc far jmp short go old_int dd ? go: pushf ; Pushing the flags before a FAR call simulates ; an INT instruction. The ISR being called will ; then IRET to here. call DWORD PTR cs:[old_isr] . . ; Do something usefull here. . IRET new_int endp This gives you the flexibility of handling the original ISR, as well as your own code. Hope this helps.... Steve -- ---------------------------------------------------------------------------- steve.resnick@f105.n143.z1.FIDONET.ORG - or - apple!camphq!105!steve.resnick Flames, grammar errors, spelling errrors >/dev/nul The Asylum OS/2 BBS - (408)263-8017 IFNA 1:143/105.0
lbr@holos0.uucp (Len Reed) (12/20/90)
In article <37017@cup.portal.com> ekalenda@cup.portal.com (Edward John Kalenda) writes: >Thomas Dwyer write: => Hi there. Would some kind soul please tell me why my machine hangs when => I run this TSR? What am I doing wrong? = =The first problem that comes to mind is that your interrupt handling =routine is doing a jump to a location pointed to by an area in your =data segment. You should use JMP cs:[oldint] since the data segment =at the time the interrupt occurs will be that of the program running, =not your TSR. You're probobly jumping off into space somewhere based on =the value of ds:[oldint] in the current program's frame of reference. This analysis is correct but the solution is a little dangerous. I say this because I assume you're going to add code rather than leave your do-nothing skeleton in place. :-) Rather than putting the explicit "cs:" prefix in you should ensure that the in-effect "assumes" always match what's in the segment registers. Having done a lot of driver and TSR programming I can assure you that using explicit prefix overrides to save coding an "assume" will eventually lead to problems. Explicitly marking your assumes informs the assembler *and* the next programmer what you thought was in the segment registers. In your case, before the interrupt handler you should say: assume cs:code, ds:nothing, es:nothing, ss:nothing The assembler will then add the segment prefix for you. If it's not addressable you should get an assembly-time error. BTW, why do you embed your pointer to the saved handler inside your procedure? Just say ; [first part omitted here] mov ax,3100h ; terminate and stay resident int 21h ;NOT REACHED even ; word-align the data for efficiency old_int dd ? assume cs:code, ds:nothing, es:nothing, ss:nothing new_int proc far jmp [old_int] new_int endp -- Len Reed Holos Software, Inc. Voice: (404) 496-1358 UUCP: ...!gatech!holos0!lbr
stever@Octopus.COM (Steve Resnick ) (12/20/90)
In article <valley.661550344@gsbsun> valley@uchicago (Doug Dougherty) writes: >brandis@inf.ethz.ch (Marc Brandis) writes: > >>In article <90351.150210TOMIII@MTUS5.BITNET> TOMIII@MTUS5.BITNET (Thomas Dwyer III) writes: >>>Hi there. Would some kind soul please tell me why my machine hangs when >>>I run this TSR? What am I doing wrong? > >>[some stuff deleted] >>> assume cs:code,ds:code,es:code >>.... >>> mov word ptr [old_int+2],es ; Save old vector >>> mov word ptr [old_int],bx > >>Here, there is a rather unsafe assumption that ds points to the code segment >>after DOS has been called. You should better set ds explicitly to code (e.g. >>by push cs, pop ds) or use an segment prefix for cs. However, it is correct >>in this place that ds points to code, it is just unsafe. > >Oh, come on. You can surely assume two things: > > 1) DS = CS on entry to a COM program > 2) No DOS call is gonna change DS (unless explicitly stated in > the documentation; I can't imagine that any do as of this > writing) > >Yes, it is a good idea to be a little paranoid (maybe a lot paranoid) >when doing assembly language programming, but you are taking it too far. > >But then again, you probably code in MASM or TASM or something like >that, so it figures you'd be a little paranoid about segment registers... Oh come on. I can surely assume one of two things: 1) You do not understand interrupts. 2) You didn't read what the message said. This code is for an interrupt handler. In an interrupt handler the ONLY segment address that is known upon entry is the CS register. Sorry for the flame, but, please read the posters question(s) before responding to them incorrectly. Steve -- ---------------------------------------------------------------------------- steve.resnick@f105.n143.z1.FIDONET.ORG - or - apple!camphq!105!steve.resnick Flames, grammar errors, spelling errrors >/dev/nul The Asylum OS/2 BBS - (408)263-8017 IFNA 1:143/105.0
lbr@holos0.uucp (Len Reed) (12/20/90)
In article <18633@neptune.inf.ethz.ch> brandis@inf.ethz.ch (Marc Brandis) writes: >In article <90351.150210TOMIII@MTUS5.BITNET> TOMIII@MTUS5.BITNET (Thomas Dwyer III) writes: >>Hi there. Would some kind soul please tell me why my machine hangs when >>I run this TSR? What am I doing wrong? > >[some stuff deleted] >> assume cs:code,ds:code,es:code >.... >> mov word ptr [old_int+2],es ; Save old vector >> mov word ptr [old_int],bx > >Here, there is a rather unsafe assumption that ds points to the code segment >after DOS has been called. You should better set ds explicitly to code (e.g. >by push cs, pop ds) or use an segment prefix for cs. >in this place that ds points to code, it is just unsafe. Nonsense. What's unsafe about this? This is obviously a ".com" TSR: COMs start with CS=DS=ES=SS. The assume notes this (although SS is not listed), and the DOS calls used preserve the DS register, so the DS register does in fact point to the code. Why use overrides or pushes and pops when the DS: points where you want it to? (And if it doesn't point where you want it to then the assumes should tell the assembler this. This is where the bug lies.) There's no problem, potential or otherwise, here. >.... >>old_int dd ? >> jmp [old_int] ; Jump to old int routine > >Here lies the real problem. As this code is called inside an interrupt, the >assumption that ds points to code is wrong (!). You can either add a correct >assume statement in front of this code, which would be > > assume cs:code, ds:nothing, es:nothing, ss:nothing > >or you can make it explicit that you want a segment prefix for this instruction >and that you want a far call, which is actually what I would suggest. It is >much better to make it explicit what is going on than to rely on the context >given by the assume statements. So try the following statement (the ultra safe >version) > > jmp dword ptr cs:[old_int] Well, maybe explicit is better, but if you're really trying to code something well your assumes should be correct. Put the assume statement in. What I'm saying is that it's fine to give the assembler more information than it needs, but you shouldn't give it wrong information (i.e., not changing the assume) and then override that wrong information with a segment prefix. Eventually this code will get expanded to do something useful. Having the assumes wrong is a recipe for future bugs and is confusing to anyone who might later read this code. I assume that your explicit adding of "dword ptr" in the above jump is intended to document that this is a far jump. (The assembler knows that old_int is a doubleword so "dword ptr" is unecessary.) Some assembler won't take the format you used; you have to say jmp cs: dword ptr [old_int] -- Len Reed Holos Software, Inc. Voice: (404) 496-1358 UUCP: ...!gatech!holos0!lbr
lbr@holos0.uucp (Len Reed) (12/20/90)
In article <1990Dec18.163810.21268@jato.jpl.nasa.gov> schmidt@mars.UUCP (Kevin Schmidt) writes: >Everything looks fine except that the last jump (jmp [old_int]) has two >problems. First the jump must include a segment override so that the >data segment (ds) is not used in calculating the address of old_int. >Second you must insure that it is a far jump. Thus the line should read: > > jmp far cs:[old_int] Elsewhere I've noted that you should change the assumes. Overriding the segment is fine, too, if you wish. You don't need to tell the assembler that this is a far jump, though, since it knows this because old_int is doubleword. If you wish to make everything explicit, though, the above form is incorrect. Try jmp cs:dword ptr [old_int] ; far jump indirect to saved handler -- Len Reed Holos Software, Inc. Voice: (404) 496-1358 UUCP: ...!gatech!holos0!lbr
valley@uchicago (Doug Dougherty) (12/20/90)
stever@Octopus.COM (Steve Resnick ) writes: >>>[some stuff deleted] >>>> mov word ptr [old_int+2],es ; Save old vector >>>> mov word ptr [old_int],bx >> >>>Here, there is a rather unsafe assumption that ds points to the code segment >>>after DOS has been called. You should better set ds explicitly to code (e.g. >>>by push cs, pop ds) or use an segment prefix for cs. However, it is correct >>>in this place that ds points to code, it is just unsafe. >> >>Oh, come on. You can surely assume two things: >> >> 1) DS = CS on entry to a COM program >> 2) No DOS call is gonna change DS (unless explicitly stated in >> the documentation; I can't imagine that any do as of this >> writing) >Oh come on. I can surely assume one of two things: > 1) You do not understand interrupts. (I do too) > 2) You didn't read what the message said. (I did too)( >This code is for an interrupt handler. In an interrupt handler the ONLY >segment address that is known upon entry is the CS register. >Sorry for the flame, but, please read the posters question(s) before >responding to them incorrectly. >Steve Yes, this is turning into a flame war and should probably be moved to talk.msdos (or some such) Nevertheless, I am well aware of the need for a CS: override in the interrupt handler itself (unless & until you set DS = CS) I have written several TSRs and several device drivers, so I ain't no newbie. However, you seemed to be saying that you thought it was a good idea to (repetitively) set DS to CS *IN THE MAIN "BOOSTER"* (i.e., non-resident) part of the program. In fact, the two lines of code quoted above follow immediately a INT 21, fn 35 call, which sets ES:BX equal to the current interrupt value. Surely that call is going to leave DS alone. (It would be unwise [because of re-entrancy considerations], not to mention pointless, to call INT 21, fn 35 inside the resident part of the TSR) Gottit? Good.
brandis@inf.ethz.ch (Marc Brandis) (12/20/90)
In article <1990Dec19.174402.5882@holos0.uucp> lbr@holos0.uucp (Len Reed) writes: >In article <18633@neptune.inf.ethz.ch> brandis@inf.ethz.ch (Marc Brandis) writes: >>[some stuff deleted] >>> assume cs:code,ds:code,es:code >>.... >>> mov word ptr [old_int+2],es ; Save old vector >>> mov word ptr [old_int],bx >> >>Here, there is a rather unsafe assumption that ds points to the code segment >>after DOS has been called. You should better set ds explicitly to code (e.g. >>by push cs, pop ds) or use an segment prefix for cs. >>in this place that ds points to code, it is just unsafe. > >Nonsense. What's unsafe about this? This is obviously a ".com" TSR: COMs >start with CS=DS=ES=SS. The assume notes this (although SS is not >listed), and the DOS calls used preserve the DS register, so the DS >register does in fact point to the code. > >Why use overrides or pushes and pops when the DS: points where you want >it to? (And if it doesn't point where you want it to then the assumes >should tell the assembler this. This is where the bug lies.) It looks like my posting is starting a flame war, which the topic is definitely not worth. Still I want to add a comment. Unless you had deleted it up there, you would see that I said that DS points to the right segment there. I certainly know this, and I would not add the code to set it explicitly to the code segment. However, from the listing given, I assumed that the original poster was not experienced in assembly language, so I wanted to show him a piece of code that works under all circumstances. Although there is no DOS call that changes DS, there are some BIOS calls that do. If you do not have good documentation about it (and lots of people do just a little bit of assembly programming without any documentation but instead copying from other's sources), it is best to make the least assumptions that you can and establish everything else that you need explicitly. Note that in this case it would not even have costed at lot, as this code is just running once. I am not (!) trying to make people add inefficiences to their programs. It is just that when you are not completely sure that some improved solution works, you should do it the safe way. Marc-Michael Brandis Computer Systems Laboratory, ETH-Zentrum (Swiss Federal Institute of Technology) CH-8092 Zurich, Switzerland email: brandis@inf.ethz.ch