
*****************************************
*	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 einer Wurzel 1/N	*
***************************************
*
* Die Wurzel wird nach folgender unendlichen Reihe berechnet:
*
*	unendl. ( n )
* SQRT(1 + 1/X)	:=	SUMME	( k ) * 1/X^k	f}r -1 < X < 1
*	n = 0
*	= n }ber k
*
* Ablauf der Rechnung:
* Es werden vier variable Speicherbereiche angelegt. In zwei davon
* werden die jeweils aktuellen Glieder berechnet (G1 und G2). In
* einem weiteren befindet sich die aktuelle Summe (S). Au~erdem
* wird f}r die Division des aktuellen Gliedes durch 2*n+1 ein Latch
* ben|tigt. Der Summenz{hler ist als 16 Bit Integer-Wert in N abge
* legt. Parallel hierzu wird in ZWEIN1 2*n+1 abgelegt.
* Glied1,2 und Summe m}ssen jeweils dasselbe Format haben. Das erste
* Byte gibt dabei jeweils die Vorkommastelle, alle folgenden die
* Dezimalen an.
* Zu Beginn wird Glied1 mit 16/5, Glied2 mit 4/239 und Summe mit
* Glied1 - Glied2 (= 16/5-4/239) geladen. In jedem Durchgang wird
* nun das alte Glied1 durch 5*5 dividiert, Glied2 zwei mal durch 239
* dividiert. Anschlie~end wird Glied2 von Glied1 im Latch subtr.
* Das Ergebnis wird durch 2*n+1 dividiert und zur Summe addiert bzw.
* subtrahiert. Ob addiert oder subtrahiert wird, h{ngt davon ab, ob
* n gerade oder ungerade ist. Die Berechnung wird abgeschlossen,
* wenn das akutelle Glied den Inhalt 0 (letztes Byte kann auch <> 0
* sein) hat. Anschlie~end erfolgt die Ausgabe der Zahl mit MOUTV.
*
* Wolfgang Schwotzer	
22.05.86
*
* System Equates:

DPVAR	EQU	$C1	Direct Page
LBUFP	EQU	$CD14	Linebufferpointer
CURCHR EQU	$CC18	Current Character
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
NXTCH	EQU	$CD27	N{chstes Zeichen vom Puffer
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	
Zwischenregister 2 Anf.zeiger
RG2END FDB	0	
Zwischenregister 2 End.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 Zahl in Byte, nach Eingabe
SANF1	FDB	0	
Zeigt auf erste Dezimale in S. = [SANF]+1
N	FDB	0	
= 16 Bit Summenz{hler
ZWEIN	FDB	0	
= 2 * N
ZAEHL	FDB	0	
= 2 * N - 3
WERT	FDB	0	
= X
MINUS	FCB	0	
Flag: <> 0 , falls WERT negativ
*
* 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
G2ANF	FDB	0	
Anfangszeiger auf Glied2
G2END	FDB	0	
Zeiger auf letzte Stelle von G2
LANF	FDB	0	
Anfanszeiger auf Latch
LEND	FDB	0	
Zeiger auf letzte Stelle von L.

*********************
* 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. (Das letzte Byte
* kann dabei auch <> 0 sein). Bei Null ist EQ-Condition.
*
MTSTV	MACRO
	LDX	&1ANF
	STX	RG1ANF
	LDX	&1END
	STX	RG1END
	LBSR	UTSTV
	ENDM

*******************
*	Programmstart	*
*******************
*
ANF	LDA	#DPVAR
	TFR	A,DP
*
* Ein- und Ausgabe
*
	CLR	MINUS
	LEAX	THALLO,PCR
	LBSR	PDATA
	JSR	INBUFF
	LDX	LBUFP
	LDA	,X
	CMPA	#'-	Mit Minus?
	BNE	ALPHA
	LDB	#1
	STB	MINUS	Negativ-Flag <> 0
	JSR	NXTCH
	JSR	NXTCH
ALPHA	JSR	INDEC
	LBCS	ERROR
	TSTB
	LBEQ	ERROR
	STX	WERT	= X-Wert
	LEAX	TFRAGE,PCR 'L{nge des Speicherplatzes'
	LBSR	PDATA
	JSR	INBUFF	Dezimalzahl
	JSR	INDEC	eingeben
	LBCS	ERROR
	TSTB
	LBEQ	ERROR
	CMPX	#12288	mu~ < 48 KByte/4 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,#11	Mult. mit 11
	LDX	[SANF]	= L{nge d. Zahl in Ziffern
	STX	ANZDEZ	abspeichern
	LDX	#0
	PLACE S	
Summe platzieren,l|schen
	PLACE G1		Glied1	"
*
	LDX	G1ANF
	LDA	#1
	STA	,X+	Glied1 := 1
*
	TRANS S,G1	Summe := Glied1
*
	LDD	#0
	STD	N	
N := 0

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

LOOPE	LDD	N
	ADDD	#1
	STD	N	
N := N + 1
	LSL	B
	ROL	A
	STD	ZWEIN	ZWEIN := N * 2
	SUBD	#3
	CMPD	#-1
	BNE	LOOPE1
	LDD	#1
LOOPE1 STD	ZAEHL	ZAEHL := N * 2 - 3
	MDIV	G1,WERT	Glied1 := Glied1 / WERT
	MDIV	G1,ZWEIN	Glied1 := Glied1 / ZWEIN
	MMULT G1,ZAEHL	Glied1 := Glied1 * ZAEHL
	TST	MINUS
	BEQ	LOMIN
	MADSU S,G1,N,+1	Summe := Summe +- Glied1
	BRA	LOOPE2
LOMIN	MADSU S,G1,#1,0	Summe := Summe - Glied1
LOOPE2 MTSTV G1	
Bis Korrekturglied = 0
	LBNE	LOOPE
*
	LBSR	HEADER	Header	ausgeben
	MOUTV S	
SUMME ausgeben
	LBSR	FOOTER	Anz der summierten Gl. ausg.
WRM	JMP	WARMS
*
ERROR	LEAX	TERRO,PCR
	LBSR	PDATA
	BRA	WRM
*
THALLO FCC	"calculation of a sqare root SQRT(1 + 1/X)",CR,LF
	FCC	"for -65535 <= X <= 65535: ",4
TNL	FCC	4
TFRAGE FCC	'size of memory in byte (<= 12288) : ',4
TERRO	FCC	'input error',4

*
* Unterprogramm zum Kopieren einer Langvariablen
* ==============================================
* Quellvariable: RG1
* Zielvariable: RG2
* 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
	LDY	RG1ANF	Zeiger auf Anfang des Divisors
DIV01	LDA	,Y
	BNE	DIV0	Zeiger weiterr}cken, bis <> 0
	LEAY	1,Y
	CMPY	RG1END	falls Ende erreicht, vorzeitiger
	BEQ	DIV9	Abbruch
	BRA	DIV01
*
DIV0	LDX	#16	Pro Fenster 16 Durchl{ufe
	LDD	#0		16-BIT Fenster zun{chst Null
DIV1	LSL	1,Y	1 Bit aus dem Fenster ,Y; 1,Y
	ROL	,Y		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,Y	falls positiv 1 in Fenster zur}ck-
	SEC	schreiben (falls neg. steht die 0
	ROL	1,Y	auf jeden Fall schon da)
NEG1	LEAX	-1,X	gesamtes Fenster durchgeschoben?
	BNE	DIV1	nein, Sprung
*
	LDX	#16	Z{hler wieder neu laden
	LEAY	1,Y	Fenster-Zeiger um 1 weiter
	CMPY	RG1END	Zeiger am Ende angelangt?
	BEQ	DIV9	ja, Sprung
	LEAY	1,Y	Zeiger noch 1 weiter
	CMPY	RG1END	Jetzt am Ende?
	BNE	DIV1	nein, Sprung
*
	LDX	#8		Hier ist noch 1 Byte zu
DIV2	LSL	,Y		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	,Y
	SEC
	ROL	,Y
NEG2	LEAX	-1,X
	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.
*
SUMME	PSHS	X,Y,D
	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
	CLRA	
zun{chst kein Carry
SUM1	ADDA	,-X	Addiere 8 Bit von Summe
	ADDA	,-Y	und 8 Bit von Glied
	STA	,X		Schreibe zur}ck nach Summe
	LDA	#0		l|sche A
	ADCA	#0		Lege ]bertrag in A ab
	CMPX	RG1ANF	Anfang von RG1 erreicht?
	BEQ	SUM9	ja, Sprung
	CMPY	RG2ANF	Anfang von RG2 erreicht?
	BNE	SUM1	nein, Sprung
SUM2	ADDA	,-X	Carry dazu
	STA	,X
	LDA	#0
	ADCA	#0		neues Carry in A
	CMPX	RG1ANF	alles aufaddiert?
	BEQ	SUM9	nein, Ende
	TSTA	
ist Carry aufgetreten?
	BNE	SUM2	ja, Sprung
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	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
	CLRA	
zun{chst kein Carry
DIFF1	NEGA	
Carry abziehen
	ADDA	,-X	Subtrahiere Carry von RG1
	SUBA	,-Y	Subtrahiere 8 Bit von RG2
	STA	,X		Schreibe zur}ck nach RG1
	LDA	#0		l|sche A
	ADCA	#0		Lege ]bertrag in A ab
	CMPX	RG1ANF	Anfang von RG1 erreicht?
	BEQ	DIFF9	ja, Sprung
	CMPY	RG2ANF	Anfang von RG2 erreicht?
	BNE	DIFF1	nein, Sprung
DIFF2	ADDA	,-X	Carry dazu
	STA	,X
	LDA	#0
	ADCA	#0		neues Carry in A
	CMPX	RG1ANF	alles subtrahiert?
	BEQ	DIFF9	nein, Ende
	TSTA	
ist Carry aufgetreten?
	BNE	DIFF2	ja, Sprung
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
	LDX	RG1ANF
TSTG1	TST	,X		Stelle <> 0 ?
	BNE	TSTG9	ja, Sprung
	LEAX	1,X	eine Stelle weiter
	CMPX	RG1END	gesamte Zahl getestet?
	BEQ	TSTG9	ja, Sprung
	BRA	TSTG1	sonst weitertesten
TSTG9	PULS	X,PC
*
* Gibt eine Header-Zeile aus
*
HEADER LEAX	TPI,PCR
	JSR	PSTRNG
	LDA	#'+
	TST	MINUS
	BEQ	HEAD1
	LDA	#'-
HEAD1	JSR	PUTCHR
	LDA	#' 
	JSR	PUTCHR
	LDA	#'1
	JSR	PUTCHR
	LDA	#'/
	JSR	PUTCHR
	LDX	WERT
	PSHS	X
	LEAX	,S
	CLRB
	JSR	OUTDEC
	LEAS	2,S
	LDA	#')
	JSR	PUTCHR
	LDA	#'=
	JSR	PUTCHR
	RTS
TPI	FCC	'square root of (1 ',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
             