Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 209
  • 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

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

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