Im vorletzten Teil unserer Serie über die Assembler-Macro-Bibliothek „ISAM & PRIMA“ werden die Standardroutinen des Modulpakets vorgestellt - zumeist Arithmetik-Routinen.
Die Artithmetik-Routinen von ISAM & PRIMA arbeiten - besonders bezüglich Kommastellen und Vorzeichen - nach den Regeln der Mathematik. Die Routinen für die Grundrechenoperationen lauten „Plus“, „Minus“, „Durch“ und „Mal“.
Zur Berechnung werden zwei standardisierte Rechenfelder mit den Bezeichnungen REFE1 und REFE2 verwendet. Sie haben folgendes Format:
DC ”0”
REFE1: DC ”0000000000”
VORZ1: DC ” + ”
KOMMA1: DC 0 SIGNI1: DC 0
DC ”0”
REFE2: DC ”0000000000”
VORZ2: DC
KOMMA2: DC 0 SIGNI2: DC 0
Zur Erläuterung: Das Format wird jeweils eine Stelle vor den Feldern REFE1 und REFE2 benötigt. Dies wird von der Routine „NUMERIC“ verlangt, die numerische Werte von der Tastatur holt und in Rechenfelder speichert. Das Feld REFE enthält den numerischen ASCII-Wert mit voranstehenden Nullen, VORZ das jeweilige Vorzeichen (+ oder -), KOMMA die Anzahl der Stellen hinter dem Komma und SIGNI die Position der ersten signifikanten Ziffern relativ zu dem Feld REFE.
Bei Bedarf kann man auch selbst andere Rechenfelder definieren. Das ist etwa beim Zwischenspeichern oder beim Umwandeln von ASCII in Binärformat interessant. Der eigentliche Rechenvorgang findet jedoch stets in den Feldern REFE1 und REFE2 statt.
Die Arithmetik-Routinen werden mit einem JSR 0ump Subroutine) angesprungen. Bei einem Überlauf enthält das Datenregister D0 den Wert -1.
Ein ungenaues Ergebnis entsteht, wenn zuviele signifikante Stellen vorhanden sind. In diesem Fall muß eine bestimmte Anzahl der Stellen nach dem Komma entfernt werden, da sonst ein Überlauf auftritt. Dadurch, daß diese Stellen abgetrennt wurden, erhält man logischerweise ein ungenaues Ergebnis. Das Feld „GENAU“ (.B) enthält dann eine - 1.
Falls keine Überlaufanzeige erfolgte und „GENAU“ eine 0 enthält, ist das Ergebnis absolut genau.
Nun zu den einzelnen Routinen:
Vor dem Aufruf mit JSR INPUT muß in D0 die maximale Anzahl der Zeichen und in A2 die Pufferadresse vorhanden sein. Die tatsächliche Anzahl der Zeichen steht im Anschluß an D0. Die eingegebenen Zeichen findet man im Puffer wieder, wobei sie durch X”00” abgeschlossen werden. Der Puffer muß aus diesem Grund um eine Stelle größer als die längste mögliche Eingabe sein. Wurde ein C eingegeben, gleich an welcher Stelle der Eingabe, so steht beim Rücksprung in D0 eine -3 und an der ersten Pufferstelle X”00”. Man sollte also nach der Rückkehr aus der INPUT-Routine unbedingt D0 auf negativ oder - 3 abfragen.
Bei dieser Routine müssen zuvor einige Felder definiert werden:
TATL: DC 0
ERG: BLK 10,"0” ;VOR ANSPRUNG
VORZ: DC ” + ” ;ADR "ERG" NACH
KOMMA: DC 0 ;A2 BRINGEN
SIGNI: DC 0
Vor dem Ansprung mit JSR NUMERIC muß die Adresse ERG in A2 stehen. Die eingegebene Zahl findet man nach der Rückkehr aus dieser Routine in ERG (Länge = zehn Stellen mit führenden Nullen). Die Anzahl der Stellen nach dem Komma steht in KOMMA, die Anzahl der signifikanten Stellen in SIGNI. Es wird eine Prüfung durchgeführt, ob das eingegebene Zeichen numerisch ist. Erfolgt eine falsche Eingabe oder wird nur die RE-TURN-Taste gedrückt oder ist die eingegebene Zahl größer 3.999.999.999, wird D0 vor dem Rücksprung auf - 1 gesetzt. Bei Eingabe von C steht in D0 anschließend eine -3. Alle Register, außer D0, bleiben unverändert.
Diese Routine wird von den Arithmetik-Routinen verwendet und ist im eigentlichen Sinne keine Standardroutine.
Vor dem Ansprung der Routine muß in D0 (.B) der Minimalwert stehen, den SIGNI annehmen darf. Als Ergebnis erhält man gleiche Nachkommastellen in REFE1 und REFE2. Das Feld mit der geringeren Anzahl von Nachkommastellen wird dabei dem anderen angepaßt. Falls der Minimalwert für SIGNI unterschritten wird, werden rechts Nachkommastellen abgeschnitten. Alle Register bleiben bei dieser Routine unverändert.
Man kann diese Routine ebenfalls zum Erweitern der Nachkommastellen auf eine bestimmte Anzahl nutzen. Dazu nimmt man eines der Rechenfelder als sogenanntes „Dummy“ und gibt im Feld KOMMA die gewünschte Anzahl von Nachkommastellen an, auf die das andere Rechenfeld erweitert werden soll.
Diese Routine ist genau wie ABGLEICH keine eigentliche Standardroutine, wird aber von den Arithmetik-Routinen benutzt. Ein Überlauf in den Rechenfeldern wird durch eine -1 im Register D0 angezeigt. Man sollte die Uber-laufkontroll-Routine mit JSR UEPLUS anspringen, nachdem ein Abgleich der Kommastellen stattgefunden hat. UEPLUS versucht dann einen drohenen Überlauf durch Abschneiden von Nachkommastellen abzuwenden.
Durch Aufruf dieser Routine werden die beiden Rechenfelder REFE1 und REFE2 addiert. Das Ergebnis steht anschließend in REFE1.
Diese Routine benutzt die PLUS-Routine, nachdem zuvor eine Vorzeichen-Invertierung stattgefunden hat. Es werden wieder die beiden Rechenfelder benutzt. Das Ergebnis steht anschließend in REFE1.
Diese Routine dividiert REFE1 und REFE2. Das Ergebnis steht in REFE1.
Durch diese Routine wird REFE1 mit REFE2 multipliziert. Das Ergebnis steht wieder in REFE1.
Vor dem Aufruf mit JSR KNEIF muß zuvor die Anzahl der gewünschten Nachkommastellen nach dem Abschneiden an D0 übergeben werden. Ebenso muß der Inhalt des Rechenfeldes REFE1 in A2 stehen. Das Ergebnis findet man danach wieder in REFE1.
Ebenso wie bei KNEIF müssen vor dem Aufruf der Routine die Nachkommastellen an D0 und REFE1 an A2 übergeben werden. Das Ergebnis steht dann wieder in REFE1.
Vor dem Aufruf der Routine muß die Anfangsadresse von REFE an A2 übergeben werden. Die Binärzahl muß als Langwort in Dl stehen, wobei Bit 31 zur Zahl und kein Vorzeichen möglich ist. Zur Umwandlung wird die Routine DIVI benötigt. Nach dem Aufruf mit JSR BINASC findet man die ASCII-Zahl im Feld REFE 10-stellig mit führenden Nullen wieder. Das Vorzeichen (immer ” + ”) steht in VORZ und die Anzahl der signifikanten Ziffern in SIGNI. Das Feld KOMMA bleibt allerdings unbeeinflußt. Die Register bleiben durch den Aufruf dieser Routine unverändert.
Die Adresse von REFE muß vor dem Aufruf der Routine in A2 stehen. Das Vorzeichen bleibt unberücksichtigt. Zur Umwandlung wird die Routine MULTI benötigt. Das Ergebnis steht anschließend in Dl. Alle anderen Register bleiben unverändert.
Durch diese Routine wird eine 32 Bit-Division durchgeführt. Vor dem Aufruf muß der Dividend in D1 und der Divisor in D3 stehen. Nach der Ausführung findet man den Quotienten in D1, den eventuellen Rest in D2 und den Divisor in D3 wieder. Alle anderen Register bleiben unverändert.
Durch diese Routine wird eine 32 Bit-Multiplikation durchgeführt. Vor dem Aufruf muß der Multiplikant in Dl und der Multiplikator in D2 stehen. Nach der Ausführung findet man das Produkt in Dl wieder. Bis auf Dl und D2 bleiben alle anderen Register unverändert. Eine -1 in D0 zeigt einen eventuellen Überlauf an.
Diese Routine benutzt die Macros TRANSFER und FILL. Es ist also darauf zu achten, daß sie auch im Speicher vorhanden sind. Die Adresse von REFE muß vor dem Ansprung in A2 stehen. Die zu editierende Zahl muß als ASCII-Zahl in den Feldern REFE, KOMMA und SIGNI, wie oben beschrieben, definiert sein. Außerdem ist es notwendig, das Empfangsfeld ED-FLD zuvor festzulegen. Dazu muß in EDFLD die Empfangsfeldlänge und in EDFLD +1 die gewünschte Anzahl der Nachkommastellen stehen. EDFLD ist schon definiert und auf eine maximale Länge von 15 Stellen festgelegt. Die aufbereitete Zahl steht anschließend in der geforderten Länge rechtsbündig mit führenden Leerstellen und Dezimalpunkt in EDFLD. Dabei werden nur negative Vorzeichen eingefügt, positive nicht. Wenn die Länge von EDFLD zu kurz gewählt wurde und deshalb die aufzunehmende Zahl zu groß ist, werden #-Zeichen angezeigt.
Man muß also EDFLD so lang wählen, daß mindestens die Ziffernanzahl, der Dezimalpunkt und das Vorzeichen Platz haben. Erwartet man zum Beispiel Zahlen bis 1000, muß mindestens eine Sechs vor Aufruf der Routine in EDFLD stehen. Alle Register bleiben unverändert.
Wir haben nun den PRIMA-Teil von ISAM & PRIMA abgeschlossen und wenden uns im nächsten Heft dem letzten, dem ISAM-Teil zu. Dies dürfte insbesondere für alle, die sich mit Dateierstellung beschäftigen wollen, sehr interessant werden.
(HE)
INPUT: MOVEM.L D1-D2/A2,-(SP)
MOVE.B D0,D1
EXT.W D1 ; MAXIMALE EINGABE -> Dl
CLR.L D2 ;ZÄHLER TATSÄCHL.EING.
IN010: SUBQ.W #1,D1
TST.W D1
BMI IN040 ;MAXIMALZAHL ERREICHT
IN020: INKEY
TST.L D0
BEQ IN020
CMP.B #8,D0 ;BACKSPACE?
BEQ IN030 ;JA
CMP.B #13,D0 ;CR ?
BEQ IN040
CMP.B #3,D0 ;^C ?
BNE IN025 ;NEIN
MOVE.L #-3,D0 ;ANZEIGER F.^C
MOVEM.L (SP)+,D1-D2/A2
CLR.B (A2) ;X’OO’ AN PUFFERANFANG
RTS
IN025: ADDQ.B #1,D2
MOVE.B D0,( A2)+ ;ZEICHEN -> PUFFER
CHAR D0
BRA IN010
IN030: TST.B D2 ;WAREN SCHON ZEICHEN DA ?
BEQ IN020 ;NEIN, BACKSPACE IGNORIEREN
SUBQ.B #1,D2
ADDQ.W #1,D1
SUBQ.L #1,A2
MOVE.B #32,(A2) ;VORANGEGANGENES ZEICHEN AUF BLANK
CHAR #8
CHAR #32
CONTROL. CLINKS
BRA IN020
IN040: MOVE.L D2,D0 ;ANZAHL EINGABEZEICHEN
CLR.B (A2) ;X"00" ANS PUFFERENDE
MOVEM.L (SP)+,D1-D2/A2
RTS
NUMERIC: MOVEM.L D1/A0-A2,-(SP)
MOVE.B #10,D0 ;MAX.10 ZEICHEN HOLEN
JSR INPUT ;PUFFERADR STEHT SCHON IN A2
NUM000: TST.B D0 ;CONTROL C ?
BMI NUMEXIT
MOVE.B D0,-1(A2) ;GELESENE ANZAHL -> TATL
MOVE.B #"+", 10(A2) ;MIT PLUS INITIALISIEREN
TST.B D0
BEQ NUM135 ;NUR ENTER-TASTE
CMP.B #"-",(A2)
BNE NUM030
NUM010: MOVE.B (A2),D0 ;VORZEICHEN RETTEN
MOVE.L A2.A0
MOVE.L A2 , A 1
ADDQ.L #1,A1
MOVE #9,D1 ;10 STELLEN UM 1 STELLE
NUM020: MOVE.B (A1)+,(A0)+ ;NACH LINKS
DBRA D1,NUM020
MOVE.B D0,10(A2) ;VORZEICHEN
BRA NUM040
NUM030: CMP.B #"+",(A2)
BEQ NUM010
BRA NUM045
NUM040: SUBQ.B #1,-1(A2)
NUM045: MOVE.B -1(A2),D0 ;NACH DEZIMALPKT SUCHEN
EXT.W D0 ; IN LANGE TATL
SUBQ #1,D0
MOVE.L A2,A0 ;AB ERG
NUM050: CMP.B #".",(A0)+
DBEQ D0,NUM050
TST D0
BMI NUM080 ;NICHT GEFUNDEN
SUBQ.L #1,A0
MOVE.L A2,D0 ;ANZAHL NACHKOMMAST. ERRECHNEN
SUB.L A0,D0 ;(ADR.ERG + TATL-ADR.PKT - 1)
SUBQ.L #1,D0
MOVE.B - 1(A2), D1
EXT.W D1
EXT.L D1
ADD.L D1,D0
MOVE.B D0,11(A2)
CMP.B #0,D0
BEß NUM070 ;KEINE NACHKOMMASTELLEN
MOVE.L A0,A1 ;PUNKT ENTFERNEN
ADDQ.L #1,A1 ;AO=EMPF.-FLD, A1=SENDEFELD
SUBQ.L # 1 , D0 ;IN LANGE NACHKOMMASTELLEN
NUM060: MOVE.B (A1)+,(A0)+
DBRA D0,NUM060
NUM070: SUBQ.B #1,-1CA2)
BRA NUM090
NUMCT80: CLR.B 11CA2)
NUM090: MOVE.B -1(A2.),D0 ! RECHTSBÜNDIG VERSCHIEBEN
EXT.W D0
SUBQ # 1 , D0 ; IN LANGE TATL
BMI NUM130 J NUR PUNKT EINGEGEBEN
MOVE.B -1(A2),D1 ;A0=SENDEFELD
EXT.W D1
EXT.L D1
MOVE.L D1,A0
ADD.L A2,A0
MOVE.L A2,A1 ;A1=EMPFANGSFELD
ADD.L #10,A1
NUM100: MOVE.B -(A0),-(A1)
DBRA D0,NUMIOO
MOVE.B - I(A2),D0 ;FÜHRENDE NULLEN EINFÜGEN
NEG.B D0 ;LANGE= 10 - TATL
EXT.W D0
ADD.W #9,D0
TST.W D0
BMI NUM115
MOVE.L A2,A0
NUM110: MOVE.B #"0",(A0)+
DBRA D0,NUM110
NUM115: MOVE #9,D0 ;PRÜFUNG AUF NUMERISCH
MOVE.L A2,A0
NUM120: CMP.B #”O"- 1,<A0>
BLS NUM130 ;FEHLER
CMP.B #-9",CA0)+
DBHI D0,NUM120
TST D0
EMI NUM140 ;OK, NUMERISCH
NUM130: MOVE.L #-1,D0
NUMEXIT: MOVEM.L (SP)+,D1/A0-A2
RTS
NUM135: MOVE.L #-2,D0
BRA NUMEXIT
NUM140: CMP.B #"3",(A2) ;ZAHL > 3.999.999 999
BHI NUM 1 30 ; JA , ZU GROß
MOVE.W #9,D0 ;1. SIGNIF.ZIFFER ERMITTELN
MOVE.L A2,A0
NUM150: CMP.B #"0“,(A0)+
DBNE D0,NUM150
SUB.L A2,A0
SUBQ.L #1,A0
MOVE.W A0,D0
MOVE.B D0,12(A2)
CLR.L D0
BRA NUMEXIT
ABGLEICH: MOVEM.L D1-D3/A1/A2,-(SP)
MOVE.L #REFE1,A1
MOVE.L #REFE2,A2
ABGOOO: MOVE.B 11(A1),D1
CMP.B 11 ( A2 ) , D1 > KOMMA 1 > K0MMA2 ?
BGT ABG020 JJA
BLT ABG010 ;KOMMA2 > KOMMA 1
MOVEM.L (SP)+,D1-D3/A1/A2
RTS
ABG010: EXG A1,A2
^BG020: MOVE.B 12(A2),D1
CMP.B D0,D1 ;MINIMALWERT SIGNI ERREICHT
BLE ABG030 ;JA
MOVE.B 12(A2),D1 :REFE2 UM 1 STELLE NACH LINKS
EXT.W Dl
EXT.L D1 1SIGNI2 + ADR REFE2
ADD.L A2,D1 ;= ADR SENDEFELD -> Dl
MOVE.L D1,D2 ;ADR SENDEFELD - 1
SUBQ.L #1,D2 ;= ADR EMPFFLD -> D2
CLR.L D3 JLANGE
MOVE.B 12(A2),D3 ;=
NEG.L D3 1 -SIGNI2
ADD.L #10,D3 1 +10 -> D3
TRANSFER D1,D2,D3
MOVE.B #"0",9(A2) ;NULL EINFÜGEN
ADDQ.B #1,11(A2) ;KOMMA2 + 1
SUBQ.B #1,12(A2) 1SIGNI2 - 1
BRA ABG000
ABG030: MOVE.L Al,D1 ;REFE1 UM 1 STELLE NACH RECHTS
MOVE.L D1,D2
ADDQ.L #1,D2
TRANSFER D1,D2,#9
MOVE.B #"0",< A1>
SUBQ.B #1,11CA1)
ADDQ.B #1,12 < A 1 >
MOVE.B #-1,GENAU
BRA ABGOOO
UEPLUS: MOVEM.L A1/A2,-(SP) ;ÜBERLAUFPRÜFUNG
MOVE.L #REFE1,A1 ;ADD ITION/SUBTRAKTION
MOVE.L #REFE2,A2
UEPLUS1: CMP.B #2,12<A1> 1SIGNI1 < 2 ?
BLT UEP020 ;JA
UEPOOO: CLR.L D0
UEP010: MOVEM.L (SP)+,A1/A2
RTS
UEP020: CMP.B #2,12<A2) JSIGNI2 < 2 ?
BGE UEPOOO J NE IN
CMP.B #0,11(A1) ;KOMMA 1 > 0 ?
BGT UEP030 1JA
MOVE.L #-1,D0 ;ÜBERLAUF
BRA UEPOIO
UEP030: MOVE.L #UEPLUS1,-(SP) ;RÜCKSPRUNGADRESSE
MOVEM.L D1-D3/A1/A2,-(SP)
JMP ABG030
PLUS: MOVEM.L Dl-D3/A2,-CSP)
MOVE.B #2,D0 J MINIMALWERT SIGNI
CLR.B GENAU
JSR ABGLEICH
JSR UEPLUS
TST.L D0
BEQ PLU020 ;KEIN ÜBERLAUF
PLU010: MOVEM.L (SP)+,D1-D3/A2
RTS
PLU020: MOVE.L #REFE2,A2
JSR ASCBI
MOVE.L D1,D2
MOVE.L #REFE1,A2
JSR ASCBI
CMP.B #"+".REFE1+10
BEQ PLU030
CMP.B .REFE2+10
BEQ PLU070
BRA PLU040
PLU030: CMP.B #"+",REFE2+10
BEQ PLU060
PLU040: CMP.L D2.D1
BHI PLU050
EXG D1,D2
MOVE.B REFE2+10,D3
BRA PLU055
PLU050: MOVE.B REFE1+10.D3
PLU055: SUB.L D2,D1
BRA PLU999
PLU060: MOVE.B #"+",D3
PLU065: ADD.L D2,D1
BRA PLU999
PLU070: MOVE.B #"-",D3
BRA PLU065
PLU999: JSR BINASC
MOVE.B D3,REFE1+10
JSR NULWEG
BRA PLU010
MINUS: EOR.B #6,REFE2+10 JVORZEICHEN INVERTIEREN
JSR PLUS
EOR.B #6,REFE2 +10
RTS
DURCH: MOVEM.L D 1-D5/AO,-CSP)
MOVE.L #1,00 ;MINI MALWERT SIGNI = 1
CLR.B GENAU
JSR ABGLEICH
MOVE.B REFE1+10,D0 ;VORZEICHEN REFE1
CMP.B REFE 2 + l0,D0 ;= VORZEICHEN REFE2 ?
BNE DU002 ;NEIN, ERGEBNIS NEGATIV
MOVE.B #"+",-(SP) ;JA, ERGEBNIS POSITIV
BRA DU004
DU002: MOVE.B #"-',-(SP)
DU004: MOVE.L #REFE2,A2
JSR ASCBI
MOVE.L D1,D3 ;REFE2 -> D3
MOVE.L #REFE1,A2 :REFE1 = DIVIDEND
JSR ASCBI ; -> Dl
TST.L D3 ;DIVISOR = 0
BNE DU006
DU005: MOVE.B (SP)+,D0 ;ÜBERLAUF ODER /O, STACKKORREKTUR
MOVE.L #-1,D0 ;FEHLERANZEIGER
BRA DU999
DU006: JSR DIVI
DU007: JSR BINASC ;VORKOMMAST. -> REFE1
MOVE.L #REFE1,D4 ;ADREMPF -> D4
CLR.L D1 JSIGNI + ADRREFE1
MOVE.B REFE1+12,D1 ;=
ADD.L D4,D1 ;ADRSEND -> Dl
MOVE.B REFE1+12,D0
NEG.B D0 SIGNI
EXT.W D0 ;+ 10
ADD.W #10,D0 ;= LÄNGE -> D0
TRANSFER D1,D4,D0
MOVE.B REFE1 + 12, D1
NEG.B D1 SIGNI
EXT.W D1 ;+ ADRREFE1
EXT.L D1 ;+ 10
ADD.L #REFE1+10,D1 J = ADREMPF -> Dl
MOVE.B REFE1+12,D0 ;LANGE = SIGNI -> D0
EXT.W D0
FILL D1,D0,#"0" JRECHTS NULLEN EINFÜGEN
MOVE.B REFE1+12,D5
SUBQ.B #1,D5
BMI DU020
EXT.W D5
EXT.L D5
MOVE.L #0,A0
SUB.L D5,A0
ADD.L #REFE1+9,A0
DU010: TST.L D2 ;REST = 0 ?
BEQ DU020 : JA
MOVE.L #10,D1
JSR MULTI ;REST * 10
TST D0 ;ÜBERLAUF ?
BMI DU005 ;JA
DUO 15: JSR DIVI ;/ DIVISOR
OR.B #$30,D1 ;= NÄCHSTE NACHKOMMASTELLE
MOVE.B D1,(A0)+
DBRA D5.DU010
DU020: MOVE.B REFE1+12,REFE1+11 ;KOMMA = SIGNI
CLR.B REFE1+12 JSIGNI = O
DUEXIT: MOVE.B (SP)+,REFE1+10 JVORZEICHEN EINSTEUERN
JSR NULWEG
CLR.L D0
DU999: MOVEM.L (SP)+,D1-D5/AO
RTS
MAL: MOVEM.L D 1/D2/A1/A2,-<SP>
CLR.B D0
CLR.B GENAU
MOVE.B REFE1+10,D0
CMP.B REFE2+10,D0
BNE MA020
MOVE.B #"+",-(SP>
BRA MA025
MA020: MOVE.B #"-",-<SP)
MA025: MOVE.L #REFE2,A2
JSR ASCBI
MOVE.L D1,D2
MOVE.L #REFE1 , A2
JSR ASCBI
JSR MULTI
TST.B D0
BPL MA030
BRA MA040
MAEXIT: MOVE.B (SP)+,REFE1+10
JSR NULWEG
MA999 : MOVEM.L <SP>+,D1/D2/A1/A2
RTS
MA030: MOVE.B REFEl+ll.D0
ADD.B REFE2+11,D0
CMP.B #10,D0
BGT MA045
MOVE.B D0,REFE1+11
JSR BINASC
TST.B D0
BEQ MAEXIT
NEG.B D0
ADD.B #10,D0
BNE MA032
CLR.B REFE1+12
BRA MAEXIT
MA032: CMP.B REFE1+12.D0
BLT MA034
BRA MAEXIT
MA034: SUBS.B #1,D0
MOVE.B D0,REFE1+12
BRA MAEXIT
MA040: MOVE.B REFEl + ll.D0
CMP.B REFE2+11,D0
BGT MA042
TST.B REFE2+1 1
BEQ MAO 45
MOVE.L #REFS2,A1
MA04S: JSR MAC60
MOVE.B #-i,GENAU
BRA MA025
MA042: MOVE.L #REFE1,A1
BRA MA041
MA045: MOVE.L #-1,D0
ADDQ.L #2,SP
BRA MA999
MAOGO: MOVE.L Al,D1
MOVE.L D1.D2
ADDQ.L #1,D2
TRANSFER D1,D2,#9
MOVE.B #"0“,(A1)
SUBQ.B #1, 1 1 (A 1)
ADDQ.B #1, 1 2 C A1)
RTS
NULWEG: MOVEM.L D1/D2/A1,-<SP) »RECHTSBÜNDIGE NULLEN ENTFERN
MOVE.L fiREFEl,Al
NULOOO: CMP.B #"0".REFE1+9
BNE NUL005
TST.B REFE1+11
BNE NUL010
NUL005 : MOVEM.L (SP) + ,D1/D2/A1
RTS
NUL010: MOVE.B REFE1+12,D1
CMP.B #9,D1
BGE NUL005
JSR MAOGO
BRA NULOOO
ROUND: MOVEM.L D1-D3/A3,-(SP)
MOVE.B 11(A2),D1 ;TATSACHL.KOMMAST. -> Dl
SUB.B D0,D1 GEWÜNSCHTE KOMMAST.
CMP.B #1,D1
BLT R0020 :HAT SICH ERLEDIGT
MOVE.B D0.1KA2) ; NEUE = GEWÜNSCHTE KOMMAST.
EXT.W D1 ;= VERSCHIEBELÄNGE -> Dl
EXT.L D1
MOVE.L D1.D2 JIO - VERSCHIEBELANGE
NEG.L D2 ;=
ADD.L #10,D2 ;TRANSFERLÄNGE -> D2
MOVE.L D2,A3
CMP.B #$34,0(A3,A2) ;ABKNEIFSTELLE > 4 ?
BLE ROOIO ,-NEIN
MOVE.B #-1,D0 5MERKMAL RUNDEN
ROOIO: MOVE.L D1.D3 ;VERSCHIEBELÄNGE RETTEN
ADD.L A2,D1 ;REFE+VERSCHIEBELÄNGE=EMPF.-ADR.
TRANSFER A2,D1,D2
FILL A 2,D 3,#"0"
CMP.B #-1,D0 :RUNDEN ?
BNE R0012 ;NEIN
JSR ASCBI ;ZAHL -> Dl
ADDQ.L #1,D1 ;+1
JSR BINASC ;ZAHL ZURÜCK
R0012: MOVE.W #9,D0 ; 1 . SIGNIF.ZI FF.ERMITTELN
MOVE.L A2,A0
R0015: CMP.B #“0",(A0)+
DBNE D0,ROO15
SUB.L A 2,A0
SUBQ.L #1,A0
MOVE.W AO,D0
MOVE.B D0,1 2(A2)
R0020: MOVEM.L (SP)+,D1-D3/A3
RTS
KNEIF: MOVEM.L D1-D3/A3,-(SP)
MOVE.B I1<A2),D1 ;TATSACHL.KOMMAST. -> Dl
SUB.B D0,DI GEWÜNSCHTE KOMMAST.
CMP.B #1,D1
BLT KN020 ;HAT SICH ERLEDIGT
MOVE.B D0,11(A2) » NEUE = GEWÜNSCHTE KOMMAST.
EXT.W D1 ;= VERSCHIEBELÄNGE -> Dl
EXT.L D1
MOVE.L D1,D2 510 - VERSCHIEBELÄNGE
NEG.L D2 ;=
ADD.L #10,D2 ;TRANSFERLÄNGE -> D2
MOVE.L D2,A3
KN010: MOVE.L D1.D3 ;VERSCHIEBELÄNGE RETTEN
ADD.L A2.D1 ;REFE+VERSCHIEBELÄNGE=EMPF.-ADR.
TRANSFER A2,D1,D2
FILL A2,D3,#"0"
KN012: MOVE.W #9,D0 ;1.SIGNIF.ZI FF.ERMITTELN
MOVE.L A2,A0
KN015: CMP.B #"0",(A0>+
DBNE D0,KNO15
SUB.L A2,A0
SUBQ.L #1,A0
MOVE.W AO,D0
MOVE.B D0,12 C A 2 >
KN020: MOVEM.L (SP)+,D1-D3/A3
RTS
BINASC: MOVEM.L D0-D3/AO/A2,-(SP)
MOVE.L #10,D3 1DIVIS0R
MOVE.L A2,A0
MOVE #10,D0 »11 STELLEN ERGEBNIS
BINAOOO: MOVE. B #“0",(A0>+ »‘NULLEN EINFÜGEN
DBRA D0,BINAOOO
MOVE.B #-+-,-<A0>
BINA020: JSR DIVI
OR.B #$30,D2 »REST
MOVE.B D2,-(A0)
CMP.L #0,D1 ;QUOTIENT = 0 ?
BEQ BINA030 1JA, FERTIG
JMP BINA02O
BINA030: MOVE.W #9,D0 11.SIGNIF.ZIFF.ERMITTELN
MOVE.L A2,A0
BINA040: CMP.B #"0",(A0)+
DBNE D0,BINA040
SUB.L A2,A0
SUBQ.L #1,A0
MOVE.W A0,D0
MOVE.B D0,12(A2)
MOVEM.L (SP)+,D0-D3/AO/A2
RTS 1 ASCII STEHT BEREIT
ASCBI: MOVEM.L D0/D2/D3/A0-A2,-(SP)
MOVE.W #9,D3 ;10 STELLEN
MOVE.L A2,A0
CLR.L D1
MOVE.L #10,D2
AS010: MOVE.L D0,-(SP)
JSR MULTI
MOVE.L (SP)+,D0
MOVE.L D1,A1
CLR.L D1
ADD.B (A0)+,D1
SUB.B #$30,D1
ADD.L A1,D1
DBRA D3,AS 010
MOVEM.L (SP)+,D0/D2/D3/A0-A2
RTS
DIVI: MOVEM.L D0/D3/D4,-(SP)
MOVE.L D3,D4
MOVE #31,D0
CLR.L D2
CLR.L D3
DIVI020: ROXL.L #1,D1 iDIVIDEND IN Dl
ROXL.L #1,D2 :1 BIT VON Dl NACH D2 ZIEHEN
ASL.L #1,D3 1 QUOTIENT 1 BIT SCHIEBEN
SUB.L D4,D2 1DIVIS0R IN D4
BMI DI VI040
ADDQ.L #1,D3 ;QUOTIENT IN D3
DI VI030: DBRA D0,DIVI0'2O
MOVE.L D3,D1
MOVEM.L (SP)+,D0/D3/D4
RTS
DIVI040: ADD.L D4,D2 ;WIEDERHERSTELLEN
BRA DIVI030
MULTI: MOVEM.L D2-D4,-(SP)
CLR.L D3
CLR.B D4
MOVE.W #31,D0
MUL010: ROR.L #1,D2
BCC MUL020
TST.B D4
BMI MUL015
ADD.L D1,D3
BCC MUL020
MUL015: MOVE.L #-1,D0
BRA MULEXIT
MUL020: ASL.L #1,D1
BCC MUL030
MOVE.B #-1,D4
MUL030: DBRA D0.MÖLOIO
MOVE.L D3,D1
CLR.L D0
MULEXIT: MOVEM.L (SP)+,D2-D4
RTS
EDIT: MOVEM.L D0-D7/AO-A2,-(SP)
MOVE.B EDFLD,D5 !LÄNGE EMPFANGSFELD RETTEN
MOVE.B EDFLD+1,D6 iGEWÜNSCHTE NACHKOMMASTELLEN
MOVE.B #10,D0 ;LÄNGE VORKOMMASTELLEN
SUB.B 11(A2),D0
SUB.B 12(A2),D0
CMP.B #0,D0
BGT ED005
CLR.B D0
ED005: EXT.W D0 ;NACH D0
EXT.L D0
MOVE.B D6,DI ; WENN GEWÜNSCHT. NACHKOMMAST.
ADDQ.B #2,D1 ;+ LÄNGEN DEZIMALPUNKT U. VORZEICH.
ADD.B D0,D1 ;+ LÄNGE VORKOMMASTELLEN
CMP.B D5,D1 ; > FELDLANGE EDFLD, DANN
BHI ED030 ; EDFLD ZU KURZ
MOVE.B D5,D1 5GEWÜNSCHTE EMPFANGSLÄNGE
SUB.B D6.D1 GEWÜNSCHTE NACHKOMMASTELLEN
SUBQ.B #1,D1 1
EXT.W Dl
EXT.L D1
ADD.L #EDFLD,D1 ;+ ADR. EDFLD
MOVE.L D1,A1
MOVE.B A1) ;= ADR. DEZIMALPUNKT
MOVE.L D1,D3 ;RETTEN
SUB.L D0,D1 LANGE VORKOMMASTELLEN
MOVE.L D1,D4 ;RETTEN
MOVE.B 12 < A2),D2 1DISPLACEMENT 1.SIGNIF.STELLE
EXT.W D2
EXT.L D2
ADD.L A2,D2 ;+ ADR. ERG
TRANSFER D2.D1.D0
MOVE.B #10,D1 110
SUB.B 11(A2),D1 5- NACHKOMMASTELLEN
EXT.W Dl
EXT.L D1
ADD.L A2,D1 ;+ ADR ERG
MOVE.L D3,D2 ;ADR DEZIMALPUNKT
ADDQ.L #1,D2 ;+l = EMPFANGSADR.NACHKOMMA -> D2
CMP.B 11(A2),D6 ITATSACHL.VORH./GEWÜNSCHT.NACHKOMMAST
BGT ED020 ;MEHR GEWÜNSCHT ALS.VORHANDEN
MOVE.B D6,D0
ED010: EXT.W D0
TRANSFER D1,D2,D0
MOVE.L D4,D0 ;EMPF.ADR. VORKOMMASTELLEN
SUB.L #EDFLD,D0 ADR EDFLD
FILL #EDFLD,D0,#" * ;FÜHRENDE BLANKS EINFÜLLEN
CMP.B #*-",10(A2) JNEGATIVES VORZEICHEN ?
BNE ED999 ;NEIN
MOVE.L D4,A0 ;EMPF.ADR.VORKOMMASTELLEN
SUBQ.L #1,A0 1
MOVE.B #"-■*, CAO) ;= VORZEICHENSTELLE
ED999: MOVEM.L (SP) +, D.0-D7 / A0-A2
RTS
ED020: MOVE.B D6,D0 ; GEWÜNSCHTE NACHKOMMASTELLEN
SUB.B 11(A2),D0 ; VORHANDENE
EXT.W D0 ; MIT NULLEN AUFZUF.STELLEN
MOVE.B 11<A2>,D7 ;VORHANDENE NACHKOMMASTELLEN
EXT.W D7
EXT.L D7
ADD.L D2,D7 ;+ EMPF.ADR.NACHKOMMASTELLEN
FILL D7,D0,#"0" ;NACHKOMMASTELLEN AUFFÜLLEN
MOVE.B 11<A2),D0 ;IN TATSÄCHL.VORH.LÄNGE
BRA ED010 ;üBERTRAGEN
ED030: FILL #EDFLD,D5,#"#" ; AUFFÜLLEN MIT #, DA ZU KURZ
BRA ED999
ENDSTAND: EQU *