• Please review our updated Terms and Rules here

Properly forwarding to an old int handler in Turbo C++

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
I'm working on a TSR project in Turbo C++ that involves hooking int 13h. I moved the old int handler to int FDh. There are several functions I intercept, but the rest get passed through to the old handler. Every program I've tried works so far, except for DEFRAG.EXE. It hangs at the drive selection screen without displaying the C: drive in the list. The last call to int 13h from it happens right before the hang, it's function 8 (get drive parameters). This is one of the functions I'm forwarding to the old handler. Here's my function passthrough code:

Code:
		default:
			{
				union REGS inregs, outregs;
				struct SREGS sregs;
				inregs.h.ah = ah;
				inregs.h.al = al;
				inregs.h.bh = bh;
				inregs.h.bl = bl;
				inregs.h.ch = ch;
				inregs.h.cl = cl;
				inregs.h.dh = dh;
				inregs.h.dl = dl;
				inregs.x.si = si;
				inregs.x.di = di;
				sregs.es = es;
				inregs.x.flags = flags;
				int86x(0xFD, &inregs, &outregs, &sregs);
				ah = outregs.h.ah;
				al = outregs.h.al;
				bh = outregs.h.bh;
				bl = outregs.h.bl;
				ch = outregs.h.ch;
				cl = outregs.h.cl;
				dh = outregs.h.dh;
				dl = outregs.h.dl;
				flags = outregs.x.flags;
				es = sregs.es;
				si = outregs.x.si;
				di = outregs.x.di;
			}
			break;

I have custom function exit code to prevent Turbo C++ from restoring the original entry regs when it's done, since I need to modify them and pass them back to the calling application. That code seems to work with everything else, so I don't suspect an issue here:

Code:
	asm {
		mov ax, flags
		mov [bp+22], ax
	}
	_ES = es; _SI = si; _DI = di;
	_AH = ah; _AL = al; _BH = bh; _BL = bl; _CH = ch; _CL = cl; _DH = dh; _DL = dl;
	asm {
		mov     sp,bp
		add		sp,18
		iret
	}

Any ideas what I'm doing wrong that could cause defrag to hang on function 8?
 
Have you tried stepping through your interrupt handler in a debugger like Bochs (using the xchg bx,bx breakpoint trick)? My guess is that some register is being corrupted before or after the BIOS Int 13h call.

EDIT: I just realized that this might be hard to do in C since ideally you would want the xchg bx,bx to be the very first instruction in your handler.
 
Have you tried stepping through your interrupt handler in a debugger like Bochs (using the xchg bx,bx breakpoint trick)? My guess is that some register is being corrupted before or after the BIOS Int 13h call.

EDIT: I just realized that this might be hard to do in C since ideally you would want the xchg bx,bx to be the very first instruction in your handler.

Hey Krille. No, I will give that a shot. I can use tcc -S to generate asm files, then stick in that line where the handler starts, assemble and link. I wasn't aware of that Bochs feature!
 
I can use tcc -S to generate asm files
I didn't think of this but that's even better. You can just read the code to see what it really looks like. :)
I wasn't aware of that Bochs feature!
Yeah, it's a really great feature. I use it for debugging BIOS code. The only problem is that you must add 'magic_break: enabled=1' to the bochsrc.bxrc file and then avoid using the GUI to configure it because it will just be removed again when you save. Then right click and select Debugger.
 
Last edited:
Hey there-

I didn't actually take your code and try it, but it looks to me as though you are calling the alternative interrupt (FD) from within the existing INT 0x13... This is not the way to go.

Instead, you want to preserve the original location that the offset executes at from the IVT and then jump to that code, letting it handle the IRET and everything else. By triggering a second interrupt you are definitely complicating the stack frame. It's possible that (for some reason) that particular function is attempting to look higher up in the stack for something.. Perhaps a memory pointer for a data structure? I don't remember any of the details of that call.
 
Hey there-

I didn't actually take your code and try it, but it looks to me as though you are calling the alternative interrupt (FD) from within the existing INT 0x13... This is not the way to go.

Instead, you want to preserve the original location that the offset executes at from the IVT and then jump to that code, letting it handle the IRET and everything else. By triggering a second interrupt you are definitely complicating the stack frame. It's possible that (for some reason) that particular function is attempting to look higher up in the stack for something.. Perhaps a memory pointer for a data structure? I don't remember any of the details of that call.

I've actually tried that as well. That was my first method of attempting this actually, since it seemed saner. Result was the same. I went to this more complicated method to see if it made a difference.

EDIT: I just fixed it. Using that method alone wasn't enough, I had to put a return immediately after it so that it wasn't still running my code to replace all the return regs on the way out! That should have been obvious to me, heh. I'm out of practice! Haven't done any low-level DOS coding in ages. Thanks guys.

For the record, I'm writing a disk caching utility. It keeps multiple (configurable) caches of different parts of the disk instead of just one. If several different locations are being hit frequently, they can all remain cached. It's working pretty well! About to run a full defrag on a disk with it, if that doesn't mess anything up on the drive I'd say it's good enough to release a beta of. (After I add one more handy feature...)
 
Last edited:
Back
Top