	OPT	PAG
	TTL	Berechnung unendlicher Reihen
	STTL	Berechnung von e

*****************************************
*	Berechnung unendlicher Reihen	*
*****************************************
*
* Dieses Programm stellt einige Hilfsmittel zur Verf}gung, um die
* Summe unendlicher Reihen, bei denen ein rekusiver Zusammenhang der
* Glieder besteht, auf mehrere tausend Dezimalen zu berechnen. Es
* besteht die M|glichkeit, den zur Verf}gung stehenden Speicher
* in eine beliebige Anzahl von sog. Langvariablen(Lvar) aufzuteilen.
* Diese bestehen aus einem Byte, dem Vorkommateil, und dem Rest,
* = Nachkommateil, jeweils bin{r dargestellt. Um diese Lvar al-
* gebraisch verkn}pfen zu k|nnen, sollten sie alle dieselbe L{nge
* besitzen. F}r jede Lvar wird in der DP ein Anfangs- und ein End-
* zeiger definiert. (mit <nam>ANF und <nam>END, die Macros beziehen
* sich sp{ter auf die Bezeichnung <nam>.)
* Die zur Verf}gung stehenden 'unendlichen' Arithmetikroutinen wur-
* den in Macros zusammengefa~t, die einen Unterprogrammsprung ent-
* halten. Das Hauptprogramm gestaltet sich so sehr einfach.
* Einzelheiten hierzu stehen unter den jeweiligen Macros.
* Mit P oder O kann die Ausgabe auch auf andere Devices umgeleitet
* werden.
*
***************************************
*	Berechnung der Zahl e	
*
***************************************
*
* Die Zahl wird nach folgender unendlichen Reihe berechnet:
*
*	
1	1	1	1
* e	:=	1 + -- + -- + -- + -- + ..
*	
1!	2!	3!	4!
*
* Ablauf der Rechnung:
* Es werden zwei variable Speicherbereiche angelegt, in dem einen
* werden die jeweils aktuellen Glieder berechnet (Glied1), in dem anderen
* befindet sich die aktuelle Summe (Summe). Au~erdem wird die Anzahl der
* Glieder (von 0 beginnend) in N abgelegt.
* Glied und Summe m}ssen jeweils dasselbe Format haben. Das erste
* Byte gibt dabei jeweils die Vorkommastelle, alle folgenden die
* Dezimalen.
* In jedem Durchgang wird nun das alte Glied durch N dividiert und
* das Ergebnis zur Summe addiert.
* Die Berechnung wird abgeschlossen, wenn Glied den Inhalt 0 (letztes
* Byte kann auch <> 0 sein) hat.
* Anschlie~end erfolgt die Ausgabe der Zahl durch stetiges Multipl.
* von Summe mit 10. Dadurch wird eine nach der anderen Dezimale vor
* das Komma geschoben und kann ausgegeben werden.
* Mit P oder O kann die Ausgabe auch auf andere Devices umgeleitet
* werden.
*
* Wolfgang Schwotzer	
29.05.86
	PAG
*
* System Equates:

DPVAR	EQU	$C1	Direct Page
PUTCHR EQU	$CD18	ASCII-Zeichen auf Device ausgeben
OUTCH2 EQU	$CD12	Zeichen auf Bildschirm ausg.
PSTRNG EQU	$CD1E	String ausgeben
PCRLF	EQU	$CD24	neue Zeile auf Device
OUTDEC EQU	$CD39	Dezimalzahl ausgeben
WARMS	EQU	$CD03	zur}ck ins Betriebssystem
INBUFF EQU	$CD1B	Auf Eingabe warten
INDEC	EQU	$CD48	Dezimalzahl einlesen
CR	EQU	$D		Carriage return
LF	EQU	$A		Line feed

	ORG	DPVAR*$100
	FCC	'	',1
	FCC	'(C) W.S. Number Crunch',CR,LF

	FCC	'	Wolfgang Schwotzer',CR,LF,4

	ORG	DPVAR*$100
	SETDP DPVAR

BEGIN	BRA	ANF
VERSIO FCB	1
*
* Interne Variablen:
*
MAXCH	FCB	72		Maximalzahl der ausg. Zeichen/Zeile
RG1ANF FDB	0	
Zwischenreg. Anfangszeiger
RG1END FDB	0	
Zwischenreg. Ende-Zeiger
RG2ANF FDB	0	
Zwischenreg.2 Anfangszeiger
RG2END FDB	0	
Zwischenreg.2 Ende-Zeiger
REG	FDB	0	
Zwischenregister
UEBER	FDB	0	
16 Bit ]bertrag bei der Multipl.
MULRG2 FDB	0	
Zwischenregister bei UMULT
MULRG1 EQU	*-1	Zwischenregister bei UMULT
CHO	FCB	0	
Z{hler f}r ausgeg. Zeichen/Zeile
STCNT	FDB	0	
Z{hler f}r Anz. der Dezimalen bei der Ausg.
ANZDEZ FDB	0	
Anzahl der Dezimalen in Ziffern
*
* Problembezogene Variablen
*
LAENGE FDB	0	
L{nge der Lvar in Byte, nach Eingabe
SANF1	FDB	0	
Zeigt auf erste Dezimale in R. = [SANF]+1
SEND1	FDB	0	
Zeigt auf ein Byte hinter letzte Dezimale
N	FDB	0	
= 16 Bit Summenz{hler
ZWEIN1 FDB	0	
= 2 * N + 1
*
* Anfangs- und Endzeiger der Lvar:
*
SANF	FDB	0	
Anfangszeiger auf Summe
SEND	FDB	0	
Zeiger auf letzte Stelle von S.
G1ANF	FDB	0	
Anfangszeiger auf Glied1
G1END	FDB	0	
Zeiger auf letzte Stelle von G1
	PAG

*********************
* Macrodefinitionen *
*********************
*
* Syntax: PLACE Lvar1
* Macro zur Zuweisung einer Variable Lvar1 von Speicherplatz der
* L{nge D+1. X zeigt zu Beginn auf die Anfangsadresse der Var. und
* danach auf das 1. Byte nach Lvar1. Au~erdem wird die Variable auf
* 0 gesetzt.
*
PLACE	MACRO
	STX	&1ANF	Anfanspointer setzen
	LEAX	D,X	L{nge dazu
	STX	&1END	Endpointer setzen
	LEAX	1,X	= Anfangspos. der n{chsten
	TFR	X,Y	Variablen
	CLR	,-Y	gesamte Variable l|schen
	CMPY	&1ANF
	BNE	*-5	**** VORSICHT	*************
	ENDM
*
* Syntax: LDIV Lvar1,Var2
* Macro zur Einleitung und Ausf}hrung einer Division. Lvar1 ist der
* Divisor, Var2 der Dividend u.z. keine Langvariable, sonder ein in
* der DP definierter 16 Bit Integer. Var2 kann auch Immediate sein.
* (z.B. #$32). Sie darf max. den Wert 32767 haben.
*
MDIV	MACRO
	LDX	&1ANF
	STX	RG1ANF
	LDX	&1END
	STX	RG1END
	LDX	&2		Dividend als 16Bit-Wert direkt
	STX	RG2ANF	in RG2ANF }bertragen
	LBSR	DIVI
	ENDM
*
* Syntax: LADSU Lvar1,Lvar2,Var3,Var4
* Macro zur Addition bzw Subtraktion zweier Langvariablen. Leitet
* eine Addition bzw Subtraktion ein. Die Summe wird in Lvar1 abge-
* legt. Ist Var3 gerade, wird addiert, sonst subtrahiert. Var4 er-
* m|glicht es, zum Inhalt von Var3 noch #1 hinzuzuz{hlen. Hierzu
* mu~ Var4 mit '+1' belegt sein (ohne Quotes). Var3 ist 16 Bit
* entweder in der DP oder immediate.
*
MADSU	MACRO
	LDX	&1ANF
	STX	RG1ANF
	LDX	&1END
	STX	RG1END
	LDX	&2ANF
	STX	RG2ANF
	LDX	&2END
	STX	RG2END
	LDD	&3		Var3 direkt in D-Reg.
	IFC	&4,+1	Wenn Var4 = +1, dann
	ADDD	#1		D := D + 1
	ENDIF
	LBSR	UADSU
	ENDM
*
* Syntax: MMULT Lvar1,Var2
* Macro zur Einleitung einer Multiplikation von Lvar1 mit Var2.
* var2 ist dabei ein 16Bit-Wert.(immed. oder direct). Achtung:
* ]bertr{ge }ber die erste Vorkommastelle von Lvar1 werden
* ignoriert.
*
MMULT	MACRO
	LDX	&1ANF
	STX	RG1ANF
	LDX	&1END
	STX	RG1END
	LDX	&2
	STX	REG
	LBSR	UMULT
	ENDM
*
* Syntax: TRANS	Lvar1,Lvar2
* Macro zur Einleitung einer Kopie von Lvar2 nach Lvar1. Lvar1 und
* Lvar2 m}ssen dieselbe L{nge haben.
*
TRANS	MACRO
	LDX	&1END
	STX	RG1END
	LDX	&2END
	STX	RG2END
	LDX	&1ANF
	STX	RG1ANF
	LBSR	BTRANS
	ENDM
*
* Syntax: MOUTV var1
* Macro zur Ausgabe einer Variable Lvar1. Die Variable hat danach
* keinen definierten Zustand. Mit der DP-Variable ANZDEZ mu~ vor-
* her die Anzahl der auszugebenden Dezimalen festgelegt werden.
*
MOUTV	MACRO
	LDX	&1ANF
	STX	RG1ANF
	LDX	&1END
	STX	RG1END
	LBSR	UOUTV
	ENDM
*
* Syntax: MTSTV Lvar
* Macro Testet die Variable Lvar, ob sie Null ist. Bei Null ist
* EQ-Condition.
*
MTSTV	MACRO
	LDX	&1ANF
	STX	RG1ANF
	LDX	&1END
	STX	RG1END
	LBSR	UTSTV
	ENDM
	PAG

*******************
*	Programmstart	*
*******************
*
ANF	LDA	#DPVAR
	TFR	A,DP
*
* Ein- und Ausgabe
*
	LEAX	THALLO,PCR
	LBSR	PDATA	'Berechnung von e'
	LEAX	TFRAGE,PCR 'L{nge des Speicherplatzes'
	LBSR	PDATA
	JSR	INBUFF	Dezimalzahl
	JSR	INDEC	eingeben
	LBCS	ERROR
	TSTB
	LBEQ	ERROR
	CMPX	#24576	mu~ < 48 KByte/2 sein
	LBHI	ERROR
	CMPX	#3		mindestens 3 Byte
	LBLO	ERROR
	STX	LAENGE	Wert abspeichern
	LEAX	TNL,PCR
	LBSR	PDATA
*
* Vorbereitung:
*
	LDD	LAENGE	L{nge der Var. in D
	SUBD	#1		Korrektur
	LDX	#0		Startadr. f}r Var.Speicher
	PLACE S	
Summe l|schen
	LDX	LAENGE	L{nge der Zahl in Byte
	STX	[SANF]
	MDIV	S,#5	div. durch 5
	MMULT S,#12	Mult. mit 12; 12/5 = 2.4
	LDX	[SANF]	= L{nge d. Zahl in Dezimalen
	LEAX	-3,X	3 Dezimalen weniger
	STX	ANZDEZ	abspeichern
	LDX	#0
	PLACE S	
Summe platzieren,l|schen
	PLACE G1		Glied1	"
*
	LDX	G1ANF
	LDA	#1
	STA	,X+	Glied1 := 1
*
	LDX	SANF
	LDA	#1
	STA	,X+	Summe := 1
*
	LDD	#0
	STD	N	
N := 0

*************************
*	Hauptprogramm	*
*************************

LOOPP	LDD	N
	ADDD	#1
	STD	N	
N := N + 1
	MDIV	G1,N	Glied1 := Glied1 / N
	MADSU S,G1,#0,0	Summe := Summe + Glied1
	MTSTV G1		Bis Korrekturglied = 0
	LBNE	LOOPP
*
	LBSR	HEADER	'e =' ausgeben
	MOUTV S	
Latch ausgeben
	LBSR	FOOTER	Anz der summierten Gl. ausg.
WRM	JMP	WARMS
*
ERROR	LEAX	TERRO,PCR
	LBSR	PDATA
	BRA	WRM
*
THALLO FCC	"calculation of number of euler e"
TNL	FCC	4
TFRAGE FCC	'size of memory in byte (<= 24576) : ',4
TERRO	FCC	'input error',4
	PAG

*
* Unterprogramm zum Kopieren einer Langvariablen
* ==============================================
* Quellvariable: RG2
* Zielvariable: RG1
* Beide Variablen m}ssen dieselbe L{nge haben, sonst
* wird }bertragen, bis der Anfang von RG1 erreicht ist.
*
BTRANS LDX	RG2END	X zeigt auf Quellvariable
	LDY	RG1END	Y zeigt auf Zielvariable
	LEAX	1,X
	LEAY	1,Y
BTR1	LDA	,-X	1 Byte von Quelle
	STA	,-Y	nach Ziel
	CMPY	RG1ANF	Bis Anfang von Var1 erreicht
	BNE	BTR1
	RTS
*
* Unterprogramm zur Berechnung einer "Unendlichen Division"
* =========================================================
* RG1 := RG1 / RG2ANF
*
* Der Divisor befindet sich dabei in der Langvariable RG1.
* Der Dividend befindet sich in der 16 Bit Intergervariable RG2ANF,
* VORSICHT: RG2 wird hier nicht wie sonst als Anfanszeiger benutzt.
* Es k|nnen nur Divisionen von ganzen positiven Zahlen von 1 bis
* 32767 durchgef}hrt werden.
* Der Dezimalpunkt des Divisors kann vom Benutzer beliebig definiert
* werden. Nach der Division steht er genau an derselben Stelle. Die
* Division wird Bit f}r Bit durchgef}hrt, indem ein 16-Bit breites
* Fenster Bit f}r Bit }ber den Divisor geschoben wird (Mit Rotate-
* Befehlen). Von diesem Bereich wird jeweils der Dividend abgezogen.
* Ist das Ergebnis negativ findet wieder eine Summation statt, und
* eine 0 wird in das Fenster zur}ckgeschrieben. Ist das Ergebnis
* negativ, so wird eine 1 zur}ckgeschrieben. Ist der gesamte Divisor
* (RG1) nicht aus lauter 16-Bit Paketen aufgebaut, sondern k*16-Bit
* + 8Bit, so findet die Division mit den letzten 8 Bit gesondert
* statt. Der Rest, der sich jeweils ergibt, wird nicht weiter be
* r}cksichtigt. Um ein korrektes Arbeiten des Algorithmus zu ga-
* rantieren, mu~ der Divisor mindestens 16-Bit breit sein.
*
DIVI	PSHS	X,Y,D
	LDD	RG2ANF	Dividend in D
	BEQ	DIV9	Bei Division durch 0 UPGM beenden
	LDX	RG1END
	LEAX	1,X
	STX	SEND1
	LDX	RG1ANF	Zeiger auf Anfang des Divisors
DIV00	LDA	,X+
	BNE	DIV0	Zeiger weiterr}cken, bis <> 0
	CMPX	SEND1	falls Ende erreicht, vorzeitiger
	BNE	DIV00	Abbruch
	BRA	DIV9
*
DIV0	LEAX	-1,X
	CMPX	RG1END
	BNE	DIV01
	LEAX	-1,X	Zahl mu~ mind. 16Bit Lang sein
DIV01	LDD	#0		16-BIT Fenster zun{chst Null
DIV1	LDY	#16	Pro Fenster 16 Durchl{ufe
DIV10	LSL	1,X	1 Bit aus dem Fenster ,X; 1,X
	ROL	,X		in das zu subrahierende Register
	ROL	B	
= D-Reg. }bertragen
	ROL	A
	SUBD	RG2ANF	Dividend subtrahieren
	BPL	POS1	falls positiv Sprung
	ADDD	RG2ANF	Sonst N wieder addieren
	BRA	NEG1
POS1	LSR	1,X	falls positiv 1 in Fenster zur}ck-
	SEC	schreiben (falls neg. steht die 0
	ROL	1,X	auf jeden Fall schon da)
NEG1	LEAY	-1,Y	gesamtes Fenster durchgeschoben?
	BNE	DIV10	nein, Sprung
*
	LEAX	1,X	Fenster-Zeiger um 1 weiter
	CMPX	RG1END	Zeiger am Ende angelangt?
	BEQ	DIV9	ja, Sprung
	LEAX	1,X	Zeiger noch 1 weiter
	CMPX	RG1END	Jetzt am Ende?
	BNE	DIV1	nein, Sprung
*
	LDY	#8		Hier ist noch 1 Byte zu
DIV2	LSL	,X		dividieren, nach dem selben
	ROL	B	
Prinzip, jedoch wird das
	ROL	A	
fehlende Byte durch Nullen
	SUBD	RG2ANF	ersetzt
	BPL	POS2
	ADDD	RG2ANF
	BRA	NEG2
POS2	LSR	,X
	SEC
	ROL	,X
NEG2	LEAY	-1,Y
	BNE	DIV2
*
DIV9	PULS	X,Y,D,PC
*
* Berechnung einer Unendlichen Summe oder Differenz. Falls das Reg.
* D eine gerade Zahl enth{lt, wird RG1 und RG2 addiert, sonst wird
* RG2 von RG1 subtrahiert. Das Ergebnis steht immer in RG1.
*
UADSU	BITB	#1
	BEQ	SUMME
	BRA	DIFF
*
* Unterprogramm zur Berechnung einer "Unendlichen" Summe
* ======================================================
* RG1 := RG1 + RG2
*
* Der Inhalt der Langvariable RG2, wird zum Inhalt der Langv. RG1
* hinzuaddiert. Der Dezimalpunkt beider Zahlen ist beliebig, es
* sollten jedoch bei RG1 und RG2 die selbe Anzahl an Dezimalen zur
* Verf}gung stehen. Au~erdem sollte RG2 nicht gr|~er als RG1 sein.
* In diesem Fall werden alle Stellen, die }ber das Format von
* RG1 hinausgehen ignoriert. Die beiden Langvariablen m}ssen min-
* destens 16Bit breit sein.
*
SUMME	PSHS	X,Y,D
	LDX	RG1ANF
	LEAX	1,X
	STX	SANF1	Zeiger auf Anfang + 1
	LDX	RG1END	Zeiger auf das Ende von RG1
	LDY	RG2END	Zeiger auf das Ende von RG2
	LEAX	1,X	Ende + 1
	LEAY	1,Y	Ende + 1
	CLRB	
zun{chst kein Carry
SUM1	CLRA	
(Carry 16 Bit)
	ADDD	,--X	Addiere 16 Bit von RG1
	PSHS	CC		Carry retten
	ADDD	,--Y	und 16 Bit von RG2
	STD	,X		Schreibe zur}ck nach RG1
	LDB	#0		l|sche B
	ADCB	,S+	Beide Carrys in B addieren
	ANDB	#1		Carry ist nur LSB
	CMPX	RG1ANF	Anfang von RG1 erreicht?
	BEQ	SUM9	ja, Sprung
	CMPX	SANF1	Anfang von RG1 + 1 erreicht?
	BNE	SUM1	nein, Sprung
*
SUM2	ADDB	,-X	nur 8 Bit addieren
	ADDB	,-Y	ohne Carry zu retten
	STB	,X
SUM9	PULS	X,Y,D,PC
*
* Unterprogramm zur Berechnung einer "Unendlichen" Differenz
* ==========================================================
* RG1 := RG1 - RG2
*
* Der Inhalt der Variable RG2, begrenzt durch RG2ANF und RG2END
* wird vom Inhalt der Variable RG1, begrenzt durch RG1ANF und RG1END,
* subtrahiert, und in RG1 zur}ckgeschrieben.
* Der Dezimalpunkt beider Zahlen ist beliebig, es sollten jedoch
* bei RG1 und RG2 die selbe Anzahl an Dezimalen zur Verf}gung
* stehen. Au~erdem sollte RG2 nicht gr|~er als RG1 sein.
* In diesem Fall werden alle Stellen, die }ber das Format von
* RG1 hinausgehen ignoriert.
*
DIFF	PSHS	X,Y,D
	LDX	RG1ANF
	LEAX	1,X
	STX	SANF1	Zeiger auf Anfang + 1
	LDX	RG1END	Zeiger auf das Ende von RG1
	LDY	RG2END	Zeiger auf das Ende von RG2
	LEAX	1,X	Ende + 1
	LEAY	1,Y	Ende + 1
	CLRB	
zun{chst kein Carry
DIFF1	CLRA
	PSHS	D	
Carry retten
	LDD	,--X	16 Bit von RG1 in D
	SUBD	,S++	Carry abziehen
	PSHS	CC		neues Carry retten
	SUBD	,--Y	und 16 Bit von RG2 abziehen
	STD	,X		Schreibe zur}ck nach RG1
	LDB	#0		l|sche B
	ADCB	,S+	Beide Carrys in B addieren
	ANDB	#1		Carry ist nur LSB
	CMPX	RG1ANF	Anfang von RG1 erreicht?
	BEQ	DIFF9	ja, Sprung
	CMPX	SANF1	Anfang von RG1 + 1 erreicht?
	BNE	DIFF1	nein, Sprung
*
DIFF2	NEGB
	ADDB	,-X	nur 8 Bit addieren
	SUBB	,-Y	ohne Carry zu retten
	STB	,X
DIFF9	PULS	X,Y,D,PC

*
* Unterprogramm zur Berechnung einer "Unendlichen" Multiplikation
* ===============================================================
* RG1 := RG1 * REG
*
* Die 16-Bit Variable REG, wird mit dem Inhalt der
* Variable RG1, begrenzt durch RG1ANF und RG1END, multipliziert, und
* in RG1 zur}ckgeschrieben. Der Dezimalpunkt von RG1 ist beliebig.
* Das Format mu~ jedoch so gew{hlt werden, da~ kein ]berlauf in
* RG1 entsteht. In diesem Fall werden alle Stellen, die }ber das
* Format von RG1 hinausgehen ignoriert.
*
UMULT	PSHS	X,Y,D
	LDX	RG1END	Zeiger auf das Ende von Summe
	LEAX	1,X	Ende + 1
	CLR	MULRG1	Zun{chst kein ]bertrag
	CLR	MULRG2
MUL1	LDA	,-X	Hole 8 Bit von Lvar
	LDB	REG+1	und untere 8 Bit vom Mult. Register
	MUL	Multiplizieren
	ADDD	MULRG2	ist das selbe wie: (2 mal Sternchen)
*	ADDB	MULRG1	]bertrag der unter. 8Bit der letzt. M. dazu
*	ADCA	MULRG2	]bertrag der oberen 8Bit der letzt. M. dazu
	STA	MULRG1	= vorl{ufiger unterer ]bertrag
	LDA	#0
	ADCA	MULRG2
	LDA	,X		Byte der Lvar nochmal holen
	STB	,X		Mult. Wert gleich zur}ckschreiben
	LDB	REG	obere 8Bit vom Mult. Register
	MUL	Multiplizieren
	ADDB	MULRG1	vorl{ufigen ]bertrag der unteren 8Bit dazu
	ADCA	MULRG2	mit Carry in den oberen ]bertrag
	STD	MULRG2	= neuer 16 Bit ]bertrag
	CMPX	RG1ANF	Anfang von Summe erreicht?
	BNE	MUL1	nein, Sprung
MUL9	PULS	X,Y,D,PC
*
* Testet RG1.
* falls RG1 = 0 (falls Anfangszeiger RG1ANF auf dieselbe Adresse
* zeigt wie der Endzeiger RG1END) so wird EQ-Condition ausgegeben,
* sonst NE-Condition.
*
UTSTV	PSHS	X,A
	LDX	RG1END
	LEAX	1,X
	STX	SEND1	Zeiger auf Ende von RG1 + 1
	LDX	RG1ANF
TSTG1	LDA	,X+	Stelle <> 0 ?
	BNE	TSTG9	ja, Sprung
	CMPX	SEND1	gesamte Zahl getestet?
	BNE	TSTG1	ja, Sprung
TSTG9	PULS	X,A,PC
*
* Gibt eine Header-Zeile aus
*
HEADER LEAX	TE,PCR
	JSR	PSTRNG	'e =' ausg.
	RTS
TE	FCC	'e =',4
*
* Footer ausgeben
*
FOOTER LEAX	TLAENG,PCR 'L{nge in Byte'
	JSR	PSTRNG	ausg.
	LDX	LAENGE
	PSHS	X
	LEAX	,S
	CLRB
	JSR	OUTDEC	Dez. ausg.
	LEAS	2,S
	LEAX	TN,PCR	'Anzahl der summ. Gl.'
	JSR	PSTRNG	ausg.
	LDX	N	
Anz. der Glieder
	LEAX	1,X	N beginnt bei 0
	PSHS	X	
auf Stack
	LEAX	,S
	CLRB
	JSR	OUTDEC	Dezimalz. ausg.
	LEAS	2,S	Stack aufr{umen
	LBSR	OINIT	neue Zeile
	RTS
TLAENG FCC	'length of number in byte: ',4
TN	FCC	'number of elements accumulated: ',4
*
* Unterprogramm zur Ausgabe einer Variablen
*==========================================
* Es wird hierbei angenommen, da~ das 1. Byte eine Dezimalzahl vor
* dem Komma darstellt, alle weiteren Bytes sind Nachkommastellen
* stellen.
* Die Ausgabe erfolgt durch schrittweises Multiplizieren der Zahl
* mit 10. Dabei rutscht jeweils eine Dezimale vor das Komma, die
* dann ausgegeben werden kann.
* Dies wird solange wiederholt, bis alle Dezimalen 0 sind, maximal
* werden jeweils soviel Dezimalstellen ausgegeben, wie sie in ANZDEZ
* vorher definiert wurden, ausgegeben.
* Die Ausgabe erfolt auf Device, d. h. evtl auch auf Drucker
* oder auf einen File.
*
UOUTV	PSHS	X,Y,A,B
	LBSR	OINIT	Ausgabe init., neue Zeile
	LDA	#' 
	LBSR	OUTCH	Zu Beginn 1 Space
	LDY	RG1ANF	Zeiger auf
	LEAY	1,Y	1. Dezimale
	STY	SANF1	in SANF1
	LDY	RG1END	Zeiger auf Ende von Summe
	LDX	ANZDEZ
	STX	STCNT
	CLR	UEBER	MSB von ]bertrag immer 0
	LDB	[RG1ANF]	Vorkommastelle ausgeben
	CLRA	
nur 8 Bit Genauigkeit
	PSHS	D	
auf Stack
	LEAX	,S		Zeiger auf Stack
	LDB	#1		mit f}hrenden Spaces
	LBSR	OUTDEC	Dezimalzahl ausg.
	LEAS	2,S	Stack aufr{umen
	LDA	CHO
	SUBA	#5	
Spaltenz{hler korrigieren
	STA	CHO
	LDA	#'.	Dezimalpunkt
	BSR	OUTCH	ausgeben
SUMA3	LEAX	1,Y	X = aktueller Positionszeiger
	CLR	UEBER+1	]bertrag = 0
SUMA1	LDA	,-X	Stelle holen
	LDB	#10
	MUL	mit 10 multiplizieren
	ADDD	UEBER	]bertrag der letzten Mul. dazu
	STB	,X		Ergebnis zur}ckschreiben
	STA	UEBER+1	neuer ]bertrag von A nach UEBER+1
	CMPX	SANF1	Anfang der Nachkommast. erreicht?
	BNE	SUMA1	nein, Sprung
	ADDA	#'0	]bertrag = neue Vorkommastelle
	BSR	OUTCH	Ausgeben
	LDX	STCNT
	LEAX	-1,X
	STX	STCNT
	BEQ	SUMA8
SUMA2	TST	,Y		letzte Stelle = 0?
	BNE	SUMA3	nein, Sprung
SUMA4	LEAY	-1,Y	eine Stelle davor
	CMPY	RG1ANF	hat Endezeiger den Anf. erreicht?
	BNE	SUMA2	nein, Sprung
*
SUMA8	LEAX	TDEZ,PCR	'Anzahl der Dezimalen'
	JSR	PSTRNG	ausg.
	LDX	ANZDEZ	Anzahl der Dez.
	PSHS	X	
auf Stack
	LEAX	,S
	CLRB
	JSR	OUTDEC	Dezimalzahl ausg.
	LEAS	2,S	Stack aufr{umen
	PULS	X,Y,A,B,PC
TDEZ	FCC	'number of decimals: ',4
*
* Initialisierung der Ausgabe:
* Setzt den Zeichenz{hler auf Null.
*
OINIT	CLR	CHO
	JMP	PCRLF
*
* Ausgabe eines Zeichens auf Device
*
OUTCH	PSHS	X,A,B
	TST	CHO	Zeichenz{hler = 0 ?
	BNE	OUTC1	nein, Sprung
	LDB	MAXCH	maximale Anzahl holen
	STB	CHO	Z{hler initialisieren
	JSR	PCRLF	neue Zeile
OUTC1	LDA	,S		Wert f}r A zur}ckholen
	JSR	PUTCHR
	DEC	CHO
	PULS	X,A,B,PC
*
* Ausgabe von CR, LF und Strings bis $4 auf Bildschirm
*
PDATA	PSHS	X
	LDA	#CR	CR, LF
	JSR	OUTCH2	ausgeben
	LDA	#LF
	JSR	OUTCH2
	LDX	,S
PDATA1 LDA	,X+	Zeichen holen
	CMPA	#4		ausgeben, bis 4 gefunden
	BEQ	PDATA9
	JSR	OUTCH2
	BRA	PDATA1
PDATA9 PULS	X,PC

	IF	*>$C700
	ERR	PROGRAM TOO LONG
	ENDIF

	END	BEGIN
                                  