• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 214
  • Last Modified:

Problem with capturing int 21h

I'd like to change a function of int 21h to my own. So I made up something like:

PROGRAM Foo

VAR
{$F+}
  OldInt21 : Procedure;
{$F-}
  InDOS : ^Byte;
  Regs  : Registers;
  {some more variables}

{$F+}
PROCEDURE NewInt21 (Flags, CS, IP, ... : Word); INTERRUPT;
BEGIN
  Inc (InDOS^);
  {some more code}
  OldInt21;
  {code}
  Dec (InDOS^};
END;
{$F-}

BEGIN
  Regs.AH = $34; {the function to get the InDOS address}
  Intr ($21, Regs);
  InDOS := Ptr (Regs.ES, Regs.BX);
  GetIntVec ($21, @OldInt21);
  SetIntVec ($21, @NewInt21};
  {code}
  Keep (0);
END.

On one PC this results in an endless loop (calling OldInt21
results in calling NewInt21 for some reason), another PC
just hangs. Can someone please tell me what I am doing wrong?

Thanks,
  Jaap.
0
jpboender
Asked:
jpboender
  • 2
1 Solution
 
vikiingCommented:
Int 21 is DOS master interrupt, this is, there are TONS of things (by DOS itself and by your application) that are done thru it.

The point here is when you receive an Int 21 call that must be handled by the original code, you must branch execution to original code in order the true DOS-Int 21 works.

Failing to do that may hang the machine, or give you any other bizarre behavior.
0
 
jpboenderAuthor Commented:
Okay, but isn't that what I'm doing? I mean, I do call the
old interrupt function.
0
 
vikiingCommented:
Sorry, I didn't see that.

One main problem is that OldInt21 returns with IRET, not with RET

As you're calling OldInt21 as a simple procedure, it's suposed it will come back with a RET instruction, not an IRET.

Thus, when OldInt21 reaches end and does an IRET, control will NOT return to the point where you called from, but it'll make a whole mess.
0
 
rbrCommented:
The problem is that oldInt21 is defined as a procedure, so the register and the return adress will be stored at the stack. But as vikiing mentioned an interrupt uses IRET which need some different stack info than a normal procedure. In C it's no problem to call a
JMP FAR oldInt21 which will not alter the stack and the old Interrupt will end correctly. You have to to the same maybe with an inline assembler code. But you can't use code after the OldInt21 becuase an Interrupt will not jump back. You have to use a branch for your new function and make a jump far to your old interrupt for your old functions.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now