gfx gfx
gfx
homegfxgaestebuchgfxforumgfxkontaktgfximpressum
gfx
QBasic
  1. QB-Forum
  2. QB-Forum
  QB-MonsterFAQ
  Tutorials
AK-LIB
  Download
  Archiv
  Hilfe
  TroubleFAQ
  Tools
Projekte
  DosFont
Extras
  Links
Statistik
Tutorials
Interrupte in Qbasic
Autor: Andre Klein

       Abschnitt 1   Was ist ein Interrupt?
Ein Interrupt (zu deutsch Unterbrecher, oft mit INT abgekürzt) ist eine Art Unterprogramm das im Speicher liegt und je nachdem mit welchen Optionen er aufgerufen wird, seine Aufgabe verrichtet und danach wieder zum aufrufenden Programm zurückkehrt.
Vorgehensweise:
- Der Prozessor führt ein Programm aus (kann auch ein QB-Programm sein!).
- Ein Interrupt wird aufgerufen.
- Der Prozessor UNTERBRICHT jetzt das aktuell laufende Programm und führt das Programm aus, das der Interrupt besitzt
- Wenn er fertig ist dann lässt er den Prozessor wieder mit dem Programm weitermachen bei dem er war!

Im Grunde genommen kann man einen Interrupt wie eine SUB-Sammlung für eine bestimmte Aufgabe ansehen.
Insgesamt gibt es 256 verschiedene Interrupte. Also ist jeder Interrupt mit einer bestimmten Nummer gekennzeichnet. Diese Nummer wird meistens in HEX angegeben und ergibt für die Interrupte einen Bereich von &H00-&HFF.
Woher weiß der Prozessor wo sich diese Programme befinden?
Am Anfang des Speichers beim SEGMENT &H0000 und dem OFFSET &H0000 befindet sich eine INT-Tabelle in der alle SEGMENT&OFFSET-Positionen der einzelnen Interrupte eingetragen sind. Jeder Eintrag hat 4 Byte.

       Abschnitt 2   Was ist der Unterschied zwischen INT und IRQ?
Als IRQ (Hardware-Interrupt) werden alle Interrupte bezeichnet die die NUMMER &H00 bis &H0F haben und direkt von einer Hardware aufgerufen werden.
einige dieser IRQ-Nummern wurden für bestimmte Hardware als Standart festgelegt!
hier einige Beipiele:

INT &H00 - ist ein Interrupt der vom Prozessor erstellt wird wenn er durch 0 teilen soll. (ist ja mathematisch verboten). Dieser Interrupt "fängt" dann diesen Fehler ab und korigiert ihn. Sonst würde der Prozessor abstürzen.

INT &H06 - wird aufgerufen wenn der Prozessor einen falschen Befehl ausführen soll. Befehls-Unterschiede kommen durch PROTECTED MODE und REAL-MODE zustande.

INT &H08 - SYSTEM TIMER - dieser INT wird 18.2 mal pro Sekunde von dem Uhrenchip auf dem MainBoard aufgerufen. Dieser Interrupt erhöht bei jedem Aufruf einen Zähler im Speicher der sich im SEGMENT &H40 am OFFSET &H6C-&H6F befindet.

INT &H09 - Tastatur-INT - jedesmal wenn man auf der Tastatur eine Taste drückt wird dieser INT aufgerufen. Das Programm welches sich dort befindet speichert die gedrückte Taste im sogenannten TASTATURPUFFER. Dieser befindet sich im SEGMENT &H40 am OFFSET &H1E und ist 32 Byte lang.

Nun zu INT
als INT (Software-Interrupt) werden alle Interrupte bezeichnet die eine Nummer von &H10 bis &HFF haben.

       Abschnitt 3   Wofür braucht man das?
Nehmen wir als Beispiel mal die MAUS. Wie du sicherlich weißt gibt es mittlerweile hunderte Anbieter von solchen "Geräten". Und die meisten von diesen Geräten werden mit komplett anderen Befehlen angesteuert und abgefragt.
Und stell dir jetzt mal vor du bist ein Programmierer der in seinem Programm eine Maussteuerung einbauen möchte. Normalerweise müßtest du für ALLE MÄUSE die es auf dem Markt gibt eine andere Routine in dein Programm einbauen damit das ganze funktioniert. Und das ist ein unmögliches Unterfangen da ja immer wieder neue Mäuse hergestellt werden.
Also braucht man eine einheitliche SOFTWARE-Schnittstelle. Und das wäre in diesem Fall der MAUS-Interrupt. Wenn der Maustreiber installiert wird legt er automatisch diesen Interrupt an. Wenn man ihn mit der entsprechenden Option/Funktionsnummer aufruft dann führt er genau das aus was du brauchst. z.B. Funktion "0" würde heißen: "Maustreiber korrekt installiert?". oder eine andere Funktion würde z.B. sein: "Wie sind deine jetzigen Koordinaten?".
Und diese Funktionsnummern sind IMMER gleich. Das heißt das der Maustreiber, je nachdem welche Funktion aufgerufen wird, die Maus richtig ansteuert. Also die Arbeit die man, wie oben erwähnt, selber machen müßte.
Man hat sich auch geeinigt diesen MAUS-Interrupt immer auf dieselbe INT-Nummer zu legen. Und zwar &H33. Wenn du dir schon mal Qbasic-Mausroutinen angeschaut hast, wirst du diese Nummer vieleicht schon mal endeckt haben.
Dazu ist noch zu sagen das &H33 für MICROSOFT-Betriebssysteme gilt. Also DOS & WINDOWS. Ob bei LINUX z.B. auch die gleichen Nummern gelten, weiß ich NICHT!
Das was für die MAUS gilt, gilt natürlich auch für ALLE anderen GERÄTE in und an deinem PC. z.B GRAFIK-KARTEN, SOUNDKARTEN, SCHNITTSTELLEN, UHREN, FESTPLATTEN usw usw...
Jetzt ist es so, das das BIOS schon grundsätzliche Interrupte zur Verfügung stellt. z.B. für Floppy-Zugriffe, Harddiskzugriffe, Tastatur und noch andere. Alle BIOS-Interrupte liegen im INT-NUMMER-Bereich von &H10 bis &H1F. Auf diese Routinen werde ich später noch eingehen.

       Abschnitt 4   Wie rufe ich einen Interrupt von QB aus auf?
Um ein INT von QB aus aufzurufen gibt es mehrere Möglichkeiten. Zum ersten INDIREKT über CALL ABSOLUTE und zum zweiten DIREKT mit CALL INTERRUPT oder CALL INTERRUPTX.
Im folgen werde ich erklären wie es mit CALL INTERRUPTX geht.
Dazu brauchst du mindestens QB V4.0 und mußt QB mit der Option /L starten. Also QB /L
siehe: Was ist eine Bibliothek?
Es ist ganz wichtig das das nun folgende am Anfang eines jeden Programmes stehen muß was ich hier beschreibe. Ich schreibe es hier nur einmal hin und setze dann voraus das es vor jedem Beipielprogramm schon geschrieben wurde.
TYPE regtypex
ax AS INTEGER
bx AS INTEGER
cx AS INTEGER
dx AS INTEGER
bp AS INTEGER
si AS INTEGER
di AS INTEGER
flags AS INTEGER
ds AS INTEGER
es AS INTEGER
END TYPE
DIM SHARED reg AS regtypex

Die gebrauchten Variablen heißen danach reg.ax, reg.bx usw. Das sind die REGISTER/VARIABELN mit denen der PROZESSOR arbeiten. Für weitere Informationen über REGISTER siehe: Was ist Assembler?
Mit diesen Variabeln werden die Werte/Funktionen an den Interrupt übertragen.
kurze Erklärung:
die normalen Register unterteilt man in zwei Bereiche. Den LOW und den HIGH-Bereich. Der entsprechende Bereich wird durch ein L oder ein H gekennzeichnet.
Das Register AX wird in AH und AL unterteilt. AX ist ein 16-Bit-Register(INTEGER). Normalerweise werden Angaben für solche Register in HEX dargestellt.
Beipiel:
reg.ax = &HABCD
Das würde bedeuten das AH =&HAB ist und AL= &HCD. Diese Erklärung dient dazu die Beispielprogramme besser zu verstehen.
Die Umwandlung in AH und AL geschieht AUTOMATISCH und man braucht sich nicht darum kümmern.

       Abschnitt 5   1. Beispiel: Maustreiber installiert?

Mit dem folgenden Programm kann man überprüfen ob die Maus installiert ist oder nicht.
reg.ax = &H0000 wir wollen AX = Funktion 0 benutzen
CALL INTERRUPTX (&H33, reg, reg) Interrupt mit der Nummer &H33 aufrufen (Mausinterrupt) und die Register übergeben. Dadurch das AX = 0 ist, weiß der Interrupt das wir jetzt den Treiber-Status abfragen wollen.
IF reg.ax = &HFFFF THEN Die Register werden durch den Interrupt verändert und man kann durch sie die gewünschten Informationen erfahren. Wenn reg.ax = &HFFFF ist, dann ist der Maustreiber installiert!.
PRINT "Maus installiert!"
ELSE Wenn reg.ax was anderes ist, dann ist der Maustreiber NICHT installiert!
PRINT "Maus nicht installiert!"
END IF


       Abschnitt 6   2. Beispiel: Mauszeiger einschalten.

Mit dem folgenden Programm kann man den Mauszeiger einschalten. Damit das ein wenig spannender ist nehmen wir auch noch SCREEN 12 dazu.
SCREEN 12
reg.ax = &H0001 wir wollen AX = Funktion 1 benutzen
CALL INTERRUPTX (&H33, reg, reg) Interrupt mit der Nummer &H33 aufrufen (Mausinterrupt) und die Register übergeben. Dadurch das AX = 1 ist, weiß der Interrupt das wir jetzt den Mauszeiger einschalten wollen(also sichbar machen).
Und schon können wir mit der Maus über unseren Bildschirm fahren! Im Textmodus(SCREEN 0) würde er aus dem Zeiger einen Block machen.

       Abschnitt 7   3. Beispiel: Mauszeiger ausschalten.

Um den Mauszeiger auszuschalten muß reg.ax die Funktion 2 erhalten. Probiere es selber mal aus!!! So lernt man am schnellsten.

       Abschnitt 8   4. Beispiel. Mauskoordinaten herausfinden.

Mit dem folgenden Programm kann man die Koordinaten des Mauszeigers herausfinden. Rückgabewerte sind in Pixel-Angaben. Im Textmodus wird Zeile und Spalte zurückgegeben.
SCREEN 12
reg.ax = &H0003 wir wollen AX = Funktion 3 benutzen
CALL INTERRUPTX (&H33, reg, reg) Interrupt mit der Nummer &H33 aufrufen (Mausinterrupt) und die Register übergeben. Dadurch das AX = 3 ist, weiß der Interrupt das wir jetzt die Koordinaten des Mauszeigers haben wollen.
taste = reg.bx Der Mausinterrupt gibt in reg.bx die gedrückte Taste zurück. 0 = keine, 1 = links, 2 = rechts
x = reg.cx Der Mausinterrupt gibt in reg.cx die X-Koordinate zurück
y = reg.dx Der Mausinterrupt gibt in reg.dx die Y-Koordinate zurück

Wenn man diese Abfrage in eine Schleife packt und in jeder Schleife die Koordinaten mit LOCATE und PRINT anzeigen lässt. Dann kann man dauerhaft die Koordinaten ansehen.

       Abschnitt 9   5. Beispiel. Selbstversuche.
Der Mausinterrupt liefert noch weitere Funktionen. Um sie auszuprobieren schreibe ich dir hier die Funktionen auf und du versuchst sie im Programm aufzurufen (zum lernen und verstehen).

Mauszeiger positioneren:
EINGABE: INT 33, AX = 4, CX = X, DX = Y
AUSGABE: nichts

X-Bereich des Mauszeigers setzen:
EINGABE: INT 33, AX = 7, CX = Xmin, DX = Xmax
AUSGABE: nichts

Y-Bereich des Mauszeigers setzen:
EINGABE: INT 33, AX = 8, CX = Ymin, DX = Ymax
AUSGABE: nichts

Wenn das alles geklappt hat, dann hast du es schon verstanden!!!! Denn mehr ist es nicht. Im folgenden werde ich dir noch ein paar andere Interrupte vorstellen die du auch ausprobieren kannst.

       Abschnitt 10   BIOS-Interrupte.
Wie schon am Anfang erwähnt liefert das BIOS schon fertige Interrupte für Standartzugriffe auf Hard- und Software.
Die Interrupte haben die Nummern &H10 bis &H1F.
hier eine kurze Übersicht:
INT 10 - Grafik
INT 11 - Ausstattung des PC's
INT 12 - Speicher
INT 13 - Laufwerke
INT 14 - Serielle Schnittstellen
INT 15 - Kassette (veraltet)
INT 16 - Tastatur
INT 17 - Drucker
INT 18 - ROM BASIC
INT 19 - Boot-Vorgang einleiten
INT 1A - Uhrzeit
INT 1B - BREAK-Kontrolle
INT 1C - Timer Tick
INT 1D - Video-Parameter-Tabelle
INT 1E - Disketten-Parameter
INT 1F - Schrift-Art-Pointer

       Abschnitt 11   Der BIOS-Interrupt 16 (Tastatur).
jetzt picken wir uns mal den Tastatur-Interrupt heraus und spielen mal damit ein bischen rum!
Bei diesem INT schauen wir uns mal die 3 wichtigsten Unterfunktionen an.

Unterfunktion AH = &H0
Wenn man INT &H16 aufruft mit der Unterfunktion AH = &H0 dann wartet dieser Interrupt solange bis eine Taste gedrückt wird und liefert dann deren ASCII und SCANCODE zurück

EINGABE: INT 16, AH = 0
AUSGABE: wenn Taste gedrückt wird: AL = ASCII-Code des Zeichens, AH = SCANCODE des Zeichens
hier das Programm:
CLS
DO
reg.ax = &H0000 wir wollen AH = Funktion 0 benutzen
CALL INTERRUPTX (&H16, reg, reg) Interrupt mit der Nummer &H16 aufrufen (BIOS-Tastatur-Interrupt) und die Register übergeben. Dadurch das AH = 0 ist, weiß der Interrupt das wir jetzt solange warten wollen bis eine Taste gedrückt wird und er uns den ASCII-Wert des Zeichens zurückgibt
taste$ = CHR$(reg.ax AND 255) Der Tastaturinterrupt gibt in AL den ASCII-Code der gedrückten Taste zurück. Da wir aber nur AX zur Verfügung haben müßen wir AL erst herausfiltern. das macht man mit "AND 255"
scancode = FIX(reg.ax / 256) Der Tastaturinterrupt gibt in AH den SCAN-Code der gedrückten Taste zurück. Da wir aber nur AX zur Verfügung haben müßen wir AH erst herausfiltern. das macht man mit "FIX(reg.ax /256)"
LOCATE 1,1
PRINT taste$, scancode Jetzt noch das gedrückte anzeigen lassen
LOCATE 2,1: PRINT INT(RND*1000) Damit man sieht das die Schleife beim Interrupt wirklich wartet, schreiben wir hier eine Zufallszahl auf den Bildschirm.
LOOP UNTIL taste$ = CHR$(27) wenn taste$ = ESCAPE dann Schleife verlassen

So, jetzt kann man damit aber nicht wirklich ein Programm schreiben. Denn wenn man zum Beispiel Grafik-Animationen hat die auch in dieser Schleife ablaufen, dann verändert sich die Grafik nur dann wenn eine Taste gedrückt wird (Da der INT ja wartet).
Aber auch hierfür gibt es eine Lösung. Und zwar müßte man irgendwie herausfinden ob eine Taste gedrückt wurde und sie erst dann auslesen können.
Um herauszufinden ob eine Taste gedrückt wurde macht man folgendes:
reg.ax = &H0100 wir wollen AH = Funktion 1 benutzen
CALL INTERRUPTX (&H16, reg, reg) Interrupt mit der Nummer &H16 aufrufen (BIOS-Tastatur-Interrupt) und die Register übergeben. Dadurch das AH = 1 ist, weiß der Interrupt das wir jetzt wissen wollen ob eine Taste gedrückt wurde oder nicht
IF (reg.flags AND 64) = 0 THEN Wenn eine Taste gedrückt wurde wird das sogenannte ZERO-FLAG auf 0 gesetzt. Dieses befindet sich an BIT 6 von reg.flags und ist ein 1BIT-Register
hier kommt dann das Tastenauslesen mit Funktion 0 hin, wie im Beispiel oben beschrieben
END IF


Jetzt noch den Status der Sondertasten herausfinden. Sondertasten sind Shift, Alt usw.
reg.ax = &H0200 wir wollen AH = Funktion 2 benutzen
CALL INTERRUPTX (&H16, reg, reg) Interrupt mit der Nummer &H16 aufrufen (BIOS-Tastatur-Interrupt) und die Register übergeben. Dadurch das AH = 2 ist, weiß der Interrupt das wir jetzt den Sondertasten-Status wissen wollen
LOCATE 3,1 Der Status wird in AL zurückgegeben
'IF (reg.ax AND 1) = 1 THEN rechte Shift-Taste
'IF (reg.ax AND 2) = 2 THEN linke Shift-Taste
'IF (reg.ax AND 4) = 4 THEN STRG
'IF (reg.ax AND 8) = 8 THEN ALT
'IF (reg.ax AND 16) = 16 THEN Rollen
'IF (reg.ax AND 32) = 32 THEN NUM-Lock
'IF (reg.ax AND 64) = 64 THEN CAPS Lock
'IF (reg.ax AND 128) = 128 THEN Einfügen
Damit ist der Tastatur-INT erstmal abgeschlossen.

       Abschnitt 12   Microsoft-Interrupte (DOS/WIN)
Diese Interrupte haben die Nummern von &H20 bis &H2F.
kurze Übersicht:
&H20 - MS-CTRL-Interrupt für laufende Programme
&H21 - Wichtigster Interrupt mit den meisten allgemein verwendbaren Programmen
&H22 - Pointer zu dem das laufende Programm zurückspringt wenn es beendet wird
&H23 - CTRL-BREAK-Handler
&H24 - ERROR-Handler (z.B. Disk nicht bereit, Schreibfehler...)
&H25 - Absolutes Lesen von Laufwerk
&H26 - Absolutes Schreiben auf Laufwerk
&H27 - Terminate and Stay Resident (TSR)
&H28 - TSR-Programm-Ausführung während warten auf Benutzer-Eingabe
&H29 - Fast Console Output
&H2A - Netzwerk
&H2B - Reserviert für DOS > V6.00
&H2C - PROTECTED-MODE
&H2D - alternativer MULTIPLEX-Interrupt
&H2E - Direkter COMMAND.COM-Interpreter
&H2F - MULTIPLEX-Interrupt

Dazu ist noch zu sagen das der einzige Interrupt den man von diesen verwenden sollte der Interrupt &H21 ist!!!
Alle anderen Interrupte aus dieser Liste braucht DOS/WIN um sich selbst zu steuern. Und deshalb sollte man sie nur in Ausnahmefällen direkt benutzen!!!

       Abschnitt 13   Der Microsoft-Interrupt &H21.
Dieser Interrupt liefert (fast) alles was man als Programmierer braucht.
hier zwei Beispiele:
Taste lesen und auf den Bildschirm schreiben:
reg.ax = &H0100 wir wollen AH = Funktion 1 benutzen
CALL INTERRUPTX (&H21, reg, reg)

Buchstabe auf Bildschirm schreiben:
reg.ax = &H0200 wir wollen AH = Funktion 2 benutzen
reg.dx=ASC(a$) DL ist ASCII-Wert des Zeichens das geschrieben werden soll
CALL INTERRUPTX (&H21, reg, reg)

Natülich stellt dieser Interrupt noch sehr viele andere Funktionen bereit.

         Abschluss   letzte Aktualisierung: 13.07.2003
Alle anderen Interrupte ab &H30 (ausser &H33) stehen eigenen Programmen zur Verfügung. Aber wenn man einen von diesen benutzt dann sollte man irgendwo weiter hinten eine Nummer nehmen.
Wenn du spezielle Informationen zu einem bestimmten Interrupt suchst, dann findest du im Internet sehr viele Informationen dazu.
Ich werde evtl. versuchen eine deutsche Liste mit den wichtigsten INT's und Funktionen zu erstellen. Da es aber sehr sehr lange dauert und sehr aufwendig ist, will ich hier nichts versprechen.
Das wars!

bei Fragen: Mail an Webmaster.




Werbung
Partner