; assembler-programmierung im avr-studio v. atmel
 ; f. die mikroprozessor-Systeme  mega8,-16,-32, ggf. asm entsprechend type abändern!
 ; allg. anweisungen
.NOLIST
.INCLUDE "m32def.inc" ; prozessortype/datei benennen/einfügen dh. hier "mega32", diese Type zuvor auch für den simulator auswählen!

; register umbenennen
.DEF HL=R16
.DEF HH=R17
.DEF KL=R18
.DEF KH=R19

; speicheradr. (ram) mit namen benennen
#define sregister  $5F
#define tempwert   $60 ;$61,62,63
#define tabzaehler $64 ;$65  untere-,obere adr.
#define ergebnis   $66 ;$67  $68/$69
#define summe      $6A ;$6B $6C/$6D
#define merker      $6E ;$6F 

; befehlsfolge (macro) benennen
.MACRO  Hreg       ; register mit festwert laden (8,8bit)
                ldi R17,@0
                ldi R16,@1
.ENDMACRO

.MACRO Hout      ; register f. ausgabe (8,8bit)
                out @0,R17
                out @1,R16
.ENDMACRO

.MACRO Xload       ; register vom speicher laden (adr.daten 8,8bit)
                lds XH,@0
                lds XL,@1
.ENDMACRO

.MACRO Yload       ; register vom speicher laden (adr.daten 8,8bit)
                lds YH,@0
                lds YL,@1
.ENDMACRO

.MACRO Xkeep        ; register in speicher laden (8,8bit)
                sts @0,XH
                sts @1,XL
.ENDMACRO

.MACRO Ykeep        ; register in speicher laden (8,8bit)
                sts @0,YH
                sts @1,YL
.ENDMACRO

.MACRO Xbyte          ; register mit festwert laden (16bit)
                ldi XL,LOW(@0)
                ldi XH,HIGH(@0)
.ENDMACRO

.MACRO Ybyte
                ldi YL,LOW(@0)
                ldi YH,HIGH(@0)
.ENDMACRO

.MACRO Zbyte
                ldi ZL,LOW(@0)
                ldi ZH,HIGH(@0)
.ENDMACRO

.MACRO  Zget                   ; register vom speicher laden (adr.daten 16bit)
                ldi ZL,LOW(@2)
                ldi ZH,HIGH(@2)
                ld @0,Z
                ldi ZL,LOW(@3)
                ldi ZH,HIGH(@3)
                ld @1,Z
.ENDMACRO

.MACRO  Zput         ; register in speicher laden (adr.daten 16bit)
                ldi ZL,LOW(@0)
                ldi ZH,HIGH(@0)
                st Z,@2
                ldi ZL,LOW(@1)
                ldi ZH,HIGH(@1)
                st Z,@3
.ENDMACRO

.MACRO  Zlpm       ; daten vom flash holen (adr.daten 16bit)
                lpm HL,Z+
                lpm HH,Z
.ENDMACRO

; prog. anfang
.cseg
.org 0   ;Datenbereich 2-199inc.
nop ; erste adr. im flash
 jmp START

SEGM7:    ; bit(7-0) +=1=ein f.segm. -.a,b,c,d,e,f,g
.DB 0b01111110,0b00110000,0b01101101,0b01111001    ;7E,30,6D,79hex,zahlen 0-3
.DB 0b00110011,0b01011011,0b01011111,0b01110000    ; 33,5B,5F,70hex,zahlen 4-7
.DB 0b01111111,0b01111011     ; 7F,7Bhex, zahlen 8,9
.DB 0b01110111,0b00011111,0b01001110,0b00111101    ; sonderzeichen. A,B,C,D
.DB 0b01001111,0b01000111,0b00000000,0b01111111    ; E,F,aus,ein

FUNKTION:    ; könnte auch im eeprom stehen u. ins ram kopiert werden
.DW BOXO,DIVI,BOXI,MULTI,BOXO,QWURZI,BOXI,SUBA,BOXO,DIVI
.DW BOXO,BITI,FMULTO,BOXU,WANDLO
.DW BOXO,BITI,ADDI,BOXI,WANDLI
.DW BOXO,ELOGI,BOXO,ELOGI,BOXO,ELOGI,BOXO,ELOGI,BOXO,ELOGI,BOXO,ELOGI
.DW BOXO,NLOGO,BOXO,NLOGO,BOXO,NLOGO,BOXO,NLOGO,BOXO,NLOGO,BOXO,NLOGO
.DW BOXO,MLOGO,BOXO,MLOGO,BOXO,MLOGO,BOXO,MLOGO,BOXO,MLOGO,BOXO,MLOGO,BOXO,MLOGO
.DW BOXO,ZSTELL,BOXO,ZSTELL,BOXO,ZSTELL,BOXO,ZSTELL,BOXO,ZSTELL,BOXO,ZSTELL
.DW BOXO,WANHD5,BOXO,WANS,BOXO,WANHD5,BOXO,WANS,BOXO,WANHD4,BOXO,WANS,BOXO,WANHD3,BOXO,WANS

DATEN:
.DW $09D8,0x002A,0,0,$E10,0,0,0,$EEEE,$321
.DW 18125,6250,0,0,0 ; 5 stellen f.werte 1,xxxx u.4 stellen f.werte 0,xxx
.DW 6250,6250,0,0,0
.DW 10000,0,7500,0,5000,0,2500,0,1250,0,625,0 ; usw.f.werte 1 0,5 0,2
.DW 27182,0,21170,0,16487,0,12840,0,11331,0,10644,0
.DW 0,8000,0,14368,0,24368,0,64368,$1,$2280,$1,$4990,$1,$70A0   ; x,y= 32bitwert f. x,xxxx
.DW 65535,4,0xB000,4,86,4,56,4,25,4,5,4
.DW 63999,0,0,5,2345,0,0,5,8765,0,0,4,965-1000,0,0,3 ; wert,stelle,abstelle,stellen
  
.cseg
.org 200    ;prog.bereich ab 200inc.

; prozesse setzen
START:
   cli         ;unterbrechung/interupt sperren
   Hreg HIGH(RAMEND),LOW(RAMEND) ; letzte adr des programmzeigers/stackpointer einstellen
   Hout SPH,SPL
   Hreg 0,0
   Zput tempwert+1,tempwert,HH,HL   ; speicherstellen (ram) auf null setzen,
   Zput tabzaehler+1,tabzaehler,HH,HL  ; start adr. f. prog.
   Zput ergebnis+1,ergebnis,HH,HL
   Zput ergebnis+3,ergebnis+2,HH,HL
   Zput summe+1,summe,HH,HL
   movw XL,HL  ; falls neustart
   bclr 6       ; t-bit löschen f.unsig./o.vorzeichen

; hauptprog. ausführen
PROG:
   Ybyte(FUNKTION*2)   ; adr. tabelle laden
   rcall ADDI
   movw ZL,XL      ; adr. in Z bereitstellen
   Zlpm       ; inhalt der adr. laden
   movw XL,R18   ; werte einstellen
   movw YL,R20
   movw ZL,HL
   icall                      ; nächstes prog. aus tab. aufrufen
   Zput ergebnis+1,ergebnis,XH,XL   ; werte in den speicher ablegen
   Zput ergebnis+3,ergebnis+2,YH,YL
   Xload tabzaehler+1,tabzaehler   ; prog.- od. tastencode laden
   adiw XH:XL,2                      ; nächste adr.
   Xkeep tabzaehler+1,tabzaehler  ; aufheben
   jmp PROG

; unterprog.
BOXO:                 ; rechenwerte aus tab. "daten" holen
   Ybyte(DATEN*2)
   Xload tabzaehler+1,tabzaehler
   rcall ADDI
   movw ZL,XL
   Zlpm
   movw R18,HL
   adiw ZH:ZL,1
   Zlpm
   movw R20,HL
   ret

BOXI:           ; werte aus dem speicher laden
   Zget R19,R18,ergebnis+1,ergebnis
   Zget R21,R20,ergebnis+3,ergebnis+2
   ret

BOXU:           ; werte aus dem speicher laden
   Zget R21,R20,ergebnis+1,ergebnis
   Zget R19,R18,ergebnis+3,ergebnis+2
 ret

BITI:
   rcall WANDLA
   movw R18,XL    ; werte einstellen
   movw XL,R16
   rcall WANDLA
   movw R20,XL
   ret

WANDLA:         ; bitwandler(num2fnum) x=>x
   ldi R16,8-1    ;umrechenwert= wert * 0x80 / 0x2710
   mov R5,R16     ; schleifenzähler
   eor R6,R6    ; reg. null setzen
   movw R16,YL
   Ybyte(10000)  ; festwert
   movw R2,YL
WANDLA_LOOP1:
   movw YL,XL    ; teste
   movw XL,R2
   rcall SUBA
   rol R6      ; carry holen
   or XL,XH
   brne WANDLA_LOOP2
   inc R6
   rjmp WANDLA_FIN
WANDLA_LOOP2:
   movw XL,YL
   movw YL,R2   ; festwert
   sbrc R6,0
   rcall SUBA   ; berechne rest
   rol XL     ; wert *2
   rol XH
   dec R5       ;schleifenzähler-1
   brne WANDLA_LOOP1
   rol R6
   rjmp WANDLA_END
WANDLA_FIN:
   clc
   rol R6
   dec R5
   brne WANDLA_FIN
WANDLA_END:
   movw XL,R6  ; einstellen
   ret

WANDLU:         ; bitwandler(num2fnum) x,y=>x
   ldi R16,16-1  ; umrechnenwert= (wert*0x8000)/0x2710
   mov R5,R16     ; schleifenzähler
   clr R4         ; allg. hilfreg.
   clr R6       ; reg. null setzen
   clr R7
   inc R4
   movw R8,YL    ; 32bit wert
   movw R10,XL
   Ybyte($2710)  ; festwert(10tsd)
   Xbyte($0000)
   movw R2,YL
   movw R0,XL
WANDLU_LOOP1:
   movw XL,R0
   movw YL,R2
   sub XL,R8    ; festwert
   sbc XH,R9
   sbc YL,R10
   sbc YH,R11
   rol R6      ; carry holen
   rol R7
   or XL,XH
   or XL,YL
   or XL,YH
   brne WANDLU_LOOP2
   add R6,R4
   clr R4
   adc R7,R4
   inc R4
   rjmp WANDLU_FIN
WANDLU_LOOP2:
   movw XL,R8      ; festwert
   movw YL,R10      ; restwert
   sbrs R6,0
   rjmp WANDLU_LOOP3
   sub XL,R0
   sbc XH,R1
   sbc YL,R2
   sbc YH,R3
WANDLU_LOOP3:
   rol XL      ; wert *2
   rol XH
   rol YL
   rol YH
   movw R8,XL
   movw R10,YL
   dec R5       ;schleifenzähler
   brne WANDLU_LOOP1
   rol R6
   rol R7
   rjmp WANDLU_END
WANDLU_FIN:
   clc
   rol R6
   rol R7
   dec R5
   brne WANDLU_FIN
WANDLU_END:
   movw XL,R6  ; einstellen
   ret

WANDLI:       ; bitwandler(fnum2num) xl=>x
   mov R6,XL
   eor XL,XL        ;null setzen
   eor XH,XH
   ldi R16,8-1
   mov R5,R16 ; schleifenzähler
   movw R16,YL
   Ybyte(10000)  ; festwert
WANDLI_LOOP:
   sbrc R6,7
   call ADDI   ; teilwert
   clc
   ror YH     ; festwert
   ror YL
   clc
   rol R6
   dec R5
   brne WANDLI_LOOP
   ret

WANDLO:            ; bitwandler(fnum2num) x=>x,y
   movw R6,XL       ; umrechnenwert=(wert*2*0x2710)/0x10000  ,bei neg.wert abzügl. 20tsd.
   ldi R16,16-1    ; bsp. 0xB000 ergibt nach wandelo 0x35B6(13750) davon 20tsd=>-0,625
   mov R5,R16    ; schleifenzähler
   movw R16,YL
   Ybyte($2710)  ; festwert (10tsd)
   Xbyte($0000)
   movw R2,YL
   movw R0,XL
   Xbyte(0)
   Ybyte(0)
WANDLO_LOOP1:
   sbrs R7,7
   rjmp WANDLO_LOOP2
   clc
   add YL,R0
   adc YH,R1
   adc XL,R2
   adc XH,R3
WANDLO_LOOP2:
   clc
   ror R3     ; festwert
   ror R2
   ror R1
   ror R0
   clc
   rol R6
   rol R7
   dec R5
   brne WANDLO_LOOP1
   ret

SUBA:        ; subtraktion x-y=x
   clc
   sub XL,YL
   sbc XH,YH
   ret

ADDI:      ; addition x+y=x
   clc
   add XL,YL
   adc XH,YH
   ret

DIVI:            ; division  x/y=x
   ldi R17,16+1  ; schleifenzähler
   clr R16     ; ereignis behalten
   clr R0      ; hilfsregister
   clr R1
   clr R2      ;  zwischenregister
   clr R3
   neg YL     ; divisor 2er komplement bilden bzw.jedes bit umkehren +1)
   adc YH,R16  ; übernehme  carry
   neg YH
DIVI_LOOP1:
   mov R0,R2    ; zwischenergebnis behalten
   mov R1,R3
   add R2,YL   ; divisor subtrahieren bzw. 2er komplement addieren
   adc R3,YH
   brcs DIVI_LOOP2
   mov R2,R0     ; zwischenergebnis wiederherstellen
   mov R3,R1
DIVI_LOOP2:
   rol XL  ; nächste stelle holen vom dividenten
   rol XH
   rol R2   ; einlesen in zwischenspeicher
   rol R3
   dec R17  ; schleifenzähler abwärts
   brne DIVI_LOOP1
   neg YL    ; beenden, divisor wiederherstellen
   adc YH,R17  ; hinzu carry
   neg YH
   ret

DIVO:            ;  division  x,y/r1,r0=x,y (erweiterte struktur von divi)
   ldi R17,32+1  ; schleifenzähler
   clr R16     ; ereignis behalten
   clr R2      ; hilfsregister r2,3,4,5
   clr R3
   clr R4
   clr R5
   clr R6    ;  zwischenregister r6,7,8,9
   clr R7
   clr R8
   clr R9
   neg R0     ;  2er komplement bilden
   adc R1,R16  ;  carry
   neg R1
DIVO_LOOP1:
   movw R2,R6    ; zwischenergebnis
   movw R4,R8
   com R16
   add R6,R0    ; hinzu 2er komplement
   adc R7,R1
   adc R8,R16 ; schiebe carry
   adc R9,R16
   brcs DIVO_LOOP2
   movw R6,R2  ; zwischenergebnis wiederherstellen
   movw R8,R4
DIVO_LOOP2:
   clr R16
   rol YL  ; nächste stelle
   rol YH
   rol XL
   rol XH
   rol R6   ; zwischenspeicher
   rol R7
   rol R8
   rol R9
   dec R17  ; zähler
   brne DIVO_LOOP1
   neg R0    ;  wiederherstellen
   adc R1,R17  ; hinzu carry
   neg R1
   ret

MULTI:      ; multiplikation x*yl=x
   clc
   clr R3
   clr R2
   ldi R16,8       ; schleifenzähler
MULTI_LOOP1:
   ror R3        ; schiebe resultat
   ror R2
   dec R16
   brlt MULTI_EXIT
   ror XL            ; schiebe multiplikant
   brcc MULTI_LOOP1  ;    übertrag ?
   add R3,YL              ; addiere multiplikator zum resultat
   rjmp MULTI_LOOP1      ; wiederhole
MULTI_EXIT:
   movw XL,R2
   ret

MULTA:         ; multiplikation x*yl=xl,y
   mov KL,YL    ; t-bit f. unsig/sig
   movw HL,XL
   clr XH      ; hilfsreg.
   lds R2,sregister
   sbrs R2,6
   mul HH,KL    ; xh*yl
   sbrc R2,6
   muls HH,KL    ; sig,xh*sig.yl
   mov YH,R0
   mov XL,R1
   sbrs R2,6
   mul KL,HL     ; yl*xl
   sbrc R2,6
   mulsu KL,HL   ; sig.yl*xl
   sbrc R2,6
   sbc XL,XH
   mov YL,R0
   add YH,R1
   adc XL,XH
   ret        ;  ergb. in xl,y

MULTO:          ; multiplikation x*y=x,y
   movw HL,YL    ; t-bit f. unsig/sig
   movw KL,XL
   clr R2       ; hilfsreg.
   lds R3,sregister
   sbrs R3,6
   mul KH,HH      ; xh*yh
   sbrc R3,6
   muls KH,HH    ; sig.xh*sig.yh
   movw XL,R0
   mul KL,HL     ;  xl*yl
   movw YL,R0
   sbrs R3,6
   mul KH,HL     ; xh*yl
   sbrc R3,6
   mulsu KH,HL   ; sign.xh*yl
   sbrc R3,6
   sbc XH,R2
   add YH,R0     ; summe bilden
   adc XL,R1     ; carry hinzu
   adc XH,R2
   sbrs R3,6
   mul HH,KL    ; yh*xl
   sbrc R3,6
   mulsu HH,KL   ; sig.yh*xl
   sbrc R3,6
   sbc XH,R2
   add YH,R0
   adc XL,R1
   adc XH,R2    ; ergeb. x,y
   ret

FMULTA:
   mov HH,XL      ;fraktionalnummer xl*yl=>x
   mov HL,YL       ;  t-bit f. unsig./sig.
   lds R2,sregister
   sbrs R2,6
   fmul HH,HL    ; xl * yl
   sbrc R2,6
   fmuls HH,HL  ; sig.xl * sig.yl
   movw XL,R0
   ret

FMULTO:         ;fraktionalnummer(bruchrechnen) x*y=x,y
   movw HL,YL    ; t-bit f. unsig/sig
   movw KL,XL
   clr R2
   lds R3,sregister
   sbrs R3,6
   fmul KH,HH  ; xh*yh  od.
   sbrc R3,6
   fmuls KH,HH  ; rechne sig.xh*sig.yh<1
   movw XL,R0
   fmul KL,HL    ; rechne xl*yl
   adc XL,R2
   adc XH,R2
   movw YL,R0
   adc XL,R2
   adc XH,R2
   sbrs R3,6
   fmul KH,HL  ; xh*yl  od.
   sbrc R3,6
   fmulsu KH,HL  ; rechne sig.xh*yl<1
   sbrs R3,6
   sbc XH,R2
   add YH,R0
   adc XL,R1
   adc XH,R2
   sbrs R3,6
   fmul HH,KL    ; yh*xl od.
   sbrc R3,6
   fmulsu HH,KL  ; rechne sig.yh*xl<1
   sbrs R3,6
   sbc XH,R2
   add YH,R0
   adc XL,R1
   adc XH,R2
   ret         ; ergb. x,y

QWURZI:           ; quadratwurzel(x)=>x   (ganzzahlig)
   movw YL,XL
   movw R4,XL
   ldi R22,16-2   ; schleifenzähler
QWURZI_GATE1:
   rcall DIVI
   rcall ADDI     ; zum ergebnis hinzu
   clc
   ror XH        ; wert halbieren mit carry
   ror XL
   movw YL,XL    ; neuer wert
   movw XL,R4
   dec R22
   brne QWURZI_GATE1
   movw XL,YL    ; ergeb. in x
   ret

ELOGI:          ;  exponentialfunktion  e(x)=>x  f.<1  (ganzzahlig gemäß euler)
   Ybyte(0)      ; bspw. sei x=1,7   umrechenwert=(e x/2)q2
   rcall WANDLU    ; kehrwert bilden, dh, wertigkeit der bits ist umgekehrt
   Ybyte(0)
   Zbyte(10000)       ; 1/fakultät(n)
   movw R10,ZL   ; abzügl. f.kofa hilfsregister
   movw ZL,YL     ;summenwert null setzen
   Ybyte($0908)       ;schleifenzähler f. 1/fakultät
   movw R12,YL
   movw R6,XL
   movw R8,XL       ; kehrwert(xn) in mul stelle ablegen
ELOGI_TOUR:
   rcall KOFA
   dec R12
   breq ELOGI_DONE
   clc
   rol XL        ; (1/!) *2
   rol XH        ;umrechnen
   movw YL,R8   ; einstellen
   rcall MULTO     ;ergebnis in x
   movw YL,ZL
   rcall ADDI      ; summenwert bilden
   movw ZL,XL
   movw XL,R8   ; xn-wert
   movw YL,R6    ; rechne xn *x bilden
   rcall FMULTO
   movw R8,XL   ; oberwert in mul stelle ablegen
   rjmp ELOGI_TOUR
ELOGI_DONE:
   movw XL,ZL    ; summenwert
   Ybyte(10000) ; hinzu ergb.
   rcall ADDI
   ret         ; erg. in x

KOFA:             ; 1/n!=x   n=r15-r14
    Xbyte(10000)  ; die hier berechneten werte könnten auch in tab. stehen
   movw YL,R10   ; hilfsregister
   rcall DIVI
   clr YH
   mov YL,R13
   sub YL,R12
   rcall MULTA
   Xbyte(10000)
   rcall DIVI
   movw R10,XL   ; teste restwert
   movw XL,R2     ;hole restwert aus divi (r3,r2)
   ldi XL,2   ; hunderstel
   subi XH,13   ; abzügl.
   brlo KOFA_BYE
   add R10,XL     ;ansonsten hinzu
   eor XL,XL   ; null setzen
   adc R11,XL   ; übernehme ergebnis
KOFA_BYE:
   movw XL,R10   ; übernehme ergebnis
   ret

NLOGO:   ; logarithmus ln(x)=>x wobei  x<2,7182  (mittels taylor-reihe), bei neg. wert ist x im zweier kompl. u. T status ein
 .EQU k_nlogo=4  ;   bsp. x=5  dann ist d. umrechenwert=ln(5/2)+ln(2)
   clr ZH        ;    f. den divisor kann man sich d. ln(1 b.5) bspw. in tab.  notieren
   clr ZL         ; summe
   Ybyte($0B0A)  ; schleifenzähler
   movw R12,YL     ;aufheben
   movw R14,XL     ;rechenwert ebenfalls aufheben
   Ybyte(10000)  ; abzügl.10tsd (f. wert 1)
   rcall SUBA     ;x-y=x, subiw setzt ggf. kennzeichen S
   clt         ; neg. kennzeichen (T)löschen d.h. rechnen nur mit pos.Zahlen
   breq NLOGO_END
   brsh NLOGO_NEXT1      ; bei neg.wert status C gesetzt
   set                          ; neg. kennzeichen (T) setzen ggf.wert umwandeln in 2er kompl.
   movw YL,R14
   Xbyte(10000)      ; abzügl.10k
   rcall SUBA      ; od.subiw setzt S
NLOGO_NEXT1:
   movw R22,XL   ; ergeb. suba f. zähler aufheben
   movw XL,R14      ; rechenwert erneut laden
   Ybyte(10000)  ; hinzu wert 10tsd.
   rcall ADDI
   movw R14,XL  ; nenner behalten
   movw XL,R22      ; zähler laden
   Ybyte(k_nlogo)
   rcall DIVI
   Ybyte(0)
   rcall WANDLU ; kehrwert bilden
   movw R22,XL  ; neuen zähler aufheben
   movw R24,XL  ; ebenso in mul.stelle ablegen
   movw XL,R14      ; nenner holen
   Ybyte(k_nlogo)      ; ebenfalls um faktor verkeinern
   rcall DIVI
   Ybyte(0)
   rcall WANDLU      ; vom nenner auch kehrwert bilden
   movw R14,XL ; neuen nenner aufheben
   movw R20,XL  ; ebenso in mul.stelle ablegen
NLOGO_NEXT2:
   rcall KOWE  ; berechne 1/n
   movw YL,R24      ; zähler aus mul.stelle holen
   rcall MULTO      ; ldf.zähler mul. mit kehrwert (multo liefert 32bitwert x,y)
   movw R0,R20      ; divident nach r1,r0 f. divo
   rcall DIVO
   movw XL,ZL  ; davon summe bilden
   rcall ADDI
   movw ZL,XL
   movw XL,R22  ; potenz des zählers bilden
   movw YL,R24      ; zähler aus mul.stelle holen
   rcall FMULTO
   movw YL,R22       ; nochmal
   rcall FMULTO
   movw R24,XL  ; potenzwert des zähler nach mull. stelle
   movw XL,R14      ; neuen nenner holen
   movw YL,R20   ; nenner aus mul.stelle holen
   rcall FMULTO
   movw YL,R14      ; nochmal da potenzwert um 2 steigt
   rcall FMULTO
   movw R20,XL  ; in mull stelle ablegen
   mov XL,R12  ; ldf.zähler ende ?
   subi XL,3
   brsh NLOGO_NEXT2      ; bei neg.wert od. gleich weiter ansonsten nach
   clc
   rol ZL   ; summe letztlich *2
   rol ZH
   movw XL,ZL   ; ergeb. nach x
   brbc 6,NLOGO_END
   eor R16,R16
   neg XL   ; 2er komplement bilden
   adc XH,R16   ; übernehme status, falls gesetzt
   neg XH
NLOGO_END:
   ret

KOWE:         ;  x=1/1  ,3,5,7
   mov YL,R13
   sub YL,R12
   Xbyte(10000)
   clr YH
   rcall DIVI
   dec R12   ; neuen ldf.zähler bilden
   dec R12
   ret

mLOGO:   ; ln(x,y)=>x (neg.wert im 2er kompl.siehe kennz.-t)
   Zbyte(10000)  ; bilde sprungwert
   movw R0,ZL
   rcall DIVO
   mov R24,YL  ; ermittelten wert aufheben
   movw XL,R18  ; wert aus Boxo nachladen
   movw YL,R20
   or R24,R24  ; ereignis setzen
   brne mLOGO_ab  ; f. höhere wert
   movw XL,YL  ; f. kleine wert weiter
   rcall NLogo
   ret
mLogo_ab:  ; bilde divisor
   ldi R25,5  ; vergl.wert
   sbrc R24,0  ; teste auf ungerade
   inc R24  ; erstelle neu
   mov r0,r24
   sub r0,r25
   brlo mLogo_um
   ldi r24,4  ;max.divisor fest
mLogo_um:
   eor r25,r25
   ZByte(6931/2)  ; einhalb von ln(2)
   movw r0,r24
mLogo_zu:
   rol ZL  ; vielfache von
   rol ZH
   dec r24
   dec r24
   or r24,r24  ; abgezählt
   brne mLogo_zu
   sts merker,ZL  ;Ln(er) aufheben
   sts merker+1,ZH
   rcall DIVO  ;wert durch 2er teiler
   movw XL,YL
   rcall NLOGO   ; bilde davon Ln
   Yload merker+1,merker
   rcall ADDI
   clt         ; kennzeichen (T)
   ret
  
ZSTELL:     ; x * 10er =x,y , startwert in X, anz.nuller in Y
  mov R17,YL    ; anz.nuller
  movw YL,XL
  Xbyte(0)
ZSTELL_ANZ:
  ldi R16,2       ; 10er bilden
  clc
  rol YL       ; zwei
  rol YH
  rol XL
  rol XH
  Ykeep summe+1,summe
  Xkeep summe+3,summe+2
ZSTELL_LOOP:
  clc
  rol YL      ; acht
  rol YH
  rol XL
  rol XH
  dec R16
  brne ZSTELL_LOOP
  movw R0,XL        ; werte sichern
  movw R2,YL
  Yload summe+1,summe       ; lade vorwert
  Xload summe+3,summe+2
  clc
  add YL,R2       ; wert bilden
  adc YH,R3
  adc XL,R0
  adc XH,R1
  dec R17
  brne ZSTELL_ANZ      ; ausgabe x,y
  ret
  
WANHD5:      ; wert in x, ablage.adr in Y, umwandlung von hex nach dez
  ldi R20,-1        ; neg.eins
WANHD_ZTSD:
  inc R20        ;erhöhe
  subi XL,low(10000)       ;x abzügl.zehntsd.
  sbci XH,high(10000)
  brcc WANHD_ZTSD        ;bis ereignis
  st Y+,R20       ; merken
  dec R20
  brcc WANHD_TSD
  subi XL,low(-10000)     ;hinzu
  sbci XH,high(-10000)
WANHD4:  
  ldi R20,-1      ;2kpl.von 1
WANHD_TSD:
  inc R20       ;erhöhe um
  subi XL,low(1000)      ;abzügl.eintsd.
  sbci XH,high(1000)
  brcc WANHD_TSD       ;bis ereignis
  st Y+,R20      ;tsd merken
WANHD3: 
  ldi R20,10     ;zähler auf zehn
WANHD_HDR:
  dec R20      ; abzügl. eins
  subi XL,low(-100)   ;hinzu 2kpl.von hdr
  sbci XH,high(-100)
  brcs WANHD_HDR     ;bis ereignis
  st Y+,R20       ;Zehner merken
  ldi R20,-1
  WANHD_ZHN:
  inc R20     ;abzügl.
  subi XL,10       ;abzügl.zehn
  brcc WANHD_ZHN
  subi XL,-10      ;hinzu
  st Y+,R20
  st Y,XL       ;rest
  ret
  
WANS:     ; start.adr in X , anz. in YL ,umwandlung von dez nach segm.
  andi YH,0       ; zähler benullen
WANS_LOOP:
  ld R24,X       ; abladen dez.wert
  andi R24,0x0F
  Zbyte(SEGM7*2)
  eor R25,R25       ; hilfreg. nullen
  add ZL,R24 ;zuladen adr.
  adc ZH,R25      ; ggf mit status beladen
  lpm R24,Z      ; aufladen adr.seg.
  st X+,R24      ; umladen
  inc YH
  cp YH,YL
  brlo WANS_LOOP
  ret
  

; ------------- ende ----------

Quellen:Siemens(Assembler8080),Motorola(MC68000),Atmel(App.Notes)

Karl Moosbauer
Techniker f. MSR                               erstellt: Jan.'09,erneuert,ergänzt: Mai'19 erweitert:Apr'21