Replacing an Interrupt

I want to write a program that replace int8 and int 10h
i know the basis of doing such job but the problem is the program
will hang whenever i try a

simple program like this ( so i don' know :D ):
.MODEL SMALL
.CODE
ORG 100H
BEGIN: JMP SHORT MAIN
Message db 'Hi$'
oldint8 dd ?
MAIN PROC NEAR
; get address of int8
mov ah, 35h
mov al, 8
int 21h
; save address of int8
mov word ptr oldint8, bx
; set the new address
mov ah, 25h
mov al, 8
mov dx,Offset newint8
int 21h

int 8

.exit
MAIN ENDP
newInt8 Proc Near
pushf
cli
call CS:oldint8 ;Call prior handler.

call print
iret
newInt8 endp
Print Proc Near
lea dx, message
mov ah, 09h
int 21h
Print ENDP
END BEGIN

if i don't call int8 at last there would be nothing, but calling
int8 it raises error
I doubt if there's something related to iret ( for example i shoud
have written ret 6 )
and also int 10 if it has something having to be considered please
let me know
please help me, it's an urgent case, Thank you

Comments

  • I see that you have oldint8 declared as a doubleword, but you only store the offset of the old handler's address in it. Additionally, you hook the handler without setting DS properly (assuming you're assembling a .EXE). Why are you calling INT 8 as if it was a servicing interrupt, like INT 21h? It's typically used for executing code whenever the programmable interrupt timer "ticks" after a specified count. Also, you're not restoring the interrupt 8 vector back to what it was at the end of your program. You could go TSR, but I don't think that's what you're trying to do. Without restoring the vector, your program ends and the area where it was is overwritten with other things. This other stuff, code or not, is executed whenever the timer ticks. This almost always leads to a crash. Reentrancy is also a problem; it occurs when an interrupt has been called, you interrupt and call it too, and in the process your call mucks up the data of the interrupt servicing the original caller. An example is if you write a TSR that loads itself into memory and the user then might use a program that calls INT 21h, say for file management. The user invokes your TSR (or maybe some other event does) and you accidentally put in INT 21h code to print stuff. You've just had two programs call one INT meant for only one program at a time.

    [code]
    .MODEL SMALL
    .CODE
    ORG 100H
    BEGIN: JMP SHORT MAIN
    Message db 'Hi$'
    oldint8 dd ?
    MAIN PROC NEAR
    ; get address of int8
    mov ah, 35h
    mov al, 8
    int 21h
    ; save address of int8
    mov word ptr oldint8, bx
    [red]mov word ptr oldint8 + 2, es[/red]
    ; set the new address
    mov ah, 25h
    mov al, 8
    [red]mov bx,cs
    mov ds,bx[/red]
    mov dx,Offset newint8
    int 21h

    int 8

    [red];Restore the INT 8 vector here using INT 21h function 25h or
    ;you'll get a crash in a few milliseconds due to the timer using INT 8
    ;as well![/red]

    [red];Where are you exiting? Will you use a RET (.COM file), INT 20h,
    ;or function 4Ch of INT 21h to complete it?[/red]

    .exit
    MAIN ENDP
    newInt8 Proc Near
    pushf
    cli [red];The CPU clears the interrupts flag during an interrupt already.[/red]
    call [red]FAR[/red] CS:oldint8 ;Call prior handler.

    call print [red];I see this executes INT 21h, quite possibly reentering it (applicable to a TSR)![/red]
    iret
    newInt8 endp
    Print Proc Near ;[red]Try using direct screen writes (seg 0B800h) instead[/red]
    lea dx, message
    mov ah, 09h
    int 21h
    [red]ret ;Ahem, can't forget this![/red]
    Print ENDP
    END BEGIN
    [/code]
  • [green]I'm writing a .Com file so CS is not important for me, the problem is that i want to add my function at the beginning of the int8 and let it do what it was supposed to do in int8.
    the main problem is kind of return from my newint8 procedure. When I looked at some relative example of replacing an interrupt, the behaviour of the newproc was different, in replacing int9 there was just iret, but in replacing of int13 it was ret 2 because the writer had known that in that specific interrupt(int13) he has to ret 2
    my problem is that it doesn't work, when i run my code nothing happens, i expect that 'Hi' be printed in every call for int8 ( i mean 1/18 second ) but nothing happens.[/green]
    [size=3]your help is highly appreciated, thank you.[/size=3]

    : I see that you have oldint8 declared as a doubleword, but you only store the offset of the old handler's address in it. Additionally, you hook the handler without setting DS properly (assuming you're assembling a .EXE). Why are you calling INT 8 as if it was a servicing interrupt, like INT 21h? It's typically used for executing code whenever the programmable interrupt timer "ticks" after a specified count. Also, you're not restoring the interrupt 8 vector back to what it was at the end of your program. You could go TSR, but I don't think that's what you're trying to do. Without restoring the vector, your program ends and the area where it was is overwritten with other things. This other stuff, code or not, is executed whenever the timer ticks. This almost always leads to a crash. Reentrancy is also a problem; it occurs when an interrupt has been called, you interrupt and call it too, and in the process your call mucks up the data of the interrupt servicing the original caller. An example is if you write a TSR that loads itself into memory and the user then might use a program that calls INT 21h, say for file management. The user invokes your TSR (or maybe some other event does) and you accidentally put in INT 21h code to print stuff. You've just had two programs call one INT meant for only one program at a time.
    :
    : [code]
    : .MODEL SMALL
    : .CODE
    : ORG 100H
    : BEGIN: JMP SHORT MAIN
    : Message db 'Hi$'
    : oldint8 dd ?
    : MAIN PROC NEAR
    : ; get address of int8
    : mov ah, 35h
    : mov al, 8
    : int 21h
    : ; save address of int8
    : mov word ptr oldint8, bx
    : [red]mov word ptr oldint8 + 2, es[/red]
    : ; set the new address
    : mov ah, 25h
    : mov al, 8
    : [red]mov bx,cs
    : mov ds,bx[/red]
    : mov dx,Offset newint8
    : int 21h
    :
    : int 8
    :
    : [red];Restore the INT 8 vector here using INT 21h function 25h or
    : ;you'll get a crash in a few milliseconds due to the timer using INT 8
    : ;as well![/red]
    :
    : [red];Where are you exiting? Will you use a RET (.COM file), INT 20h,
    : ;or function 4Ch of INT 21h to complete it?[/red]
    :
    : .exit
    : MAIN ENDP
    : newInt8 Proc Near
    : pushf
    : cli [red];The CPU clears the interrupts flag during an interrupt already.[/red]
    : call [red]FAR[/red] CS:oldint8 ;Call prior handler.
    :
    : call print [red];I see this executes INT 21h, quite possibly reentering it (applicable to a TSR)![/red]
    : iret
    : newInt8 endp
    : Print Proc Near ;[red]Try using direct screen writes (seg 0B800h) instead[/red]
    : lea dx, message
    : mov ah, 09h
    : int 21h
    : [red]ret ;Ahem, can't forget this![/red]
    : Print ENDP
    : END BEGIN
    : [/code]
    :

  • The author of the INT 13h routine probably wanted to return a modified FLAGS register intact. IRET pops IP, CS, and FLAGS in that order. RETF pops only IP and CS, but will additionally pop the number of bytes you specify by an immediate value. The value of 2 was selected because it just happens that FLAGS takes up 2 bytes on the stack (in real/V86 mode).

    I assume you don't want your TSR to become resident because the "Hi" thing would get very annoying very quickly! Here's some untested code:
    [code]
    GetVector equ 3500h
    SetVector equ 2500h
    DOS_Int equ 21h
    TimerInt equ 8
    Call_Far_Imm_Opcode equ 9Ah
    LF equ 10
    CR equ 13

    mov ax,GetVector + TimerInt
    int 21h
    mov [OldInt08hHandler + 0],bx
    mov [OldInt08hHandler + 2],es

    mov ax,GetVector + DOS_Int
    int 21h
    mov [OldInt21hHandler + 0],bx
    mov [OldInt21hHandler + 2],es

    mov ax,SetVector + TimerInt
    mov dx,NewInt08hHandler
    int 21h

    mov ax,SetVector + DOS_Int
    mov dx,NewInt21hHandler
    int 21h

    xor ah,ah ;Wait for a keypress before continuing.
    int 16h

    mov ax,SetVector + TimerInt
    lds dx,[OldInt08hHandler]
    int 21h

    mov ax,SetVector + DOS_Int
    lds dx,[cs:OldInt21hHandler] ;The CS override is needed because DS
    int 21h ;doesn't point to CS because of the last LDS DX,[...] execution.

    int 20h ;Exit.

    NewInt08hHandler:
    pushf ;It's a good idea to call the likely time
    db Call_Far_Imm_Opcode ;critical hardware interrupt handler first.
    OldInt08hHandler dd 0
    cmp [cs:InDOS],0
    jnz _Iret

    push ds ;The INT 16h handler probably needs DS to remain constant.
    push cs
    pop ds
    mov ah,9
    mov dx,Hi
    int 21h
    pop ds

    _Iret:
    iret ;Here FLAGS needs to remain intact.

    NewInt21hHandler:
    mov [cs:InDOS],1
    pushf ;Note that a PUSHF/CALL FAR pair simulates an INT.
    db Call_Far_Imm_Opcode
    OldInt21hHandler dd 0
    mov [cs:InDOS],0 ;The reason I didn't use AND was because it would modify the flags.
    retf 2 ;It is very likely that a DOS service needed to return FLAGS intact.
    ;Using IRET instead could prove disastrous (sp?).

    InDOS db 0
    ;There's an undocumented call that can be made to DOS to retrieve the
    ;address of a flag with similar function. This example demonstrates
    ;using your own flags.

    Hi db LF, CR, "Hi$"

    [/code]
  • Thank You
    I set and get oldinterrupt directly from 0:[intNumber * 4]
    It worked out, but when i try to use the same code with int21 and ah=35 and ah=25 it didn't work , i don't know why but it didn't

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories