| 2.5 Übungen zur Assemblerprogrammierung | Inhalt der Kurseinheit 3 |
Zu P2.3-1:
Für pass 1 des Assemblers ergibt sich als Flußdiagramm:

Für pass 2 des Assemblers ergibt sich als Flußdiagramm:

Zu P2.4-1:
0001 ************************************************** 0002 * P24-1.ASM 0003 * 0004 * Programm zur Addition von BCD-Zahlen ohne Verwen 0005 * des DAA-Befehls 0006 * 0007 0400 ORG $0400 ;Beginn des Programmbereichs 0008 0009 0400 bd f1 10 JSR CLRDISP ;Anzeige loeschen 0010 0403 10 8e 06 00 LDY #$0600 ;Datenzeiger laden 0011 0407 6f a4 CLR 0,Y ;Datenbereich mit Null initialisieren 0012 0409 6f 21 CLR 1,Y ; 0013 040b 8e 00 00 START: LDX #$0000 ;X loeschen 0014 040e bd f1 43 JSR HALTKEY ;Zeichen von Tastatur lesen 0015 0411 c1 86 CMPB #$86 ;Vergleich, auf Ende der Eingabe "S" 0016 0413 27 30 BEQ ENDE ; 0017 0415 c1 09 CMPB #$09 ;Test der Eingabe auf gueltige Ziffer 0018 0417 22 f2 BHI START ;bei ungueltiger Ziffer zurueck 0019 0419 eb a4 ADDB 0,Y ;Addition der Eingabe mit LSB der Sum 0020 041b 1f 98 TFR B,A ; 0021 041d 84 f0 ANDA #$F0 ;Test auf Ueberlauf durch vorherige A 0022 041f 26 06 BNE BCDADD ;wenn ja, Korrektur 0023 0421 1f 98 TFR B,A ; 0024 0423 81 09 CMPA #$09 ;Test auf gueltige BCD-Ziffer 0025 0425 23 02 BLS CARRY2 ;wenn nein, Korrektur 0026 0427 cb 06 BCDADD: ADDB #$06 ;Korrektur, als Ergebnis gueltige BCD 0027 0429 1f 98 CARRY2: TFR B,A ; 0028 042b 84 f0 ANDA #$F0 ; 0029 042d 27 06 BEQ SHOW ;Test auf Ueberlauf durch vorherige A 0030 042f 86 01 LDA #$01 ; 0031 0431 ab 21 ADDA 1,Y ;naechsthoeherwertige Ziffer um Eins 0032 0433 a7 21 STA 1,Y ;naechsthoeherwertige Ziffer abspeich 0033 0435 c4 0f SHOW: ANDB #$0F ;eventl. Uebertrag der korrigierten Z 0034 0437 e7 a4 STB 0,Y ;korrigierte Ziffer abspeichern 0035 0439 bd f1 1c JSR SHOWT7SG;korrigierte Ziffer in Anzeige 0036 043c e6 21 LDB 1,Y ;naechsthoeherwertige Ziffer laden 0037 043e 30 01 LEAX 1,X ;Anzeigestelle nach links verschieben 0038 0440 bd f1 1c JSR SHOWT7SG;naechsthoeherwertige Ziffer in Anz 0039 0443 20 c6 BRA START ;zurueck zur naechsten Eingabe 0040 0445 3f ENDE: SWI1 0041 0042 f110 CLRDISP EQU $F110 ;Loeschen der Anzeige, In:-, 0043 f11c SHOWT7SG EQU $F11C ;unteres Nibble von B in Anzeige 0044 f143 HALTKEY EQU $F143 ;Lesen der Tastatur mit Warten, Number of errors 0
Das folgende Flußdiagramm zeigt die Problematik:

Zu P2.4-2:
Zu P2.4-3:
Der "DS9" erzeugt aus der Datei "P24-1.HEX" das folgende Listing:
; *** 6809 - Disassembler Ver. 1.3 *** 0400: BD F1 10 JSR $F110 0403: 10 8E 06 00 LDY #$0600 0407: 6F A4 CLR ,Y 0409: 6F 21 CLR $01,Y 040B: 8E 00 00 LDX #$0000 040E: BD F1 43 JSR $F143 0411: C1 86 CMPB #$86 0413: 27 30 BEQ $30 ;$0445 0415: C1 09 CMPB #$09 0417: 22 F2 BHI $F2 ;$040B 0419: EB A4 ADDB ,Y 041B: 1F 98 TFR B,A 041D: 84 F0 ANDA #$F0 041F: 26 06 BNE $06 ;$0427 0421: 1F 98 TFR B,A 0423: 81 09 CMPA #$09 0425: 23 02 BLS $02 ;$0429 0427: CB 06 ADDB #$06 0429: 1F 98 TFR B,A 042B: 84 F0 ANDA #$F0 042D: 27 06 BEQ $06 ;$0435 042F: 86 01 LDA #$01 0431: AB 21 ADDA $01,Y 0433: A7 21 STA $01,Y 0435: C4 0F ANDB #$0F 0437: E7 A4 STB ,Y 0439: BD F1 1C JSR $F11C 043C: E6 21 LDB $01,Y 043E: 30 01 LEAX $01,X 0440: BD F1 1C JSR $F11C 0443: 20 C6 BRA $C6 ;$040B 0445: 3F SWI(1)
Symbolische Adressen für Sprungziele und Unterprogramme können bei einer Disassemblierung nicht berücksichtigt werden. Ein "Nach-Disassemblieren" von Hand ist notwendig. Der generierte Quellcode stimmt ansonsten mit dem "Original"-Code überein.
Beachten Sie bitte, daß der "DS9"
bei Verzweigungen nicht nur den Offset zum Sprungziel angibt, sondern auch die absolute Adresse des Sprungzieles.
Zu P2.5-1:
Für das Unterprogramm von Tabelle 2.4-6 ergibt sich das folgende Flußdiagramm:

Im Falle eines Übertrages auf die nächsthöhere Ziffer wird das Register A auf einen Wert ungleich Null gesetzt und dem Hauptprogramm übergeben. Die berechnete Ziffer wird abgespeichert. Die Übergabe der zugehörigen Speicheradresse erfolgt durch das Register Y.
Zu P2.5.2:
Das Flußdiagramm für das Hauptprogramm ist auf der folgenden Seite abgebildet. Erzeugt die BCD-Addition einen Übertrag, so wird das Unterprogramm nochmals aufgerufen, um den Übertrag zur nächsthöheren Ziffer der Summe zu addieren. Im worst case muß über die gesamte Zahlenbreite eine Übertragsaddition erfolgen. Wird ein Überlauf erkannt, so wird das Overflow-Symbol zur Anzeige gebracht. Wird danach die "S"-Taste gedrückt, so wird das Programm beendet, ansonsten bei Eingabe einer gültigen Ziffer mit einer neuen Addition begonnen.

Eine mögliche Implementierung für das Hauptprogramm folgt jetzt.
;****************************************************************************
; P1a.ASM
;
; Programm zur Addition von BCD-Zahlen mit maximal 7 Ziffern ohne Verwendung
; des 6809-Befehls DAA. Der Befehl wird durch das Unterprogramm UP_ADD er-
; setzt.
; Erweiterung der Wortbreite ohne Probleme moeglich
; (Praktikumsrechner hat allerdings max. 8 Stellen).
; Bei Ueberlauf Aktivierung der Anzeige.
; Abbruch der Eingabe mit der Taste "S" des Praktikumsrechners.
;
ORG $0400 ;Beginn des Programmbereiches
NEW: JSR CLRDISP ;Anzeige loeschen
CLRA ;A loeschen
CLRB ;B loeschen
STD >$0600 ;Datenbereich $0600 - $0607
STD >$0602 ;mit Null initialisieren
STD >$0604 ;
STD >$0606 ;
START: LDX #$0000 ;X loeschen
LDY #$0600 ;Datenzeiger laden
LDU #ZWIDTH ;Zahlenbreite laden
JSR HALTKEY ;Zeichen von Tastatur lesen
CMPB #$86 ;Vergleich, auf Ende der Eingabe (Taste "S")
BEQ END ;
CMPB #$09 ;Test der Eingabe auf gueltige Ziffer (0..9)
BHI START ;bei ungueltiger Ziffer zurueck zur Eingabe
CARRY: JSR UP_ADD ;Aufruf UP zur Addition von zwei BCD-Ziffern
JSR SHOWT7SG ;korrigierte Ziffer in Anzeige
LEAX 1,X ;X:=X+1
LEAY 1,Y ;Y:=Y+1
LEAU -1,U ;U:=U-1
LDB #$01 ;Reg. B fuer Addition des Uebertragsbits auf 1
CMPA #$00 ;Vergleich auf Ueberlauf
BEQ START ;wenn nein, zurueck zur naechsten Eingabe
CMPU #$0000 ;Vergleich auf max. Zahlenbreite
BEQ OVERFL ;Overflow, Uebertrag ignorieren; zur OV-Behandlung
BRA CARRY ;Uebertrag addieren und anzeigen
OVERFL: LDA #$5C ;
JSR SHOWA ;Overflow-Symbol in Anzeigestelle S7
JSR HALTKEY ;Zeichen einlesen
CMPB #$86 ;Programmende?
BNE NEW ;nein, neuer Lauf
END: SWI ;Programmende
ZWIDTH EQU $0007 ;Maximale Ziffernanzahl einer zu speichernden BCD-Zahl
;----------------------------------------------------------------------------
; Hier beginnen die Definitionen der Monitorroutinen und der Adressen der
; Hardware-Register.
; Monitorroutinen
;
CLRDISP EQU $F110 ;Loeschen der Anzeige, In:-, Out:-
SHOWT7SG EQU $F11C ;unteres Nibble von B in Siebensegmentcode wandeln
;und anzeigen, Position in X
SHOWA EQU $F113 ;Direkte Ansteuerung der Segmente der Anzeige-
;stelle durch das Byte in A, Position in X
HALTKEY EQU $F143 ;Lesen der Tastatur mit Warten, In:-, Out:B
Sie finden das Assemblerprogramm in dem Unterverzeichnis "Software" der CD-ROM in der Datei "P1a.ASM".
Zu P2.5-3:
Die folgenden drei Unterprogramme repräsentieren die geforderten Zähler. In "UP1" werden die Register über den Stack gerettet, während in "UP2" nicht benötigte Register verwendet werden. Das Programm ist auch als Datei "P25-3.ASM" im Unterverzeichnis "KE2" abgelegt.
;=====================================================================
;Unterprogramm UP1: Zaehler, für die Anzeigestellen S5,S4
; Register B und X werden ueber den Stack gerettet.
;
UP1: LDX #$0004 ;Anzeigeposition laden (S5,S4)
LDB #$FF ;Zaehler initialisieren
NEXT1: INCB ;Zaehler inkrementieren
JSR SHOWB7SG ;Zaehlerstand anzeigen
PSHS B ;Zaehler und Anzeigeposition ueber
PSHS X ;den Stack retten
JSR UP2 ;Aufruf des zweiten UP
PULS X ;Zaehler und Anzeigeposition einlesen
PULS B ;
CMPB #$FF ;Abbruchbedingung erfuellt?
BNE NEXT1 ;wenn nein, zurueck zu NEXT1
RTS ;Ende Unterprogramm
;=====================================================================
;Unterprogramm UP2: Zaehler, für die Anzeigestellen S3,S2
; Register B und X werden ueber Register gerettet.
;
UP2: LDX #$0002 ;Anzeigeposition laden (S3,S2)
LDB #$FF ;Zaehler initialisieren
NEXT2: INCB ;Zaehler inkrementieren
JSR SHOWB7SG ;Zaehlerstand anzeigen
TFR B,A ;Zaehler und Anzeigeposition ueber
TFR X,Y ;andere Prozessorregister retten
JSR UP3 ;Aufruf des dritten (letzten) UP
TFR A,B ;Zaehler und Anzeigeposition wieder
TFR Y,X ;zurueckschreiben
CMPB #$FF ;Abbruchbedingung erfuellt?
BNE NEXT2 ;wenn nein, zurueck zu NEXT2
RTS ;Ende Unterprogramm
;=====================================================================
;Unterprogramm UP3: Zaehler, für die Anzeigestellen S1,S0
;
UP3: LDX #$0000 ;Anzeigeposition laden (S1,S0)
LDB #$FF ;Zaehler initialisieren
NEXT3: INCB ;Zaehler inkrementieren
JSR SHOWB7SG ;Zaehlerstand anzeigen
CMPB #$FF ;Abbruchbedingung erfuellt?
BNE NEXT3 ;wenn nein, zurueck zu NEXT3
RTS ;Ende Unterprogramm
Im Unterprogramm "UP2" werden je zwei Stackoperationen benutzt, um die Registerinhalte auf den Stack zu schreiben bzw. einzulesen. Es ist auch möglich, die Stackoperationen mit jeweils einem Befehl auszuführen. Hierzu ist entweder der numerische Wert "immediate" anzugeben; oder die einzelnen Register durch Kommata getrennt aufzuzählen.
Zu P2.5-4:
Eine mögliche Implementierung des Hauptprogramms und der Interruptroutine zeigt das folgende Listing:
;*********************************************************************
; P4.ASM
;
; Ziffern-Zaehlprogramm mittels einer Software-Interruptroutine.
; Software-Interrupt wird als Monitor- (Betriebssystem-) Gate benutzt,
; um Funktionen des Monitors zu benutzen. Eingegebener Wert wird in S0
; dargestellt, Anzahl der eingebenen Werte fuer "0" in S7, fuer "1" in
; S6. Uebergabeparameter: X-Reg.: call-by-value, B-Reg.: call-by-refr.
; Parameter werden in der Interruptroutine Stack-relativ geladen.
;
ORG $0400 ;Beginn des Programmbereiches
LDX #MRGATE ;Interruptroutine in der Vektortabelle
STX $004C ;an Adresse $004C, $004D eintragen
NEW: LDX #$0008 ;Uebergabeparameter nach A (Anzeige loeschen)
SWI3 ;Software-Interrupt ausfuehren
CLRB ;Zaehler in den Speicherstellen
LDX #$0006 ;$06 und $07 in der Zero-Page
STB ,X ;mit Null initialisieren
SWI3 ;und jeweiliger Wert (0)
LEAX 1,X ;in den Anzeigestellen
STB ,X ;S6 und S7 anzeigen
SWI3 ;
INPUT: LDX #$0009 ;Uebergabeparameter fuer Tastatur nach X und
SWI3 ;zur Interruptroutine verzweigen
CMPB #$01 ;Wurde Taste "1" betaetigt?
BNE INPUT0 ;Wenn nein, vielleicht "0"
LDX #$0000 ;Wert in Anzeigestelle
SWI3 ;S0 anzeigen
LEAX 6,X ;Zaehler fuer den
LDB ,X ;Wert "1" laden,
INCB ;inkrementieren und wieder
STB ,X ;abspeichern
SWI3 ;In S6 anzeigen
BRA INPUT ;zurueck zur naechsten Eingabe
INPUT0: CMPB #$00 ;Vergleich auf Taste "0"
BNE INPUT+ ;wenn nein, vielleicht "+"-Taste
LDX #$0000 ;Wert in Anzeigestelle
SWI3 ;S0 anzeigen
LEAX 7,X ;Zaehler fuer "0"
LDB ,X ;laden,
INCB ;inkrementieren und
STB ,X ;abspeichern
SWI3 ;In S7 anzeigen
BRA INPUT ;zurueck zur naechsten Eingabe
INPUT+: CMPB #$80 ;Vergleich auf "+"-Taste
BEQ NEW ;Wenn ja, Zaehler neu initialisieren
BRA INPUT ;ungueltige Taste, zurueck zur Eingabe
; Interruptroutine
MRGATE: LDX 4,S ;X-Register vom Stack holen (Stack-relativ)
CMPX #$0008 ;Routine fuer Anzeige gefordert ?
BHS DISP ;Wenn nein, vielleicht Anzeige loeschen
JSR SHOWT7SG ;Anzeige des unteren Nibbles aus B
BRA SUBEND ;zum RTI
DISP: CMPX #$0008 ;Routine zum Loeschen der Anzeige gefordert?
BNE TAST ;Wenn nein, vielleicht Routine zur Tastatureing.
JSR CLRDISP ;Anzeige loeschen
BRA SUBEND ;zum RTI
TAST: CMPX #$0009 ;Routine zur Tastatureingabe gefordert?
BNE SUBEND ;Wenn nein, falscher Uebergabeparameter; zurueck
JSR HALTKEY ;auf Eingabe von Tastatur warten
STB 2,S ;B-Register auf den Stack legen (Stack relativ)
SUBEND: RTI ;Ruecksprung zum Hauptprogramm
CLRDISP EQU $F110 ;Loeschen der Anzeige, In:-, Out:-
SHOWT7SG EQU $F11C ;unteres Nibble von B in Anzeige, Position in X
HALTKEY EQU $F143 ;Lesen der Tastatur mit Warten, In:-, Out:B
Es hat sich als gute Programmierpraxis erwiesen, in Unterprogrammroutinen, und insbesondere in Interruptroutinen, nur eine Aussprungstelle zu programmieren. In der obigen Interruptroutine wäre es möglich nach den einzelnen Abfragen nicht mit einem BRA-Befehl zum Ende der Routine zu verzweigen und erst dann einen RTI-Befehl durchzuführen, sondern statt eines BRA-Befehls sofort einen RTI-Befehl zu programmieren. In Bezug auf ein gutes Software-Engineering und einfache Wartungs- und Pflegeoptionen hat sich herausgestellt, daß sich eine Beschränkung auf eine einzige Aussprungstelle positiv auf die Programmierfehlerrate auswirkt.
Sie finden das Assemblerprogramm im Unterverzeichnis "Software" der CD-ROM in der Datei "P4.ASM".
| 2.5 Übungen zur Assemblerprogrammierung | Inhalt der Kurseinheit 3 |