;                   IdIRQ.asm
;
;       Эта программа _ПЫТАЕТСЯ_ определить базовый IRQ
;
;      идея: Дмитрий  Зоткин  2:5020/28.33
; реализция: Сусликов Евгений 2:5020/35.200
;
;-----------------------------------------------------------
        .model tiny
        .code
        org  100h
start:
        jmp  skip
msg     db   13,10," ■ IRQ base: "
msgXX   db   "??",13,10,36
msg2    db   13,10," Timeout...",13,10,36
        even
baseCS       dw   0
tempCS       dw   0
baseIRQ      dw   0
old21port    db   0

        even
chain_int:
        sti
        db   0EAh
jmpAddr dd   0

; сюда придут ВСЕ прерывания (видел, кажется, у Пачковского)

all_int:
        cli
        push cs
        db   0EAh
        dw   align_segment
my_seg  dw   0

align_segment:
        pop  cs:tempCS
        push ax cx di si ds es

; поставили вектора на место

        mov  ax,cs
        mov  ds,ax
        sub  ax,ax
        mov  es,ax
        mov  si,OFFSET oldVectors
        sub  di,di
        mov  cx,200h
        rep  movsw

; посчитали, по какому вектору пришло прерывание

        mov  si,tempCS
        sub  si,baseCS
        mov  baseIRQ,si

; и ушли на оригинальный

        shl  si,1
        shl  si,1
        push ds es
        pop  ds es
        mov  di,OFFSET jmpAddr
        movsw
        movsw
        pop  es ds si di cx ax
        jmp  chain_int

;-----------------------------------------------------------
;
;       подготовить таблицу векторов
;

MakeVectors  proc
        mov  ax,cs
        mov  my_seg,ax
        mov  cx,256
        sub  ax,cx
        mov  baseCS,ax
        mov  bx,OFFSET all_int + 256*16
        sub  di,di
        mov  es,di
        cld
        cli
make_loop:
        xchg ax,bx
        stosw
        xchg ax,bx
        stosw
        inc  ax
        sub  bx,16
        loop make_loop
        sti
        ret
MakeVectors  endp

;-----------------------------------------------------------
;
;       byte -> string
;

H2S     proc
        mov  ah,al
        shr  al,1
        shr  al,1
        shr  al,1
        shr  al,1
           call Convert
Convert:
        and  al,0fh
        add  al,90h
        daa
        adc  al,40h
        daa
        xchg al,ah
        ret
H2S     endp

;-----------------------------------------------------------

skip:

;       сохраним значение из 21-го порта

        in   al,21h
        mov  old21port,al

;       сохраним вектора

        mov  di,OFFSET oldVectors
        sub  si,si
        mov  ds,si
        mov  cx,200h
        rep  movsw
        mov  ax,cs
        mov  ds,ax

;       запретим все, кроме таймера

        mov  al,0FEh
        out  21h,al
        jmp  short $+2

;       поставим все на ALL_INT

           call MakeVectors
        mov  ax,cs
        mov  ds,ax
        sub  ax,ax
        mov  es,ax

;       ждем прерывания от таймера

        mov  cx,100h
dummy:
        push cx
        sub  cx,cx
dummy2:
        cmp  tempCS,ax          ; если <> 0, то чего-то дождались
        jnz  break
        loop dummy2
        pop  cx
        loop dummy
break:

;       вернули 21-й порт обратно

        mov  al,old21port
        out  21h,al
        jmp  short $+2

        jcxz timeout_error      ; цикл прошел, а нет ничего => timeout

;       показали базовый вектор

        mov  al,byte ptr baseIRQ
           call H2S
        mov  word ptr msgXX,ax
        mov  dx,OFFSET msg
        jmp  short done

;       timeout

timeout_error:
        cli
        mov  si,OFFSET oldVectors
        sub  di,di
        mov  cx,200h
        rep  movsw
        sti
        mov  dx,OFFSET msg2

;       вот и все

done:
        mov  ah,9
        int  21h
        mov  ah,4ch
        int  21h

        align 16
        db   "by SEN ",??DATE,"."
oldVectors   label word
        end  start


