
.fi schoen            
  
         von W.SOKOL und F.FIALA

De folgend Beitra sol di Bedeutun de Interrupt (Unterbre
chungen i MSDOS-Betriebssyste zeigen Beispielprogramm werde 
vorgestellt.

PC-Interrupts
=============
     * Wie funktionieren sie?
     * Wie bentzt man sie?
     * Was ist ein Interrupt-Vektor?
     * Wie kann man den Wert des Interrupt-Vektors sichtbar machen?
     * Wie verndert man eine Interrupt-Service-Routine?
     * Wie baut man ein Tastatur-Filter ein?
     * Wie testet man das Interrupt-Programm?

PC-DOӠ is ei interruptgesteuerte Betriebssystem CP/͠ ka zu 
Beispie i manche Implementatione zu Gnz ohn Interrupt aus 
Da ist fas so al mt di Softwar i all Richtunge gleich
zeiti schauen Di Interrupt (=Unterbrechungen vereinfache de 
Aufba eine Betriebssystem un ermgliche komplexer Systeme d 
di Programm be Einhaltun einfache Regel entkoppel sind Ma 
vergleich nu de Bandwurmkod de APPLE-Bio mi de Aufba de 
PC-Bios.

Durc eine Interrup wir da Program gezwunge de normale 
Programmablau z verlassen sic de Interruptusach zuzuwende un 
danac wiede da ursprnglich Program fortzufhren D Interrupt 
i.a vo externe Quelle komme (Tastatur Megert Timer... sin 
si asynchron Ereigniss bezoge au da aktuell Programm S wi 
wi durc ei Telefo dutzend Mal a Ta a unsere Arbei gehin
der werde knnen wir e ei Rechne tausende- ode millionenmal 
pr Tag 

Ein wichtig (un di ursprngliche Anwendun vo Interrupt is 
di堠 Datenbertragun砠 zwische externe Hardwar堠 (Tastatur 
Diskette.. un de Prozessor 

E ha sic offenba herumgesprochen da di Interrupt praktisc 
verwendba sin un ma ha si i P s verallgemeinert da auc 
di Softwar eine Interruptaufru durc de Befeh INԠ simuliere 
kann 

Ma erhl ein einheitlich Struktu de Benutzerschnittstell 
anstell de bei CPM-Syste verwendete Unterprogrammaufrufe.

Di堠 Kommunikatio zwische Benutzerprogram un Betriebssyste 
erfolg nich be konkret Adresse sonder ebenfall be 
Interrupts Wen jede Anwenderprogram di Startadress eine 
bestimmte Betriebssystem-Routin (e gib be 50 kenne mte 
wr e schwer nderunge a Betriebssyste vorzunehmen S norm 
ma einfac di Interruptnummer Au welche Adress di zugehrig 
Routine steht ist ohne Bedeutung.
.pa
Arten der Interrupts
====================

Die Interrupts knnen am IBM-PC in 4 Gruppen eingeteilt werden:

1. CPU-Interrupts
-----------------
Dies  fn Interrupt sin bereit i di Architektu de CP 
eingebaut Si werde ausgelst wen ein de Bedingunge eintritt:

Interrupt Interruptursache
Nummer:
     0H   Division durch Null
     1H   Single Step
     2H   NMI
     3H   Break Point
     4H   Overflow

2. Hardware-Interrupts (durch 8259 priorittsgesteuert)
----------------------
     8H   Zeitgeber
     9H   Tastatur
     BH   COM2
     CH   COM1
     DH   Hard-Disk
     EH   Floppy-Disk
     FH   Drucker

Beispiel Seriell Schnittstelle0BH,0CH 
Sowoh di Ankunf eine Zeichens al auc da erfolgt Absen
de eine Zeichen lse eine Interrup aus Welch de beide 
Interruptursache f de Interrup mageben war is be 
Einlange de Interrupt noc unbekannt Da Program (di 
sogenannt Interrupt-Service-Routine prf i serielle Inter
face-Baustei WĠ 825 da entsprechend Interrupt-Fla un 
verzweig dan i di richtig Routin i BIOS-ROM Di Inter
rupt-Ursach wir durc di Interrupt-Service-Routin festge
stell un behandelt.

3. BIOS-Funktionen (Software-Interrupts)
------------------
Interrupt      Interruptursache
Nummer: 
     10H-1FH   immer ein Programm, mit Parameterbergabe
 
Hie beginn di Grupp jene 'Interrupts' di mi Parameterber
gab ausgefhr werde un dennoc denselbe Aufrufmechanismu be
ntze (Software-Interrupt) Da is s z verstehen Ei Hardware-
Interrup kan irgendwan eintreffen De einzige durc de Inter
rupt-Controlle bergeben Paramete is di Interrupt-Nummer Wa 
de Interrup bewirk ha is z diese Zeitpunk noc unkla un 
mu durc di Interrupt-Service-Routin festgestell werden Di 
Maschinensprach de 808 erlaub es diese Fal de Hardware
interrupt durc eine Befeh (INT z simulieren soda de Pro
grammaufba (insbesonder de Abschlu mi IRET de Hardware-Inter
rupt un de BIOS-Funktione gleic sei kann De programmge
steuert Interrup erforder anstell de i Punk  beschriebene 
'Quellenforschung'(=Feststellun de Interruptursache da Gegen
teil nmlic da setze vo Anfangsbedingunge i de Prozessor
registern Di Anfangsbedingunge sin erforderlich dami da BIOS-
Program auc wei wa de Benutze eigentlic will 

Beispiel Seriell Schnittstelle14H
D da BIOS-Program nich meh unmittelba durc ein Hard
ware-Funktio ausgels wird sonder nu durc eine sogenann
te Software-Interrupt werde i de Prozessorregister A un 
A Paramete bergeben Beispiel AH=1 Zeiche i A senden 
AH= Zeiche empfange un i A bergeben.

Di BIOS-Interrupt sin i Boot-Epro enthalten E sin di 
Interrupt 0..31 


4. PC-DOS-Interrupts
--------------------
Interrupt      Interruptursache
Nummer: 
     20H-1FH   immer ein Programm, mit Parameterbergabe
 
Dies Grupp vo Interrupt wir ausschlielic dan installiert 
wen mi de MS-DOS-Betriebssyste gefahre wir (MS-DOS-System
diskette) All andere Betriebssysteme di au unsere Rechne 
mglic sin (CP/ 86 VENIX XENI abe auc viel Spiel habe 
dies Interrupt-Aufruf nicht 

.pa

Anzeigen der Interrupt-Vektoren
===============================

Ein List de Interrupt-Vektore vo 0..3 knne Si sic durc 
da folgend Program ausdrucke lasse 

.fi elite

(*****************************************************************************)
program VEKTOR;
(*****************************************************************************)

(*
Anzeige des aktuellen Wertes der Interrupt-Vektoren im IBM-PC.
Die Anfangswerte sind im technischen Handbuch auf Seite 3.3 enthalten.
Die Adressen und zustzlichen Informationen siehe Seite 3.21
*)
(*P$256 *)
(* Die Compiler-Otion P256 wird bentigt
um die durch das Programm VEKTOR erzeugte Tafel
in eine Datei umzulenken.

Diese Option ist bei frheren Turbo-PASCAL-Versionen nicht mglich.
Das Umlenken erfolgt durch folgenden Programmaufruf:
     vectors > vector.lst
vector.lst ist der Name der Datei, in die die Tafel geschrieben wird 
*)

type
     VectorName = string (.30.);
     HexWort    = string (.5.);


(*$I HEX.P *)

(*
Hex bernimmt eine 16-Bit-Zahl als Argument
und bergibt einen 5-Zeichen-String,
der das hexadezimale Aequivalent dieser Zahl ist
*)

procedure PrintVector (V:integer; S:VectorName);
(*
PrintVector druckt fr jeden Interrupt den zugehrigen Interrupt-Vektor
*)
var
     A,B,C,D   : integer;
begin
     A    := mem (.0000:V*4.);
     B    := mem (.0000:V*4+1.);
     C    := mem (.0000:V*4+2.);
     D    := mem (.0000:V*4+3.);
     Write (Hex(V),S:20,' ',Hex((D SHL 8)+C),':',Hex((B SHL 8)+A));
end;
.fi schoen
.pa
.fi elite
begin (* Hauptprogramm *)
  ClrScr;               PrintVector ($00,'Division durch 0');
  GotoXY( 1,WhereY+1) ; PrintVector ($01,'Single Step');
  GotoXY( 1,WhereY+1) ; PrintVector ($02,'NMI');
  GotoXY( 1,WhereY+1) ; PrintVector ($03,'Haltepunkt');
  GotoXY( 1,WhereY+1) ; PrintVector ($04,'OverFlow');
  GotoXY( 1,WhereY+1) ; PrintVector ($05,'PrintScreen');
  GotoXY( 1,WhereY+1) ; PrintVector ($06,'Reserviert');
  GotoXY( 1,WhereY+1) ; PrintVector ($07,'Reserviert');
  GotoXY( 1,WhereY+1) ; PrintVector ($08,'Timer');
  GotoXY( 1,WhereY+1) ; PrintVector ($09,'Tastatur');
  GotoXY( 1,WhereY+1) ; PrintVector ($0A,'EGA');
  GotoXY( 1,WhereY+1) ; PrintVector ($0B,'COMM,Reserviert');
  GotoXY( 1,WhereY+1) ; PrintVector ($0C,'COMM,Reserviert');
  GotoXY( 1,WhereY+1) ; PrintVector ($0D,'Alt.Printer,80287');
  GotoXY( 1,WhereY+1) ; PrintVector ($0E,'Disk');
  GotoXY( 1,WhereY+1) ; PrintVector ($0F,'Reserviert');
  GotoXY(40,1)        ; PrintVector ($10,'Video I/O');
  GotoXY(40,WhereY+1) ; PrintVector ($11,'Equipment Check');
  GotoXY(40,WhereY+1) ; PrintVector ($12,'Memory Check');
  GotoXY(40,WhereY+1) ; PrintVector ($13,'Disk I/O');
  GotoXY(40,WhereY+1) ; PrintVector ($14,'RS-232 I/O');
  GotoXY(40,WhereY+1) ; PrintVector ($15,'Cassette I/O');
  GotoXY(40,WhereY+1) ; PrintVector ($16,'Keyboard I/O');
  GotoXY(40,WhereY+1) ; PrintVector ($17,'Printer I/O');
  GotoXY(40,WhereY+1) ; PrintVector ($18,'Rom BASIC Entry');
  GotoXY(40,WhereY+1) ; PrintVector ($19,'Boot Strap Loader');
  GotoXY(40,WhereY+1) ; PrintVector ($1A,'Tageszeit');
  GotoXY(40,WhereY+1) ; PrintVector ($1B,'KBD Break');
  GotoXY(40,WhereY+1) ; PrintVector ($1C,'Timer-Tick');
  GotoXY(40,WhereY+1) ; PrintVector ($1D,'Video-Init 6845');
  GotoXY(40,WhereY+1) ; PrintVector ($1E,'Diskparameter');
  GotoXY(40,WhereY+1) ; PrintVector ($1F,'Gr.Char.Table');
end.

.fi schoen
Di folgend Include-Date HEX. wir auc i de sptere Testpro
gram INTER.PA verwendet.
.fi elite 
(*
Die Funktion 'HEX' erhaelt ein 16-Bit-Integer-Wort als Argument
und uebergibt einen String aus 4 zeichen
das das hexadezimale quivalent dieser Zahl ist
*)
function  Hex (v:integer):HexWort;
const
     map:array (.0..15.) of char='0123456789abcdef';
var
     Tmp : HexWort;
begin
     Tmp (.4.) := Map (.(v and $7fff) Mod 16.); (* Maskieren der Vorzeichen-Stelle *)
     Tmp (.3.) := Map (.(v shr 4) mod 16.);
     Tmp (.2.) := Map (.(v shr 8) mod 16.);
     Tmp (.1.) := Map (.(v shr 12) mod 16.);
     Tmp (.0.):=#4;                             (* Byte 0 ist die String-Laenge *)
     Hex := Tmp;
end;
.fi schoen
.pa
Abarbeitung eines Interrupts
============================
Interrupts knnen auf zwei Arten ausgelst werden.

     * durch Hardware (IRQ-Leitung)
     * durch Software (INT-Befehl)

Maskieren von Interrupts
Nac de Geset vo Murph trete Interrupt imme dan auf wen 
ma si a wenigste braucht Beispielsweis wen gerad ein Inter
rupt-Service-Routin abgearbeite wird Interrupt knne (mi eine 
Ausnahme NMI maskier werden  da heit ih Auftrete kan be 
Bedar ignorier werden Daf is de Maschinen-Befeh CL vorgese
hen Der dazu inverse Befehl ist STI.

Hardware-Interrupts
F all periphere Einrichtunge steh ein einzig Interrupt-
Leitun a de CP zu Verfgung Wen nu dies Mglichkei de 
Unterbrechun砠 bestnde dan wt di CPՠ zwa vo de 
Unterbrechung nich abe welch Einrichtun etwa will Da ergb 
ein uers zeitraubend Such nac de Strenfried Deshal 
liefer di Interruptquell gleichzeiti auc di Interruptnumme a 
di CPU 

Di bliche Interruptquelle (Schnittstellen knne da nich 
selbstndig si bediene sic de Interrupt-Controller 8259 de 
bei Boote di Interruptnummer mitgeteil werden Di Inter
ruptquell melde sic bei 825 be ein vo  Leitunge (IRQ0-
IRQ7) Dies sin f di Priorisierun de Interrupt vorgesehen 
Da hei be gleichzeitige Auftrete mehrere Interrupt gib e 
ein Abhngigkeitsreihenfolge di durc di Signalzustnd au 
diese Leitunge bestimm ist Di Reihenfolg wurd i de letzte 
PC-New abgedruckt Di Abarbeitungsreihenfolg wir durc de 825 
(PIC Programabl Interrup Controller untersttzt 
E gibt wen diese Interrup nich maskier ist dies Aufforde
run a di CP weiter wen nich gleichzeiti ei Interrup 
hhere Priorit einlangt E addier vorhe z de Leitungsnumme 
nu meh di Zah 8 

De Prozeso erhh dies Zah durc Multiplikatio mi  un erhl 
ein Numme (0..255 au de e ein Adress (0..1023 berechnet 
au de de sogennant Interrupt-Vekto steht  Di Adress is 
einfac Interrupt-Nummer*4 d jede Interrupt-Vekto 3 Bit umfa 
(Segment+Offset) Di erste 102 Adresse sin f di Interrupt-
Vektore reserviert 

Al nchste werde all weitere etw einlangende Interruptanfor
derunge durc di CP automatisc gesperr (entsprich de Befeh 
CLI un da Flaggenregiste au de Stape gebracht Danac wir 
di Interrupt-Service-Routin angesprungen.

Di erst Aufgab eine Interrupt-Service-Routin is nu da Fest
stelle de Interrupt-Ursach堠 un䠠 danac蠠 di堠 eigentlich 
Abarbeitung Davo un danac abe msse einig Formalitte 
erledig werden Dami di CPU-Registe a End de Routin wiede 
i selbe Zustan bergebe z knnen mu de Programmiere daf 
sorgen da  all bentigte Registe a Stape gesicher werde un 
a End de Ausfhrun wiederhergestell werden Auerde mu 
entschiede werde o di Interrupt-Routin wiede durc eine 
Interrup unterbrechba sei sol un wann Da geschieh durc de 
Befeh STI Be zeitkritische Operatione kan da STɠ auc entfallen.

Software-Interrupts
Wir de Interrup durc Softwar ausgelst dan is di Interrupt-
Numme da de INT-Befeh folgend Byte Di Ausfhrun erfolg 
ebenso wie die des Hardware-Interrupt.

Nac Ausfhrun de Interrupt-Service-Routin kehr de Prozesso 
wiede zu ursprngliche Hauptprogram zurck 

Aufruf von Interrupt-Service-Routinen
=====================================
Dami di Interrupt-Service-Routin auc wei wa z tu ist werde 
i de Prozessor-Register Paramete bergeben Z.B.:

Lesen eines Zeichens von der Tastatur

     MOV AH,0
     INT 16H

De Wer i Interrupt-Registe A bestimmt o ei Zeiche gelese 
ode geschriebe wird Is de Wer 0 wir gelesen Be Ausfhrun 
de Interrupt wir da Flaggenregiste un de aktuell Programm
zhlerstan au de Stape gelegt Be Abschlu de Interrupt-
Service-Routin mi IRE wir de Programmzhle wiede gelade un 
di Flagge wiederhergestellt Dahe kan dieselb Routin be 
Kenntni ihre Beginnadress wi i obige Beispie (auc au de 
BIOS durc di Folge:

     MOV AH,0
     PUSHF
     CALL Adresse

simulier werden Di Anweisun PUSH is dabe wichtig sons komm 
de Stape durcheinander.

Die BIOS-Interrupts knnen auch in TURBO_PASCAL verwendet werden:

const V_TASTATUR=$16;
type
   PCreg=record
     case integer of
        1:(ax,bx,cx,dx,bp,di,si,ds,es,Flags:integer)
        2:(AL,AH,BL,BH,CL,CH,DL,DH:byte)
     end;
var
   Register:PCreg
begin
   Register.AH:=0;          (* Tastatur lesen *)
   intr(V_TASTATUR,Register)
end.


.pa
Ein Beispiel fr die nderung der Tastaturabfrage
=================================================
Di meiste Sonderwnsch ha ma bezglic de Tastatur-Routine 
Deshal stamm da Beispie TRIVIAL.AS daz auc au diese Be
reich I de Beispielprogram wir lediglic gefordert da jeweil 
bei Tippe eine 'z diese i ei 'Z verwandel wir un umge
kehrt.

Be Tastaturroutiunge ergib  sic allerding de Nachteil da 
jede Programmfehle de sofortige Systemabstur zu Folg hat d 
di (jetz neue Tastatur-Routin noc nich funktioniert E is 
deshal empfehlenswert zu Teste eine anderen unwichtige Vekto 
z bentzen I diese Fal wir de Vekto 06 (reserviert ode 
15Ƞ (Kassettensteuerung verwendet S wir de lebenswichtig 
Interrup 16Ƞ (Tastatur erhalten Ers wen de Tes mi de 
'Hilfs'-Interrup funktionier wir au 16 umgestellt 


Wi kan ma jetz ei residente Program i da Syste einbauen?

Dazu gibt es zwei grundstzlich verschiedene Mechanismen:

1. Ei COM-Programm welche de DOS-Interrup 27 (Terminat Resi
dent bentzt welche eine definierte Kode-Bereic i da 
Syste einbindet Wichti ist da de Syste jed nderun de 
Interrupt-Vektore mitgeteil wird Die geschieh durc di DOS-
Funktio 35 (Vekto holen un 25 (Vekto setzen) I diese 
beide DOS-Funktione werde di Vektore verndert 

2. Durc eine Einheiten-Treiber Di Einheiten-Treibe habe di 
Endun SYӠ un werde de Syste bei Boote de Text-Date 
CONFIG.SYӠ durc di Anweisun DEVICE=...SYӠ mitgeteilt Dies 
Einheiten-Treibe habe eine definierte Aufbau Ei Beispie 
daf folg i de nchste PC-NEWS.

Da COM-Forma is f klein schnell Utilities mi geringe Platz
bedar gedacht E gib hie kei eigene Stapel-Segmen un e gib 
Beschrnkunge be de Wah de Programm- un Datensegments Di 
Ausfhrun beginn be de Adress 100 un nich be 0H Be COM-
Programme sol kei Stapel-Segmen definier werden un di erst 
Programmzeil mu nac de Assembler-Anweisun OR 100 kommen De 
Assemble erzeug zwa ein Warnung da kei Stapel-Segmen defi
nier war dies Warnun is z ignorieren 

Was geschieht beim Aufruf eines COM-Programms?

 Ein Kopi de Programm-Kode wir au di Adress 100 de aktu
   elle Kode-Segment geschrieben.

 Ei Unterprogrammaufru (CALL au di Adress 100Ƞ wir ausge
   fhrt.

  Da Program kan mi RE ode mi IN 2 abgeschlosse werden.


.pa
Aufrufstruktur beim Aufruf einer BIOS-Routine (GRUNDZUSTAND)
=============================================
0000:
0000H                
              58H=             
            >INTERRUPT->
             4*16H  VEKTOR         
                                   
                         
            ^                         v
                         
                                   
            INT 16H ANWENDER-      
            <PROGRAMM       
                                    
                          
F000:                                 v
E000H                     
                                    
                      R O M    <
                      B I O S  
F000:                          
FFFFH                              


Aufrufstruktu bei Aufru eine BIOS-Routine (MANIPULATION)
=============================================
0000:
0000H                
              58H=   NEUER      
            >INTERRUPT->
             4*16H  VEKTOR         
                                   
                         
            ^    
                         
                   ALTER           
                   VEKTOR          
                   ----------      
                >TREIBER-        unser neues Programm
                    ERGNZUNG >
                         
            ^                         v
                         
                                   
            INT 16H ANWENDER-      
            <PROGRAMM       
                                    
                          
F000:                                 v
E000H                     
                                    
                      R O M    <
                      B I O S  
F000:                          
FFFFH                              
.pa
Aufbau von TRIVIAL.ASM
======================
Definitionen
Sprung auf die Initialisierung
Alter Vektor
Keyboard_Manipulator-Einsprungpunkt
Keyboard_Manipulator (Eigentliches Programm, das resident bleibt)
Initialisierung
     Alten Vektor holen
     Neuen Vektor setzen
     Programm resident machen

Bei DOS-Aufru (Interrupt 27 wir be da Registe Dؠ jen 
Adress mitgeteilt bi z de de Kod residen bleibe soll I 
Program TRIVIAL.AS͠ is de erst Programmkod de Sprun zu 
Initialisierungsroutin a Programmende Dami de Kodebedar mini
mier wird sollt de gesamt Initialisierungsaufwan a da Pro
grammend verlager werden Diese Kodetei wir bei Resident-
mache de Programm einfac vergessen nich abe de Interrupt-
handle selbst 

.fi elite

;TRIVIAL.ASM;

     PAGE   58,132

;Ein triviales Beispiel fr Tastatur-Manipulationsprogrammm

;Konstantendefinitionen
;
V_Tastatur            equ  16H  ;Tastatur-Vektor-Nummer
                                ;fr Testzwecke auf 06H gendert
DOS_Funktion          equ  21H  ;MSDOS-Interrupt
DOS_resident_bleiben  equ  27H  ;Abschlu der Funktion, 
                                ;Kode bleibt resident
DOS_hole_Vektor       equ  35H  ;MSDOS-Funktion zum Holen des 
                                ;alten Interrupt-Vektors
DOS_setz_Vektor       equ  25H  ;MSDOS-Funktion zum Setzen 
                                ;des neuen Vektors
;
CSEG Segment
     assume    cs:cseg,ds:cseg     ;
     org  100H                     ;alle COM-Dateien beginnen bei 100H
;
;die nchste Anweisung wird beim Aufruf der Datei TRIVIAL.COM
;als erste ausgefhrt. Da die einzige Funktion des Programms der Einbau
;des Tastaturtreibers ist, geschieht nichts als das.
;daher wird zum Beginn gleich auf jenem Programmteil gesprungen,
;der den Code resident macht
;
start:
     jmp  Initialisierung
.fi schoen
.pa
.fi elite
;hier kann das Anwenderprogramm beginnen
;
;alle Variablen, die das Anwenderprogramm bentigt,
;knnen hier definiert werden.
;dieser Abschnitt verbleibt resident
;nicht vergessen, alle diese Variablen mssen in CSEG,
;nicht in DSEG definiert sein,
;da jeder Code im Anschlu an das Programm abgeschnitten wird
;
Alter_Tastatur_Vektor_W LABEL WORD  ;Damit dasselbe Ziel
                                    ;(=Alter_Tastatur_Vektor) sowohl
                                    ;als Wort, als auch als D_Wort
                                    ;verwendet werden kann
Alter_Tastatur_Vektor_D dd ?        ;Platz fr den alten Tastaturvektor

;

Tastatur_Manipulator  proc far
     assume    cs:cseg,ds:cseg     ;

;das ist die eigentliche Tastaturbeeinflussungsroutine
;sie prft, welche Tastaturfunktion angefordert wurde.
;wenn die Funktion LESEN ist (ah=0),
;dann simuliert sie einen DOS-Interrupt der alten Funktion,
;die das Zeichen im AL liefert.
;wenn das Zeichen ein 'z' ist, es durch 'Z' ersetzt
;und das Programm beendet
;wenn die Funktion keine LESE-Funktion ist,
;kehren wir einfach zur alten Funktion zurck
;
     sti                           ;Interrupts wieder einschalten
     or   ah,ah                    ;LESEN? (AH=0)
     jnz  ki2                      ;ja,fhre die besondere Routine aus
     pushf                         ;Flaggen auf den Stapel zur 
                                   ;Simulation eines Interrupt-Aufrufs
     assume    ds:nothing          ;
     ;damit das alte Keyboard-Programm nicht nocheinmal
     ;geschrieben werden braucht
     ;bentzen wir es durch einen Interrupt-Aufruf

     call Alter_Tastatur_Vektor_D   ;
                                  ;das Zeichen kommt im Register AL zurck
                                  ;es wird auf 'z' geprft und auf 'Z' transformiert
     cmp  al,'z'                  ;Zeichen kommt in AL
     jne  ki0                     ;wenn kein 'z', nchster Test
     mov  al,'Z'                  ;Umwandlung in 'Z'
     jmp  ki1                     ;beende Interrupt
                                  ;prfe 'Z', verwandle in kleines 'z'
ki0: cmp  al,'Z'                  ;
     jne  ki1                     ;wenn nicht, bleibt Zeichen unverndert
     mov  al,'z'                  ;verwandle in Kleinbuchstaben
ki1: iret                         ;Rckkehr vom Interrupt-Aufruf
;
;wenn AH<>0, wird einfach die Kontrolle der alten
;Tastatur-Routine bergeben
.fi schoen
.pa
.fi elite
ki2:
     assume    ds:nothing
     jmp  Alter_Tastatur_Vektor_D
;
Tastatur_Manipulator     endp
;
;hier endet der Anwender-Code
;
Initialisierung:
     mov  bx,cs                   ;DSEG=CSEG
     mov  ds,bx                   ;8088-Befehlssatz nicht ausreichend
;
;Holen des alten Tastaturvektors
;
     mov  al,V_Tastatur                ;Tastaturvektor
     mov  ah,DOS_hole_Vektor           ;das Betriebssystem wird ber die
                                       ;Vernderung imformiert
     int  DOS_Funktion                 ;
     mov  Alter_Tastatur_Vektor_W,bx     ;alter Vektor in ES:BX
     mov  Alter_Tastatur_Vektor_W[2],es  ;als Variable speichern
;
;Tastatur-Vektor umbiegen
;
     mov  bx,cs                   ;MSDOS-Funktion erwartet den Vektor in DS:CS
     mov  ds,bx     ;
     mov  dx,offset Tastatur_Manipulator
     mov  al,V_Tastatur
     mov  ah,DOS_setz_Vektor
     int  DOS_Funktion
;
     mov  bx,cs                   ;erste nicht mehr bentigte Adresse
     mov  ds,bx                   ;
     mov  dx,offset Initialisierung    ;Programm beenden aber
     int  DOS_resident_bleiben    ;Manipulator bleibt resident
;
CSEG ENDS
     END START

.fi schoen
.pa

Assemblieren
============
Nachde diese einfach Program al Tex geschriebe wurde wir 
de Tex assemblier un gelinkt Al bun is di Texteingab  
nich einma schlecht d ma di Fehlermglichkeiten di bei 
Assembliere mglic sind gan gu kennenlernt Einfache is e 
aber wen Si sic di entsprechend Club-Diskett (au de di PC-
NEWS- sind besorgen Weiter bentig ma daz eine Assembler a 
beste MAS vo Microsoft eine Linke LINK.CO un da Program 
EXE2BIΠ de Betriebssystemdiskette E is folgend Eingabefolg 
notwendig:

    MAS <name         ;Assembliere de Programm <name>.AS 
                        ;(erforder de Microsoft-Assemble MASM
                        Es werden die Dateien:
        <name>.OBJ
        <name>.LST
        <name>.CRF
     erzeugt. 
    
    LINK <name>         Erzeugt <name>.EXE aus <name>.OBJ
    
    EXE2BIN <name>      Erzeugt <name>.BIN aus <name>.EXE
    RENAME <name>.BIN <name>.COM
    
Da wa nu da Prinzip Dies Anweisungsfolg knne Si auc durc 
Ausfhrun de Batch-Date ASM.BAԠ erreichen Si is etwa 
komfortabe un erforder whren de Assemblieren un Linken 
kein weiter Eingab vo de Konsole.

Inhal de Date ASM.BAT (be mi is de Assemble i de 
                           Subdirectory 'asm')

    \asm\masm %1,%1,%1,,
    if NOT exist %1.OBJ goto fehler
    
    \asm\link %1,%1,%1;
    if NOT exist %1.EXE goto fehler
    exe2bin %1
    
    erase %1.COM
    rename %1.BIN %1.COM
    echo Assemblierung erfolgreich
    goto ende
 
    :fehler
    echo Assemblierung abgebrochen

    :ende
 
Wi bentze f Interrupt-Handle COM-Dateie anstell vo EXE-
Dateien Da vereinfach de Kod un is auc schneller 
.pa
Debugging
=========
Di schwierigst Sach is aber de Interrupt-Handle berhaup zu 
Laufe z bringen E is j ei neue Bestandtei de Betriebssys
tems Klein Fehle i Tastatur-Treibe ode Video-Treibe wirke 
sic katastropha aus d da gesamt restlich Betriebssyste vo 
diese Programmteile abhngt 

Ein bereit beschrieben Techni is da Ersetze eine wenige 
lebenswichtige Interrupt-Vektor f di Phas de Fehlersuche 
Diese 'Umbiegen  de Vektor bedeute da 'sic Merken de alte 
Vektor un Einfgun eine Vektor au jene Programmteil de i 
di Routin eingesetz werde soll De Abschlu diese Programm 
is dan wiede ei Sprun au de alte Vektor 

Ein zweit wichtig Technik insbesonder be lngere Interrupt-
Handlern is da Teste vo Programmteile ohn de Interrupt-
Vekto umzubiege un diese Programmtei ers nac de Teste dor 
einzufgen Da heit zuers ei gewhnliche Program schreiben 
welche de z testende Programmtei enthlt (da Testprogram 
kan auc de Einfachhei halbe ei PASCAL-Program sein).

Zu Illustratio werde hie zwe Testprogramm vorgestellt di 
beid de Include-Modu HEX. bentzen 

VEKTOR.PAS
----------
Da erst Testprogram wurd scho weite vorn dargestell un 
zeig de Wer de Interruptvektoren Vergleiche Si di List mi 
de Anfangswerte  bei Hochfahre un vielleich auc nac de 
Installatio eine Hintergrundprogramm (z.b SIDEKICK) Da Pro
gram  is ntzlic u di Wirkun de Vektor'biegens besse kon
trolliere z knnen.

TEST.PAS
--------
Zeig de Zustan de Prozessor-Registe vo un nac Anwendun de 
z testende Interrupts 
.fi elite
(*****************************************************************************)
program   Interrupt_Handler_Test_Program;
(*****************************************************************************)
const
     INTERRUPT=$16; (* Der Interrupt der getestet wird *)
type
(*
     Der folgende Variante-Record repraesentiert die
     8088-Register und erlaubt das lesen oder Schreiben
     der Register A-D in Worten oder Bytes
*)
     PC_Register=record
        case integer of
          1: (AX,BX,CX,DX,BP,DI,SI,DS,ES,FLAGS:integer);
          2: (AL,AH,BL,BH,CL,CH,DL,DH:byte);
        end;
     HexWort = string (.4.);  (* 4-Zeichen-String fuer den HEX-konverter *)
var
     Register : PC_Register; (* Record fuer den DOS-Aufruf *)
.fi schoen
.pa
.fi elite
(*$I HEX.P *)

procedure ZeigeRegister;
begin
     WriteLn;
     Write (' AX:',Hex(Register.AX));
     Write (' BX:',Hex(Register.BX));
     Write (' CX:',Hex(Register.CX));
     Write (' DX:',Hex(Register.DX));
     Write (' BP:',Hex(Register.BP));
     Write (' DI:',Hex(Register.DI));
     Write (' DI:',Hex(Register.DI));
     Write (' DS:',Hex(Register.DS));
     Write (' ES:',Hex(Register.ES));
     WriteLn;
     (* Anzeigen der Zustands-Bits *)
     if ((Register.flags and $0001)>0) then Write (' CF');
     if ((Register.flags and $0004)>0) then Write (' PF');
     if ((Register.flags and $0010)>0) then Write (' AF');
     if ((Register.flags and $0040)>0) then Write (' ZF');
     if ((Register.flags and $0080)>0) then Write (' SF');
     if ((Register.flags and $0100)>0) then Write (' TF');
     if ((Register.flags and $0200)>0) then Write (' IF');
     if ((Register.flags and $0400)>0) then Write (' DF');
     if ((Register.flags and $0800)>0) then Write (' OF');
     WriteLn;
end;

procedure TestKode0;
(* 
    Warten auf ein Zeichen, Lesen eines Zeichens
    Lesen durch Interrupt mit dem richtigen Funktions-Kode.
    Der Zustand der Register wird vor und nach dem Interrrupt angezeigt.
*)
   var
     C    : byte;
   begin
     C := 0;
     while (c<>3)   (* Ausstieg mit Control C *)  do begin
          Register.AH := 0;  (* Funktions-Kode setzen *)
          Register.AL := 0;  (* Alle anderen Register 0 setzen *)
          Register.BX := 0;  (* Damit Aenderungen sichtbar werden *)
          Register.CX := 0;
          Register.DX := 0;
          ZeigeRegister;
          Write ('Zeichen eingeben: ');
          intr (INTERRUPT,Register);   (* Interrupt ausfuehren *)
          ZeigeRegister;
          WriteLn ('Zeichen=(.',ord(Register.AL),'.)     (',chr(Register.AL),')');
          WriteLn ('-------');
          C := Register.AL;
     end;
   end;

begin     (* Hauptprogramm *)
     TestKode0;
end.
.fi schoen
.pa
Eine Weiterentwicklung des einfachen Tastaturmanipulators
=========================================================
Da Assembler-Program LETZT.AS zeig ein sinnvoll Erweiterun 
de kleine Demoprogramm TRIVIAL.ASM Da Program behl sic ein 
Kopi de letzte eingegebene Kommando vo de Konsol i 'Altz
eilen' Bei Drcke de Tastenkombinatio CTRL-'\ wiederhol sic 
au de Konsol de zuletz eingegeben Befeh ei Zeiche nac de 
anderen Ein hnlich Funktio ha auc di Tast F i DOS-Be
triebssystem Hie sehe Si etw wi si funktioniert Be de 
deutsche Tastature is di Tasten-Kombinatio CTRL-'\ nich er
reichbar Gebe Si anstell ALT-28-AL ein 
.fi elite
;letzt.asm

;Speicherung der letzten Eingabezeile
;Wiederholung der Zeile buchstabenweise
;beim Drcken von  CTRL-\ (ALTein-28-ALTaus)

          PAGE  58,132

;Definition von Konstanten

V_Tastatur            equ  16h  ;Nummer des Tastatur-Interrupts
DOS_Funktion          equ  21h  ;DOS-Interrupt-Nummer
DOS_resident_bleiben  equ  27h  ;Beenden und resident lassen
DOS_hole_Vektor       equ  35h  ;DOS-Funktionsnummer fr Vektor holen
DOS_setz_Vektor       equ  25h  ;DOS-Funktionsnummer fr Vektor setzen
;
CSEG SEGMENT
     assume    cs:cseg,ds:cseg     ;Mitteilungen an MASM
     org  100H                     ;alle .COM-Dateien beginnen bei 100H
;
start:
     jmp  Initialisierung
;
;hier beginnt der Kode fr die eigentliche Anwendung;

Alter_Tastatur_Vektor_W  LABEL WORD
Alter_Tastatur_Vektor_D  dd 0 ;alter Tastatur-Vektor
;
AltZeil   db   80 dup(0)      ;Alte Eingabezeile
          dw   0              ;Zeilenabschlu
NeuZeil   db   80 dup(0)      ;Neue Eingabezeile
          dw   0              ;Zeilenabschlu
AltZeig   dw   0              ;Zeiger auf AltZeil
NeuZeig   dw   0              ;Zeiger auf NeuZeil
;
.fi schoen
.pa
.fi elite
Tastatur_Manipulator     proc far
     assume    cs:cseg,ds:cseg     ;Mitteilungen an den Assembler
     sti                           ;Interrupts einschalten
     push ds                       ;Retten der Register,
     push bx                       ;die in diesem Programmteil
     push di                       ;verwendet werden
     mov  bx,cs                    ;Datensegment=Kode-Segment
     mov  ds,bx
     cmp  ah,0                     ;wird gelesen (ah=0)?
     jne  ki1                      ;wenn nicht, benutze das ROM
;
;simuliere einen Interrupt-Aufruf zum alten Keyboard I/O-Handler
;
ki:  pushf                         ;Flaggen auf den Stapel
     assume    ds:nothing          ;
     call Alter_Tastatur_Vektor_D  ;benutzen des alten Keyboard-Handlers
     cmp  al,28                    ;suche CTRL-\
     je   ki3
     cmp  al,8                     ;suche Backspace
     je   ki4
     cmp  al,13                    ;suche Wagenrcklauf
     jne  ki0
;
;nach Wagenrcklauf zeigen auf den Beginn des Eingabe-Puffers
;
ki00:     assume    ds:cseg
     push si                       ;benutzte Register retten
     push di
     push cx
     push ax
     push es
     mov  si,ds                    ;Source-Segment in DS
     mov  es,si                    ;Zielsegment in ES
     mov  si,offset NeuZeil        ;Quell-Offset in SI
     mov  di,offset AltZeil        ;Ziel Offset in DI
     mov  bx,NeuZeig               ;Input-String mit 0 abschlieen
     mov  byte ptr[si+bx],0
     mov  cx,80                    ;Anzahl der Wiederholungen in CX
     rep  movsb                    ;verschiebe Byte-String
     pop  es                       ;Register wiederherstellen
     pop  ax
     pop  cx
     pop  di
     pop  si
ki02:
     mov  AltZeig,0                ;Pointer rcksetzen
     mov  NeuZeig,0
     jmp  ki01

.fi schoen
.pa
.fi elite
;
;Zeichen in den Einlese-Puffer geben
;
ki0: assume    ds:cseg
     mov  di,offset NeuZeil        ;benutze Input-Puffer
     mov  bx,NeuZeig               ;nchster leerer Platz
     cmp  bx,80                    ;nicht mehr als 80 Zeichen
     jg   ki01
     mov  [di+bx],al               ;wenn weniger als 80 Zeichen,
                                   ;addiere Zeichen
     inc  NeuZeig                  ;und erhhe Zeiger
;
;Rckkehr vom Interrupt nach Wiederherstellung der Register
;
ki01:
     pop  di
     pop  bx
     pop  ds
     iret
;
;die ROM-Routine macht alles inklusive die Rckkehr vom Interrupt
;
ki1: pop  di
     pop  bx
     pop  ds
     assume    ds:nothing          ;alle Annahmen lschen (wichtig)
     jmp  Alter_Tastatur_Vektor_D
;
;sende das nchste Byte eines String so,
;als wre es von der Tastatur eingegeben worden
;
ki3: assume    ds:cseg
     mov  di,offset AltZeil   ;bentze den Ausgabe-Puffer
     mov  bx,AltZeig          ;zeige auf nchstes zu sendendes Zeichen
     mov  al,[di+bx]          ;Zeichen in AL
     cmp  al,0                ;Wurde der Puffer bentzt?
     je   ki01                ;wenn ja, kehre mit 0 zurck
     inc  AltZeig             ;wenn nicht, erhhe Zeiger
     jmp  ki0
;
;das Zeichen Backspace wird nicht gespeichert,
;erniedrige Pointer um 1, wenn er nicht 0 ist
;
ki4: assume    ds:cseg
     cmp  NeuZeig,0                ;Ist der Puffer ler?
     je   ki01                     ;Wenn ja, kehre zurck
     dec  NeuZeig                  ;Erniedrige Zeiger
     jmp  ki01                     ;und kehre zurck

Tastatur_Manipulator     endp
;
;hier endet der Anwender-Kode
;
.fi schoen
.pa
.fi elite
Initialisierung:
     mov  bx,cs                    ;DSEG=CSEG
     mov  ds,bx
;
;hole den alten Tastatur-Vektor und bertrage ihn in Variable
;
     mov  al,V_Tastatur            ;die Vektornummer, die wir brauchen
     mov  ah,DOS_hole_Vektor       ;DOS-Funktionsnummer zum Holen 
                                   ;des Vektors
     int  DOS_Funktion             ;Ausfhrung
     mov  Alter_Tastatur_Vektor_W,bx       ;alter Vektor in ES:BX
     mov  Alter_Tastatur_Vektor_W[2],es    ;Variable speichern
;
;setze den Tastatur-Vektor auf die Ausgabe-Routine
;
     mov  bx,cs                    ;die DOS-Funktion erwartet 
                                   ;den Vektor in DS:DX
     mov  ds,bx                    ;Manipulator-SEG:OFS wird hier abgelegt
     mov  dx,offset Tastatur_Manipulator
     mov  al,V_Tastatur            ;DOS-Funktion zum Setzen des Vektors
     mov  ah,DOS_setz_Vektor            ;
     int  DOS_Funktion             ;Ausfhrung
     mov  bx,cs                    ;
     mov  ds,bx
     mov  dx,offset Initialisierung
     int  DOS_resident_bleiben
;
CSEG ENDS
     END start
.fi schoen
.pa
Drucker-Treiber
===============

Jede a de Drucke gesendete Zeiche kan mittel de hie 
abgedruckte Program DRIVER.AS͠ durc ei andere Zeiche ode 
durc ein Folg vo Zeiche ersetz werden Als zu Beispie dann 
wen ei Drucke verwende werde soll de nich gan de IBM-
Zeichensat entspricht Da Program is f all Anwendunge 
geeignet di f di Druckerausgab de Interrup 17 verwenden.

Ei Zeiche kan i ein Zeichenreih (max 14 umgewandel werden 
Besonder vorteilhaf is diese Treibe f di Ansteuerun vo 
Typenradschreibmaschinen.

De Treibe is residen un wir a beste i durc da AUTOEXEC-
Fil geladen.

  DRIVER.ASM, DRIVER1.ASM : Treiber mit Tabelle fr Triumph-Adler
                            1020B mit Dreusicke-Schnittstelle PCU102

  TEST.TXT                : Testtext, ASCII-File
  TESTXT.BAS, TESTXT1.BAS, 
  TESTXT2.BAS             : BASIC-Programme fr Zeichen-
                            satzgenerierung.

TEST.TXT
     abcdefghijklmnopqrstuvwxyz
     ABCDEFGHIJKLMNOPQRSTUVWXYZ
       !"$%&/()=?`'
     #^+*-_:.;,

TESTXT.BAS
     10 FOR I=32 TO 255
     15 PRINT CHR$(I);
     20 LPRINT CHR$(I);
     30 NEXT
     35 PRINT
     40 LPRINT
     50 GOTO 10
     
TESTXT1.BAS
     10 FOR I=32 TO 255 STEP 4
     15 PRINT I,CHR$(I),,I+1,CHR$(I+1),,I+2,CHR$(I+2),,I+3,CHR$(I+3)
     20 LPRINT I,CHR$(I),,I+1,CHR$(I+1),,I+2,CHR$(I+2),,I+3,CHR$(I+3)
     30 NEXT
     35 PRINT
     40 LPRINT
     50 STOP
     
TESTXT2.BAS
     10 FOR I=32 TO 255 STEP 4
     15 PRINT I;CHR$(I),I+1;CHR$(I+1),I+2;CHR$(I+2),I+3;CHR$(I+3)
     20 LPRINT I;CHR$(I),I+1;CHR$(I+1),I+2;CHR$(I+2),I+3;CHR$(I+3)
     30 NEXT
     35 PRINT
     40 LPRINT
     50 STOP
.pa
.fi elite
;****************************************************
;***     UNIVERSAL  PRINTER  DRIVER               *** Dateiname : DRIVER.ASM
;****************************************************
;
driver  segment word
        org     100h
        assume  cs:driver,ds:driver,es:driver
;
newpr   equ     80h     ;nummer des neuen bios-vectors  17h ---> 80h
r       equ     10h     ;zahl der bytes fr jeden buchstaben
esc     equ     27
mark    equ     255     ;ende markierung fr die ausgabe
;
start   proc    near
;
        mov     al,17h          ;hole wert des alten 17h-vector
        mov     ah,35h
        int     21h
        mov     al,newpr        ;setze diese auf den neuen vector
        mov     ah,25h
        mov     dx,bx
        push    es
        pop     ds
        int     21h
        mov     ah,25h          ;richte den neuen 17h-vector ein
        mov     al,17h          ;dieser zeigt nun auf die untere
        push    cs              ;routine, die fr die Ausgabe an den
        pop     ds              ;drucker den 80h-vector benutzt.
        mov     dx,offset newr
        int     21h
        mov     dx,offset ende  ;mache neuen bios-interrupt resident
        int     27h
;
newr:   push    si              ;rette die zwei benutzten register
        push    ds
        push    cs              ;setze DS auf aktuelles CS
        pop     ds
        cmp     ah,0            ;befehldcode fr zeichenausgabe ?
        jne     normal          ;nein: dann fhre INT normal aus
        mov     si,offset nc    ;ja: dann beginne mit berprfung
l1:     cmp     al,[si]         ;byte in tabelle = auszudruckendes z.?
        je      print           ;ja: dann verzweige in druckroutine
        add     si,r            ;ansonsten suche weiter in der tabelle
        cmp     si,offset ende  ;ende der tabelle ?
        jna     l1              ;nein: dann weitersuchen
        jmp     normal          ;ja: dann normal ausdrucken
;
print:  inc     si              ;setze si auf zielbyte in tabelle
        mov     ah,0            ;setze ah=0 fr druck
        mov     al,[si]         ;hole zu druckendes byte
        cmp     al,mark         ;endmarkierung erreicht ?
        je      ready           ;ja: dann erledigt
        int     newpr           ;nein: drucke byte aus
        jmp     print           ;wiederhole vorgang erneut
normal: int     newpr           ;normale ausfhrung des INTs
ready:  pop     ds              ;hole benutzte register
        pop     si
        iret                    ;zurck zum aufrufer
.fi schoen
.pa
.fi elite
; tabelle fr die neuen zeichen:  das erste zeichen jeder datenzeile
; stellt das zeichen dar, das durch die nachfolgende bytesequenz bis
; mark ersetzt wird. diese tabelle wird hier fr den "normalfall" an-
; gegeben, wobei die umlaute und sonderzeichen des ibm pc in die
; gewohnten klammern und slashes des ascii-zeichensatzes verwandelt
; werden. so kann man texte mit herkmmlichen druckern drucken, indem
; diese auf deutschen zeichensatz umgeschaltet werden. zu beachten ist, 
; da der PCcounter immer auf volle 16 byte ( = r ) eingestellt wird.

        org    150h                     ; setze pc auf paragraph
nc:     db     01h,20h,mark               org    nc+r*24                     
        org    nc+r*1                     db     5bh,4ch,08h,14h,2dh,12h,mark
        db     02h,20h,mark               org    nc+r*25                     
        org    nc+r*2                     db     5ch,20h,mark                
        db     03h,20h,mark               org    nc+r*26                     
        org    nc+r*3                     db     5dh,4ah,08h,14h,2dh,08h,    
        db     04h,20h,mark                      12h,12h,2dh,14h,mark        
        org    nc+r*4                     org    nc+r*27                     
        db     05h,20h,mark               db     7bh,28h,08h,3ch,mark        
        org    nc+r*5                     org    nc+r*28                     
        db     06h,20h,mark               db     7ch,20h,mark                
        org    nc+r*6                     org    nc+r*29                     
        db     0eh,20h,mark               db     7dh,29h,08h,3eh,mark        
        org    nc+r*7                     org    nc+r*30                     
        db     0fh,20h,mark               db     7eh,5eh,08h,27h,32h,mark    
        org    nc+r*8                     org    nc+r*31                     
        db     10h,20h,mark               db     80h,40h,mark                
        org    nc+r*9                     org    nc+r*32                     
        db     11h,20h,mark               db     81h,7dh,mark                
        org    nc+r*10                    org    nc+r*33                     
        db     12h,20h,mark               db     82h,27h,65h,mark            
        org    nc+r*11                    org    nc+r*34                     
        db     13h,20h,mark               db     83h,5eh,08h,61h,mark        
        org    nc+r*12                    org    nc+r*35                     
        db     14h,20h,mark               db     84h,7bh,mark                
        org    nc+r*13                    org    nc+r*36                     
        db     15h,40h,mark               db     85h,60h,61h,mark            
        org    nc+r*14                    org    nc+r*37                     
        db     16h,20h,mark               db     86h,1bh,44h,08h,61h,mark    
        org    nc+r*15                    org    nc+r*38                     
        db     17h,20h,mark               db     87h,63h,08h,2eh,mark        
        org    nc+r*16                    org    nc+r*39                     
        db     18h,20h,mark               db     88h,5eh,08h,65h,mark        
        org    nc+r*17                    org    nc+r*40                     
        db     19h,20h,mark               db     89h,65h,08h,22h,mark        
        org    nc+r*18                    org    nc+r*41                     
        db     1ah,20h,mark               db     8ah,60h,65h,mark            
        org    nc+r*19                    org    nc+r*42                     
        db     1ch,20h,mark               db     8bh,69h,mark                
        org    nc+r*20                    org    nc+r*43                     
        db     1dh,20h,mark               db     8ch,5eh,08h,69h,mark        
        org    nc+r*21                    org    nc+r*44                     
        db     1eh,20h,mark               db     8eh,5bh,mark                
        org    nc+r*22                    org    nc+r*45                     
        db     1fh,20h,mark               db     8fh,1bh,44h,08h,41h,mark    
        org    nc+r*23
        db     40h,43h,08h,14h,   
               61h,12h,mark ;Fortsetzung rechts oben
.fi schoen
.pa
.fi elite
        org    nc+r*46                          org    nc+r*72      
        db     90h,27h,45h,mark                 db     0abh,20h,mark
        org    nc+r*47                          org    nc+r*73      
        db     91h,20h,mark                     db     0ach,20h,mark
        org    nc+r*48                          org    nc+r*74      
        db     92h,20h,mark                     db     0adh,69h,mark
        org    nc+r*49                          org    nc+r*75      
        db     93h,5eh,08h,6fh,mark             db     0aeh,20h,mark
        org    nc+r*50                          org    nc+r*76      
        db     94h,7ch,mark                     db     0afh,20h,mark
        org    nc+r*51                          org    nc+r*77      
        db     95h,60h,6fh,mark                 db     0b0h,20h,mark
        org    nc+r*52                          org    nc+r*78      
        db     96h,5eh,08h,75h,mark             db     0b1h,20h,mark
        org    nc+r*53                          org    nc+r*79      
        db     97h,60h,75h,mark                 db     0b2h,20h,mark
        org    nc+r*54                          org    nc+r*80      
        db     98h,79h,08h,22h,mark             db     0b3h,20h,mark
        org    nc+r*55                          org    nc+r*81      
        db     99h,5ch,mark                     db     0b4h,20h,mark
        org    nc+r*56                          org    nc+r*82      
        db     9ah,5dh,mark                     db     0b5h,20h,mark
        org    nc+r*57                          org    nc+r*83      
        db     9bh,63h,08h,49h,mark             db     0b6h,20h,mark
        org    nc+r*58                          org    nc+r*84      
        db     9ch,1bh,56h,mark                 db     0b7h,20h,mark
        org    nc+r*59                          org    nc+r*85      
        db     9dh,59h,08h,3dh,mark             db     0b8h,20h,mark
        org    nc+r*60                          org    nc+r*86      
        db     9eh,50h,74h,mark                 db     0b9h,20h,mark
        org    nc+r*61                          org    nc+r*87      
        db     9fh,66h,mark                     db     0bah,20h,mark
        org    nc+r*62                          org    nc+r*88      
        db     0a0h,27h,61h,mark                db     0bbh,20h,mark
        org    nc+r*63                          org    nc+r*89      
        db     0a1h,27h,69h,mark                db     0bch,20h,mark
        org    nc+r*63                          org    nc+r*90      
        db     0a2h,27h,6fh,mark                db     0bdh,20h,mark
        org    nc+r*64                          org    nc+r*91      
        db     0a3h,27h,75h,mark                db     0beh,20h,mark
        org    nc+r*65                          org    nc+r*92      
        db     0a4h,5eh,08h,27h,                db     0bfh,20h,mark
               32h,08h,6eh,mark                 org    nc+r*93      
        org    nc+r*66                          db     0c0h,20h,mark
        db     0a5h,5eh,08h,27h,                org    nc+r*94      
               32h,08h,4eh,mark                 db     0c1h,20h,mark
        org    nc+r*67                          org    nc+r*95      
        db     0a6h,61h,08h,5fh,mark            db     0c2h,20h,mark
        org    nc+r*68                          org    nc+r*96      
        db     0a7h,6fh,08h,5fh,mark            db     0c3h,20h,mark
        org    nc+r*69                          org    nc+r*97      
        db     0a8h,20h,mark                    db     0c4h,20h,mark
        org    nc+r*70                          org    nc+r*98      
        db     0a9h,20h,mark                    db     0c5h,20h,mark
        org    nc+r*71
        db     0aah,20h,mark

        ; Fortsetzung rechts oben
.fi schoen
.pa
.fi elite
        org    nc+r*99             org    nc+r*127               
        db     0c6h,20h,mark       db     0e2h,20h,mark          
        org    nc+r*100            org    nc+r*128               
        db     0c7h,20h,mark       db     0e3h,20h,mark          
        org    nc+r*101            org    nc+r*129               
        db     0c8h,20h,mark       db     0e4h,20h,mark          
        org    nc+r*102            org    nc+r*130               
        db     0c9h,20h,mark       db     0e5h,20h,mark          
        org    nc+r*103            org    nc+r*131               
        db     0cah,20h,mark       db     0e6h,1bh,43h,mark      
        org    nc+r*104            org    nc+r*132               
        db     0cbh,20h,mark       db     0e7h,20h,mark          
        org    nc+r*105            org    nc+r*133               
        db     0cch,20h,mark       db     0e8h,6fh,08h,49h,mark  
        org    nc+r*106            org    nc+r*134               
        db     0cdh,20h,mark       db     0e9h,4fh,08h,2dh,mark  
        org    nc+r*107            org    nc+r*135               
        db     0ceh,20h,mark       db     0eah,20h,mark          
        org    nc+r*108            org    nc+r*136               
        db     0cfh,20h,mark       db     0ebh,53h,08h,6fh,mark  
        org    nc+r*109            org    nc+r*137               
        db     0d0h,20h,mark       db     0ech,1bh,4fh,6fh,6fh,  
        org    nc+r*110                   1bh,4fh,mark           
        db     0d1h,20h,mark       org    nc+r*138               
        org    nc+r*111            db     0edh,6fh,08h,2fh,mark  
        db     0d2h,20h,mark       org    nc+r*139               
        org    nc+r*112            db     0eeh,20h,mark          
        db     0d3h,20h,mark       org    nc+r*140               
        org    nc+r*113            db     0efh,20h,mark          
        db     0d4h,20h,mark       org    nc+r*141               
        org    nc+r*114            db     0f0h,20h,mark          
        db     0d5h,20h,mark       org    nc+r*142               
        org    nc+r*115            db     0f1h,2bh,08h,1bh,39h,  
        db     0d6h,20h,mark              2dh,1bh,38h,mark       
        org    nc+r*116            org    nc+r*143               
        db     0d7h,20h,mark       db     0f2h,3eh,08h,1bh,39h,  
        org    nc+r*117                   2dh,1bh,38h,mark       
        db     0d8h,20h,mark       org    nc+r*144               
        org    nc+r*118            db     0f3h,3ch,08h,1bh,39h,  
        db     0d9h,20h,mark              2dh,1bh,38h,mark       
        org    nc+r*119            org    nc+r*145               
        db     0dah,20h,mark       db     0f4h,20h,mark          
        org    nc+r*120            org    nc+r*146               
        db     0dbh,20h,mark       db     0f5h,20h,mark          
        org    nc+r*121            org    nc+r*147               
        db     0dch,20h,mark       db     0f6h,3ah,08h,2dh,mark  
        org    nc+r*122            org    nc+r*148               
        db     0ddh,20h,mark       db     0f7h,20h,mark          
        org    nc+r*123            org    nc+r*149               
        db     0deh,20h,mark       db     0f8h,1bh,44h,mark      
        org    nc+r*124            org    nc+r*150               
        db     0dfh,20h,mark       db     0f9h,20h,mark          
        org    nc+r*125            org    nc+r*151               
        db     0e0h,20h,mark       db     0fah,1bh,38h,2eh,      
        org    nc+r*126                   1bh,39h,mark           
        db     0e1h,7eh,mark
.fi schoen
.pa
.fi elite        
        org    nc+r*152
        db     0fbh,20h,mark
        org    nc+r*153
        db     0fch,1bh,40h,mark
        org    nc+r*154
        db     0fdh,1bh,41h,mark
        org    nc+r*155
        db     0feh,20h,mark
;
ende    db     0
;
start   endp
driver  ends
        end start

.fi schoen
Verwendete Literatur
--------------------

Tom Wadlov, Writing Desk Accessories
BYTE, 1985, Inside the IBM-PCs.

Au diese Verffentlichun stamme di Interruptdemo be di 
Tastatur Si wurde au Funktio geprf un sin i Source-Kod 
au de TGM-Diskette enthalten 

SCHMIDT, IBM-BIOS-Funktionen
MC 6/86, S.40

I diese Verffentlichun finde Si ein bersichtlich Dars
tellun de BIOS-Funktione mi de jeweilige List de ber
gabe-Parameter.

K.Werner, PC-DOS-Interrupts
c't 85/9, S.112
   I diese Verffentlichun finde si ei Aufstellun be all 
PC-DOS Interrupts und die Funktionsnummern des Interrupt 21H.

H. Groauer, Ein 'X' frn 'U'?
c't 6/86, S.66
   Au diese Verffentlichun stamm da Beispie f de Drucker
   treibe 


I eine de nchste Ausgabe de PCNEW finde Si Beispiel f 
Einheitentreiber.
.pa
