I am attempting to hook and chain an interrupt. I have written code which sets up timer2 so that int 19 will be called every 10ms. Now I need to hook this int 19 call to another subroutine, so the subroutine will excecute every 10ms. In order to do this, I know I have to save the current interrupt vector, hook the vector to point to the new subroutine, then chain it back to point to where it pointed originally. My question is, how do I know what the new CP:IP value will be so that I can move it into the int vector?

something along the lines of:

CALL <subroutine that initialized int 19 to be called every 10 mseconds>
CLI ;so I have time to change segment and offset before interrupt kicks in
push es
mov ax,0
mov es,ax
mov ax,es:[4*19]
mov oldIP,ax ;save old IP for int 19
mov ax,es:[4*19+2]
mov oldCS,ax ;save old CS for int 19
hook interrupt here ; point int vector to new subroutine
pop es

using NASM as my assembler and this is to run on an old 8086
thanks.
Posted on 2004-06-12 19:01:20 by illz
wait a minute, if you want to call the old routine already installed, you should just get its address push the flags (I believe) and do a call to the address. This is how I did it in my DOS timer routine for my DOS game so that I dont have to mess up my time. I'm not sure I understand what you want, but I'll clear this up, do the following:

-Read the old int 19 handler and save the segment and offset of the handler (in a variable)
-Put in the segment and offset of your handler in the int 19 area
-In your int 19 handler have code call the OLD handler, by pushing the flags (double check what the x86 does in respond to an interrupt) and invoking a FAR call to the old address.
Posted on 2004-06-12 20:23:38 by x86asm
I guess my question is, how do I know what the handler of the new code is. I assume it will be loaded into the code segment, so could I just say:

extern _newcode
.
.
.
es mov word [4*19], _newcode

after setting es = 0

or if I have the new code as
newcode:
blah
blah

could I just do
mov word ax, offset newcode
es mov [4*19],ax
mov ax,cs
es mov [4*19+2],ax
Posted on 2004-06-12 20:54:14 by illz
hi illz,

mov word ax, offset newcode
es mov [4*19],ax
mov ax,cs
es mov [4*19+2],ax

Yes, this should work. and it can be simplified by:

es mov [4*19],offset newcode
es mov [4*19+2],cs

BTW: int 19 = int 13h, that is the interrupt for disk access. So be careful.

Japheth
Posted on 2004-06-13 04:53:00 by japheth
Well, that's on the PC, this certainly doesn't sound like it's for the PC.

Illz: You should hook the interrupt before you set up the timer.

This code should do it, if oldIP is accessible from ES and you aren't using SI and DI.


push es
push ds
xor cx,cx
mov ds,cx
mov si,0x5c
push si
mov di,oldIP wrt (Name of segment that ES points to)
movsw
movsw
pop di
mov es,cx
mov ax,_newcode
stosw
mov [di],cs
pop ds
pop es
call (subroutine to set up timer)

If that's not the case, this would be the shortest I think:


push es
xor ax,ax
mov es,ax
mov ax,_newcode
xchg ax,es:[0x5c]
mov [oldIP],ax
mov ax,cs
xchg ax,es:[0x5e]
mov [oldCS],ax
pop es
call (subroutine to set up timer)

You should know which segment the code is in by which section in the ASM file you have defined it in. If it's not in the same section as the setup code, then use SEG _newcode for the segment (assuming there is provision for it in the executable format)

Then just end your interrupt code with JMP FAR cs: or if the instruction is in a range accessible from ES or DS, use opcode 0xea and patch the address in the setup code.
Posted on 2004-06-13 15:45:08 by Sephiroth3