Zaehler:                     ; Zaehlroutine
cmp cs:flag,0                ; Zaehlroutine aktiviert ?
jz Ende_Zaehler              ; nein => Sprung zum Ende
dec cs:time                  ; ja => Zaehler dekrementieren
jnz Ende_Zaehler             ; Zaehler!=0 => Sprung zum Ende
mov cs:flag,0                ; Zaehlroutine deaktivieren
call cs:[hdl_adr]            ; Handlerroutine aufrufen
Ende_Zaehler:                
jmp cs:[old_adr]             ; Alten Int 01Ch anspringen



Install_Timer:               ; INSTALL_TIMER
cmp cs:installed,0           ; Schon installiert ?
jnz Ende_Install             ; Ja => Sprung zum Ende
push ax                      ; Verwendete Register sichern
push ds                      
mov ax,0                     
mov ds,ax                    ; ds=0  (Interrupts liegen bei 0:Adresse)
mov ax,ds:[070h]             ; ax=offset Int 01Ch
mov cs:[old_ofs],ax          ; abspeichern
mov ax,ds:[072h]             ; ax=segment Int 01Ch
mov cs:[old_seg],ax          ; abspeichern
cli                                      ; Jetzt keinen Interrupt !
mov word ptr ds:[070h],offset Zaehler    ; neue Int 01Ch Adresse setzen
mov ds:[072h],cs
sti                                      ; Interrupts wieder zulassen
mov cs:installed,1                       ; Installflag setzen
pop ds                                   ; benutzte Register zuruecksichern
pop ax              
Ende_Install:                          
ret               


Remove_Timer:                    ; Remove_Timer
cmp cs:installed,0               ; War was installiert ?
jz Ende_Remove                   ; nein => Sprung zum Ende 
push ax                          ; benutzte Register sichern
push ds
  mov ax,0
  mov ds,ax                      ; ds=0 (Interruptadressen sind bei Segment 0)
  cli                            ; Jetzt keinen INTERRRRRRRRUPT !!!!!!!! 
  mov ax,cs:[old_ofs]            ; ax=alter Offset
  mov ds:[070h],ax               ; und setzen
  mov ax,cs:[old_seg]            ; ax=altes Segment
  mov ds:[072h],ax               ; und setzen
  sti
  mov cs:flag,0                  ; fuer spaetere Neuinstallation deaktivieren
  mov cs:installed,0             ; und Installationsflag loeschen
pop ds                           ; Register zuruecksetzen
pop ax
Ende_Remove:
ret    



; ax   DELAY
; bx   Segmentadresse Handler
; cx   Offsetadresse Handler

; Ausgabe: ax==0 => Erfolgreich installiert.
;          ax==1 => Fehler aufgetreten (Timeout schon besetzt)
SET_TIMEOUT:                           ; SET_TIMEOUT
push bp                                ; Prolog
mov bp,sp                              ; alten SP sichern 
sub sp,2                               ; platz fuer return-code
mov word ptr [bp-2],1                  ; zunaechst mal Fehler annehmen
cmp cs:installed,0                     ; Zaehlroutine Installiert
jnz No_Install                         ; Ja => weiter gehts
call Install_Timer                     ; Nein => Gleich mal installieren
No_Install:                            
cmp cs:flag,0                          ; Zaehlroutine schon aktiviert
jnz Ende_Timeout                       ; => Anfrage ignorieren und zum Ende
mov word ptr [bp-2],0                    ; Ab jetzt kein Fehler mehr
push ax                                ; benutzte Register sichern
push dx
push si
mov si,182                             ; Zeit in Ticks ausrechnen:
mul si                                 ; dx:ax=ax * 182
add ax,5                               ; ax+5 (wegen Rundung)
jnc no_carry                           ; kein Ueberlauf, alles ok
inc dx                                 ; Ueberlauf => noch eins zu dx dazu
no_carry:                              ; d.h. dx:ax+=5
mov si,10                              
div si                                 ; ax=dx:ax/10  (ax=ax*18.2 (gerundet)) 
mov cs:time,ax                         ; Zeit in Ticks setzen
mov cs:hdl_ofs,cx                      ; Offset der Handlerroutine setzen
mov cs:hdl_seg,bx                      ; Segment der Handlerroutine setzen
mov cs:flag,1                          ; und aktivieren
pop si                                 ; benutzte Register zuruecksichern
pop dx
pop ax
Ende_Timeout:
mov ax,[bp-2]                                 ; Returncode nach ax
mov sp,bp
pop bp
ret

 
flag db 0                              ; Aktivierungsflag fuer Zaehlroutine
installed db 0                         ; Installierungsflag 
time dw 0                              ; Wartezeit in Ticks (1/18.2 s)
hdl_adr equ this dword                 ; Handler-Adresse (seg:ofs)
hdl_ofs dw 0                           ; Offset von Handler-Adresse
hdl_seg dw 0                           ; Segment von Handler-Adresse

old_adr equ this dword                 ; das Gleiche f. alten Int 01Ch 
old_ofs dw 0
old_seg dw 0