.386                       ; TASM Vorspann
code segment use16 para
assume cs:code,ds:code,es:code,ss:code
org 0100h                  ; an offset 0100h anlegen,
start:                     ; da .com Programm
  Call Print_Time          ; Momentane Zeit ausgeben

  call INSTALL_TIMER

  mov ax,13                ; nach 13 Sekunden Unterbrechung
  mov bx,cs                ; Handler adresse in bx:cx
  mov cx,offset Handler
  call SET_TIMEOUT         ; SET_TIMEOUT aufrufen (INSTALL_TIMER automatisch!)
  cmp ax,0
  jnz Fehler               ; Fehler aufgetreten
  
  mov ax,0b800h            ; es=0b800h (Segment fuer Bildschirmspeicher)
  mov es,ax            
  mov al,070h              ; Hintergrund invertieren          
  mov si,120               ; insgesamt drei schleifen:
outer_loop2:               ; for k=30 to 0; for l=500 to 0; for m=65536 to 0
  mov di,160
outer_loop:         
  mov cx,0
schleife: loop schleife    ; innerste Warte Schleife
  dec di                   
  mov es:[di],al           ; Abwechselnd invertieren/normal
  dec di
  jnz outer_loop           ; next l
  xor al,077h              ; Al ist abwechselnd 070h 007h 
  dec si                                
  jnz outer_loop2          ; next k

Ende:
  call REMOVE_TIMER        ; Zaehlroutine deinstallieren
  Call Print_Time          ; Zeit ausgeben
  int 020h                 ; Programm beenden  

Fehler: 
  mov dx,offset Fehlerstring
  mov ax,0900h
  int 021h
  jmp Ende

Fehlerstring db 'Fehler. Timeout schon besetzt.',0Dh,0Ah,'$'
            
; Handlerroutine gibt einen kleinen Text aus und 
; schreibt die Aktuelle Zeit auf den Bildschirm
Handler:                  
pusha                     ; Sichern der Register
  mov ax,cs               ; Text ausgeben
  mov ds,ax               ; dazu DOS Int 021h Routine Nummer 9 aufrufen:
  mov ax,0900h            ; ds:dx Adresse von auszugebenden Text
  mov dx,offset output
  int 021h                 
  Call Print_Time         ; Zeit ausgeben
popa                      ; Zuruecksichern der Register
retf             
output db 'Das ist ein Test!',0Dh,0Ah,'$'    ; Text fuer Handler


Print_Time:
  mov ax,0200h              ; Zeit mit BIOS Int 01Ah Funktion 02 auslesen
  int 01Ah                  
  push dx                   ; dx (Sekunden) sichern
  mov ah,ch                 ; Stunden nach ah
  call Bcd_to_Ascii         ; Und in Ascii uebersetzen 
  mov ax,0900h              ; und mit DOS Int 021h Funkt 09 schreiben
  mov dx,offset ascii       
  int 021h
  mov dx,offset double      ; Doppelpunkt ausgeben
  int 021h
  mov ah,cl                 ; Minuten nach ah
  call Bcd_to_Ascii         ; in Ascii uebersetzen 
  mov ax,0900h              ; und ausgeben
  mov dx,offset ascii
  int 021h
  pop dx                    ; dx (Sekunden) vom Stack holen 
  mov ah,dh                 
  Call Bcd_to_Ascii         ; in Ascii uebersetzen
  mov ax,0900h              
  mov dx,offset double      ; Doppelpunkt ausgeben
  int 021h
  mov dx,offset ascii       ; Sekunden ausgeben
  int 021h
  mov dx,offset return      ; Naechste-Zeile-Code ausgeben
  int 021h       
ret

; Eingabe ah = bcd Code von Zahl
; Ausgabe als Asciistring als $ beendeter String bei ascii
Bcd_to_Ascii:
push ax                     
shr ax,4
shr al,4
add ah,48
add al,48
mov ascii,ah
mov ascii+1,al     
pop ax
ret                  

ascii db '  $'             ; Hier kommt das Ergebnis von Bcd_to_Ascii rein
double db ':$'             ; Doppelpunktstring
return db 0Dh,0Ah,'$'      ; CR-LF-string
include tgirout.asm        ; Timeoutroutinen einbinden
code ends   
end start