Logo: Geos Online Print Archiv
G.O.P.A. - Geos Online Print Archiv
19.04.2024 Archiv  #  Recherche  #  Links  #  Kontakt  #  Gästebuch  #  Impressum

Index
Register
Login

Die Anzeige des Archivs erfolgt grafisch. Ändern

Kurs: Programmieren (Teil 5)

Autoren: H. J. Ciprina, R. Bonse

Sofern Sie Ihre "Hausaufgaben" aus dem 4. Teil noch nicht gemacht haben, ändern Sie bitte Ihr Listing wie folgt ab:

   1. Umändern des Dateimenüs in ein normales Untermenü:
Löschen Sie die Zeilen ab :DateiDyn bis zum folgenden rts. Einige Zeilen unter dem Label :MenüTab finden Sie die Einträge für den Dateimenüpunkt. Tauschen Sie diesen durch folgende Zeilen aus:

   w   DateiText
   b   SUB_MENU
   w   DateiSub

   2. Abbau der kompletten Untermenüstruktur bei Anwahl der Menüpunkte "CD-Titel" und "Titel".
Nach den Labeln :DoCDTitel und :DoTitel dürfen sich nur die beiden Zeilen befinden:

       jsr   GotoFirstMenu
       rts

   3. Steuern des Menüpunktes "ändern" durch ein Sternchen im Menütext.
Ergänzen Sie folgende Zeilen ab :DoChange

   :DoChange
          bit     ChangeFlag
          bmi     :10
          LoadB   Ändern Text,"*"
          LoadB   ChangeFlag,$ff
          bne     :20
   ::10   LoadB   ÄndernText,""
          LoadB   ChangeFlag,$00
   ::20   jsr     ReDoMenu
          rts
   :ChangeFlag    b 0

Ferner müssen folgende Zeilen ab :ÄndernText vor b "ändern" hinzugefügt werden:

                  :ÄndernText
                    b   " ";2*Space
                    b   GOTOX
                    w   BMLinks+12

Der heutige Kursteil beschäftigt sich mit einer praktischen Methode zum Abfangen von Fehlern beim Programmieren.
Wenn Sie schon versucht haben, eigene Programme zu schreiben oder auch nur unsere Programme (falsch) abgetippt haben, werden Sie hin und wieder den einen oder anderen Fehler beim Eingeben des Quelltextes gemacht haben. Sofern es sich um Syntaxfehler handelte, gab der MegaAssembler entsprechende Fehlermeldungen aus. Stürzt das Programm hingegen mit einem "Systemfehler nahe $xxxx" ab, so liegt ein Programmierfehler vor, den der MegaAssembler natürlich nicht abfangen kann. Bei der obigen Fehlermeldung muß GEOS neu gestartet werden. Ein häufiger Fehler entsteht z.B. dann, wenn anstelle des b-Opcodes der w-Opcode in Tabellen verwendet wird. In einem solchen Fall könnte die CPU des C64 den Bytewert NULL als brk-Befehl interpretieren. Trifft die CPU auf diesen Befehl, so verzweigt GEOS auf die Routine, deren Zeiger (word) in der Adresse BRKVector ($84af) abgelegt ist. Standardmäßig ist hier die Adresse der Routine abgelegt, die "Systemfehler nahe $xxxx" ausgibt. Unsere Fehlerbehandlungsroutine ändert den BRKVector so ab, daß sie auf eine neue Routine zeigt, die ebenfalls die Systemfehlermeldung ausgibt, aber die bei Anwahl des OK-Icons bzw. Drücken der Taste <RETURN> (ab GEOS 1.3) zum DeskTop zurückkehrt.
Geben Sie zunächst das Listing Break.src ein und speichern es bitte unbedingt unter diesem Namen ab.

   :Break.src

   :InitBreak
        LoadW BRKVector,NewBreak
        rts
   :NewBreak
        PopW   r0
        sec
        lda    r0L
        sbc    #$02
        sta    r0L
        lda    r0H
        sbc    #$00
        sta    r0H
        ldx    #$00
        lda    r0H
        jsr    WertBerechnung
        lda    r0L
        jsr    WertBerechnung
        LoadW  r0,BreakDial
        jsr    DoDlgBox
        jmp    EnterDeskTop

   :WertBerechnung
        pha
        lsr
        lsr
        lsr
        lsr              ;Hi-Nibble
        jsr    WertASC
        inx
        pla
        and    #%00001111;Lo-Nibble
        jsr    WertASC
        inx
        rts

   :WertASC
        cmp    #$0a
        bcs    :10
        adc    #$30
        bne    :20
   ::10 clc
        adc    #$37
   ::20 sta    WertText,x
        rts

   :BreakDial
        b      %10000001
        b      DBTXTSTR
        b      10
        b      10
        w      BreakText
        b      OK
        b      8
        b      30
        b      NULL

   :BreakText
        b      BOLDON
        b      "Programmfehler nahe $"
   :WertText   b         "0000",NULL

Die Routine InitBreak verändert den Breakvektor auf unsere Routine (NewBreak), die nun beschrieben wird:
Trifft die CPU auf den Befehl brk, so wird u. a. die aktuelle Adresse + 2 auf dem Stack gesichert. Da uns diese Adresse interessiert, laden wir als erstes die auf dem Stack abgelegte Adresse mit Hilfe des Makros PopW nach r0. Das Makro ersetzt die Befehlsfolge:

               pla
               sta   r0L
               pla
               sta   r0H

Der Zugriff auf den Stack erfolgt durch den pla-Befehl, der das oberste Byte des Stacks in den Akku schiebt und den Stack-Pointer um 1 vermindert. Da auf dem Stack zunächst das Low-Byte und dann das High-Byte steht, enthält nach dem Makroaufruf auch r0L das Low-Byte und r0H das High-Byte der Adresse+2. Wir wollen aber die richtige Position des brk-Befehls im Speicher ausgeben und müssen daher noch das word r0 um den Wert 2 vermindern. Um eine korrekte Subtraktion auszuführen, wird als erstes das Carry-Flag mittels sec gesetzt. Danach ziehen wir zuerst vom Low-Byte r0L den Wert 2 ab und speichern diesen auf r0L. Trat nun ein Unterlauf auf (d. h. hier: r0L war 0 oder 1), so ist das Carry-Flag jetzt gelöscht und das High-Byte muß auch noch um den Wert 1 vermindert werden. Dieses geschieht, indem wir den Wert 0 vom High-Byte abziehen, ohne vorher das Carry-Flag verändert zu haben. Denn wenn das Carry-Flag gelöscht ist, wird nicht das Argument, sondern das Argument + 1 (also hier 0+1=1) abgezogen!

Nachdem wir nun den richtigen Wert in r0L und r0H haben, müssen diese noch in ausgebbare Zeichencodes umgerechnet werden. Weil wir diese Arbeit sowohl für das Low-Byte als auch für das High-Byte erledigen müssen, haben wir eine Routine WertBerechnung geschrieben, die diese Arbeit übernimmt. Als Eingabeparameter benötigt diese Routine im Akku den umzurechnenden Wert und im X-Register einen Wert, der bestimmt, wo die Zeichen abgespeichert werden sollen.
Als nächstes zeigen wir die ermittelte Adresse in einer Standarddialogbox an. Hierzu übergibt man in r0 einen Zeiger auf die Dialogboxtabelle und ruft die Routine DoDlgBox auf. Wird schließlich die Dialogbox verlassen, so wird durch jmp EnterDeskTop der DeskTop geladen und gestartet.
Die Routine WertBerechnung ordnet den Low und High-Nibbles des Akkus jeweils den entsprechenden Zeichencode zu. Da der Akku im Laufe der Berechnungen verändert wird, sichern wir ihn mittels pha zuerst auf den Stack. Um an den Wert des High-Nibbles zu gelangen, schieben wir den Inhalt des Akkus durch 4-maliges Benutzen des lsr-Befehls um 4 Bit nach rechts. Das endgültige Berechnen und Setzen des dazugehörigen Zeichens (0,1.....9,a,b.....f) erledigt die Routine WertASC, die im Akku den umzurechnenden Wert und im X-Register den Wert für die Speicher-Position benötigt.
Nach Umrechnen des High-Nibbles muß das Low-Nibble ebenfalls umgerechnet werden. Wir erhöhen zunächst das X-Register um den Wert 1, da beim Ausgeben der Zeichen der Wert des Low-Nibbles rechts neben dem des High-Nibbles erscheinen soll. Den auf dem Stack gesicherten Inhalt des Akkus holen wir mit dem pla-Befehl zurück und isolieren das Low-Nibble durch eine logische UND-Verknüpfung mit dem Wert %00001111. Nach wiederholten Aufruf von WertASC erhöhen wir das X-Register noch um den Wert 1, damit es beim nächsten Aufruf von WertBerechnung auf die nächste Speicherposition zeigt.

Den Werten 0 bis 9 entsprechen die Zeichenausgabe-Codes $30 bis $39. Bei den Werten 10 bis 15 müssen die Buchstaben A bis F ausgegeben werden. Diesen entsprechen die Codes $41 bis $46. Daher unterscheidet die Routine WertASC zunächst, ob der Wert im Akku kleiner oder größer gleich dem Wert 10 ist.
Dazu benutzen wir den cmp-Befehl, der mehr als nur auf Gleichheit testen kann! Ist das Carry-Flag gesetzt, so ist der Wert im Akku größer oder gleich 10 und wir verzweigen zum lokalen Label ::20. Ist der Wert kleiner als 10 (Carry-Flag =0), so addieren wir den Wert $30 zum Akku. Das Carry-Flag brauchen wir hier nicht extra für die korrekte Addition zu löschen, denn es ist ja im kleiner-Fall schon gelöscht. Dadurch erhalten wir den gewünschten Zeichen-Code im Akku. Da das Ergebnis der Addition sicherlich ungleich Null ist ($30 bis $39), können wir durch bne :20 garantiert den größer-gleich-Fall überspringen und den Zeichen-Code an der Speicherposition ablegen. Die Adresse, ab der die auszugebenden Zeichen stehen müssen, ist durch das Label :WertText gekennzeichnet.

Da die genaue Position abhängig vom X-Register (0 bis 3) sein soll, speichern wir den Wert X-Indiziert ab (sta WertText,x). Im größer-gleich-Fall (ab ::10) müssen wir den Wert $37 zum Akku addieren, denn $0a plus $37 ergibt $41. Damit erhalten wir die Buchstaben A bis F. Für die korrekte Addition muß hier natürlich vorher das Carry-Flag durch clc gelöscht werden.

Durch die Tabelle ab dem Label :BreakDial wird die Dialogbox, in der unsere berechneten Werte ausgegeben werden sollen, in ihren äußeren Maßen festgelegt. Anhand des ersten Bytes in der Tabelle unterscheidet Geos, ob eine Standardbox oder eine User definierte aufzubauen ist, und ob und welches Füllmuster für den Schatten der Box genommen werden soll.
Da wir hier neben einen kleinen Text nur noch ein OK-Icon ausgeben wollen, genügen völlig die Ausmaße der Standardbox. Zu diesem Zweck muß in dem ersten Byte das siebte Bit gesetzt sein. Die unteren vier Bits (Bit 0 bis Bit 3) des Bytes entscheiden über das Füllmuster. Wir haben hier den Wert 1 gesetzt, der einen ausgefüllten Schatten zur Folge hat. Probieren Sie doch mal andere Werte aus!

Der nächste Wert DBTXTSTR ist ein Steuercode, der Geos anzeigt, daß ein Text auszugeben ist. Die darauf folgenden zwei Bytes geben die relative Position in Pixel an, ab der der Text ausgegeben wird. Das nächste Word BreakText zeigt auf den auszugebenden Text, der mit einem Null-Byte abgeschlossen sein muß. Mit dem nächsten Byte OK installieren wir noch das OK-System-Icon, damit wir die Box auch wieder verlassen können! Dem Steuercode folgt ein Byte für die relative X-Position in Cards und ein Byte für die relative Y-Position in Pixel. Den Abschluß der Tabelle bildet das Null-Byte.

Zum Testen der neuen Break-Routine muß im Programm zunächst einmal der neue Breakvektor installiert werden. Dazu tragen Sie bitte am Anfang des Listings Quell3.obj nach dem Label :Start den Befehl

   jsr   InitBreak

ein. Zum Einbinden des Quelltextes von Break.src fügen Sie bitte am Ende des Listings Quell3.obj den Befehl

   t   "Break.src"

ein. Damit Sie nun die neue Breakroutine austesten können, müssen Sie noch im Listing ein brk setzen. Tragen Sie doch beispielsweise bei der Routine DoInfo ein brk ein. So können Sie kontrolliert, durch Anwählen des entsprechenden Menüpunktes, die Break-Routine testen.
Wenn Sie sich versichern wollen, ob auch die richtige Adresse ausgegeben wird, dann schreiben Sie vor dem brk-Befehl ein externes Label (Bsp.: .AddBreak) und lassen sich durch den MegaAssembler eine externe Symboltabelle ausgeben, die dann die Adresse des brk-Befehls angibt. Diese können Sie nun mit der in der Dialogbox angezeigten vergleichen.

Mit Hilfe dieser break-Routine können Sie durch gezieltes Setzen des brk-Befehls in der Entwicklungsphase z. B. testen, ob Ihr Programm eine bestimmte Stelle überhaupt erreicht. Endlosschleifen können Sie damit zwar nicht vermeiden, aber sehr wohl eingrenzen. Haben Sie Ihr Programm fertig geschrieben, so kann die Break-Routine natürlich wieder entfernt werden.

Viel Spaß beim Programmieren und Austesten, bis zur nächsten Ausgabe.

 

R. Bonse, H.J. Ciprina

 

 

 




Dieser Artikel ist Bestandteil von:

Ausgabe 19

! - - - - - M I C R O F I L M - - - - - ! | Editorial | Das Clubtreffen | Meinungen | Regionales | Dies & Das | Regio Betreuer | Büro-Kurs (Teil 2) | GEOS - Tastaturbelegung, Tastenkürzel mit Commodore Taste | Kurs: Programmieren (Teil 5) | Neu: Der GeoHexer | Font Collection 2 | Festplatte | US Einkaufshilfe | Der Wettbewerb - Erfahrungen eines 64'er Lesers | Disk Reparatur | Deutsche Anleitung | GeoThek Uebersicht, GEOS Professional | Die neue GeoThek | Das aktuelle Kurz-Info | Berührungsängste ? | GEOHEXER | PC/GEOS TEIL zur GEOS - USER - POST 19


Kurs Programmieren

Kurs: Programmieren (Teil 1) | Kurs: Programmieren (Teil 2) | Kurs: Programmieren (Teil 3) | Kurs: Programmieren (Teil 4) | Kurs: Programmieren (Teil 5) | Kurs: Programmieren (Teil 6) | Kurs: Programmieren (Teil 7) | Kurs: Programmieren (Teil 8)


Kurzlink hierhin: http://geos-printarchiv.de/1253


Letzte Änderung am 01.11.2019