← ST-Computer 01 / 1987

ISAM & PRIMA Teil 3 - die Standardroutinen

Software

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:

INPUT - Eingabe von Zeichen von der Tastatur

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.

NUMERIC - Eingabe von numerischen Zeichen von der Tastatur

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.

ABGLEICH - Kommastellen von REFE1 und REFE2 aufeinander abgleichen

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.

UEPLUS - Überlaufkontrolle für Addition und Subtraktion

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.

PLUS - Addition zweier Werte

Durch Aufruf dieser Routine werden die beiden Rechenfelder REFE1 und REFE2 addiert. Das Ergebnis steht anschließend in REFE1.

MINUS - Subtraktion zweier Werte

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.

DURCH - Division zweier Werte

Diese Routine dividiert REFE1 und REFE2. Das Ergebnis steht in REFE1.

MAL - Multiplikation zweier Werte

Durch diese Routine wird REFE1 mit REFE2 multipliziert. Das Ergebnis steht wieder in REFE1.

KNEIF - Abschneiden von Kommastellen ohne Runden

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.

ROUND - Runden der Nachkommastellen

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.

BINASC - Umwandlung von Binär- in ASCII-Format

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.

ASCBI - Umwandlung von ASCII- in Binär-Format

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.

DIVI - 32 Bit Division

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.

MULTI - 32 Bit-Multiplikation

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.

EDIT - Editierroutine

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 *