
; Routinen zum Konvertieren von FFP-Fließkommazahlen in ASCII und umgekehrt.










; FFP = afp (Stringzeiger)
; Wandelt einen ASCII-String in eine FFP-Fließkommazahl um.  Rückgabe in D0.

      IFD   afp_c

      XDEF  _afp

      XREF  FFPAFP

_afp_REG REG   d1-d7/a0-a6
REGISTER SET   14

_afp
      movem.l  _afp_REG,-(SP)
      move.l   REGISTER*4+4(SP),a0  ; Stringzeiger
      jsr      FFPAFP
      move.l   d7,d0                ; Rückgabewert
      movem.l  (SP)+,_afp_REG
      rts

      ENDC










; FFPAFP
; Assemblerversion von _afp.
; Eingabe:  A0 zeigt auf den umzuwandelnden ASCII-String.
; Ausgabe:  D7 und D0 enthalten die FFP-Fließkommazahl.
;           A0 zeigt direkt hinter den gelesenen ASCII-String.
;           Falls ein Fehler auftrat, ist das Carry-Flag gesetzt, und A0
;           zeigt auf die Fehlerstelle.

; Der String muß die Form haben:
;     [+|-]{x}.xxxx[(e|E)[+|-]x{x}]
;     [+|-]x{x}[(e|E)[+|-]x{x}]

      IFD   afp_a

      INCLUDE  "lvo/math.i"

      XDEF  FFPAFP

      XREF  _MathBase

FFPAFP
      ; Initialisiere ein paar Werte.
      move.l   a0,a5                ; benutze A5 als Quellzeiger
      moveq    #0,d7                ; Zahl
      moveq    #0,d6                ; Zeichen
      move.l   _MathBase,a6         ; Library-Basis

      ; Gibt es ein Vorzeichen ?
      move.b   (a5)+,d6             ; hole Zeichen
      cmp.b    #'-',d6              ; Minus ?
      seq      d5                   ; ja, setze Vorzeichenflag
      beq.s    1$                   ; ja, neues Zeichen holen
      cmp.b    #'+',d6              ; Plus ?
      bne.s    2$                   ; nein, dann Vorzeichen beendet
1$    move.b   (a5)+,d6             ; hole Zeichen
      bra.s    2$



      ; Solange Dezimalziffern (vor dem Komma) kommen, multipliziere die
      ; Zahl mit zehn und addiere die Ziffer.
4$    move.l   d7,d0                ; FFP-Zahl
      move.l   #$A0000044,d1        ; mal 10
      jsr      _LVOSPMul(a6)
      bvs      AFPOverflow          ; wenn Überlauf
      move.l   d0,d7
      move.l   d6,d0
      sub.b    #'0',d0              ; ergibt Integerzahl der Ziffer
      jsr      _LVOSPFlt(a6)        ; wandele in FFP um
      move.l   d7,d1
      jsr      _LVOSPAdd(a6)        ; addiere die Ziffer zur Zahl
      bvs      AFPOverflow          ; wenn Überlauf
      move.l   d0,d7
      move.b   (a5)+,d6             ; hole Zeichen
2$    cmp.b    #'0',d6
      blo.s    3$
      cmp.b    #'9',d6
      bls.s    4$                   ; wenn weitermachen



      ; Jetzt folgt ein Punkt mit Nachkommastellen oder der Exponent.
3$    cmp.b    #'.',d6              ; folgt Punkt ?
      bne.s    AFPNoDot             ; nein
      move.l   #$CCCCCD3D,d4        ; beginne mit 0.1
      bra.s    5$

      ; Addiere Nachkommastellen.
6$    move.l   d6,d0
      sub.b    #'0',d0              ; ergibt Integerzahl der Ziffer
      jsr      _LVOSPFlt(a6)        ; wandele in FFP um
      move.l   d4,d1
      jsr      _LVOSPMul(a6)
      move.l   d7,d1
      jsr      _LVOSPAdd(a6)        ; addiere die Ziffer zur Zahl
      bvs      AFPOverflow          ; wenn Überlauf
      move.l   d0,d7
      move.l   d4,d0
      move.l   #$CCCCCD3D,d1        ; mal 0.1
      jsr      _LVOSPMul(a6)
      beq.s    AFPNoDot             ; wenn Stellen nicht mehr signifikant
      move.l   d0,d4
5$    move.b   (a5)+,d6             ; hole Zeichen
      cmp.b    #'0',d6
      blo.s    AFPNoDot
      cmp.b    #'9',d6
      bls.s    6$                   ; wenn weitermachen



AFPNoDot
      ; Jetzt kann der Exponent folgen.
      bclr     #5,d6                ; wandele in Großbuchstaben
      cmp.b    #'E',d6              ; kommt jetzt Exponent ?
      bne.s    AFPEnd               ; nein, Ende

      ; Gibt es ein Exponentenvorzeichen ?
      swap     d5                   ; rette Vorzeichenflag
      move.b   (a5)+,d6             ; hole Zeichen
      cmp.b    #'-',d6              ; Minus ?
      seq      d5                   ; ja, setze Flag
      beq.s    1$                   ; und hole neues Zeichen
      cmp.b    #'+',d6              ; Plus ?
      bne.s    2$                   ; nein, dann Vorzeichen beendet
1$    move.b   (a5)+,d6             ; hole Zeichen


      ; Lies den Exponenten maximal vierstellig.  Bei zu vielen Stellen
      ; gibt es automatisch einen Überlauf.
2$    moveq    #4-1,d0
      moveq    #0,d3                ; Exponentenzahl
      cmp.b    #'9',d6              ; Dezimalziffer ?
      bhi.s    AFPOverflow          ; nein, Fehler
      cmp.b    #'0',d6
      blo.s    AFPOverflow          ; nein, Fehler

4$    mulu     #10,d3
      sub.b    #'0',d6
      add      d6,d3
      move.b   (a5)+,d6
      cmp.b    #'0',d6
      blo.s    3$                   ; wenn Ende
      cmp.b    #'9',d6
      bhi.s    3$                   ; wenn Ende
      dbra     d0,4$


      ; Der Exponent ist zu Ende.  Ermittle den Exponentenfaktor.
3$    move.l   #$80000041,d0        ; beginne mit 1.0
      move.l   #$A0000044,d4        ; vorerst Faktor 10.0
      swap     d5
      btst     #16,d5               ; negativer Exponent ?
      beq.s    5$
      move.l   #$CCCCCD3D,d4        ; ja, dann Faktor 0.1
      bra.s    5$

6$    move.l   d4,d1                ; Faktor
      jsr      _LVOSPMul(a6)
      bvs.s    AFPOverflow          ; wenn Überlauf
5$    dbra     d3,6$


      ; Multipliziere den Exponenten hinein.
      move.l   d7,d1
      jsr      _LVOSPMul(a6)
      bvs.s    AFPOverflow          ; wenn Überlauf
      move.l   d0,d7


AFPEnd
      ; Soll die FFP-Zahl negativ sein ?
      move.l   d7,d0
      tst.b    d5
      beq.s    1$                   ; nein
      jsr      _LVOSPNeg(a6)        ; ja, negiere Zahl
      move.l   d0,d7
1$    subq     #1,a5                ; stelle Zeiger zurück
      move.l   a5,a0
      andi     #~1,CCR              ; lösche das Carry-Flag
      rts



AFPOverflow
      ; Es kam ein Überlauf vor.
      subq     #1,a5                ; zeigt jetzt auf Fehlerstelle
      move.l   a5,a0
      ori      #1,CCR               ; setze das Carry-Flag
      rts

      ENDC










; Exponent = fpa (FFP-Zahl, Stringzeiger)
; Wandelt eine FFP-Fließkommazahl in einen ASCII-String um.

      IFD   fpa_c

      XDEF  _fpa

      XREF  FFPFPA

_fpa_REG REG   d1-d7/a0-a6
REGISTER SET   14

_fpa
      movem.l  _fpa_REG,-(SP)
      movem.l  REGISTER*4+4(SP),d0/a0
      jsr      FFPFPA               ; Exponent in D0 zurück
      movem.l  (SP)+,_fpa_REG
      rts

      ENDC










; FFPFPA
; Assemblerversion von _fpa.
; Eingabe:  D0 enthält die FFP-Fließkommazahl.
;           A0 zeigt auf den Zielstring.
; Ausgabe:  D0 enthält den Exponenten als vorzeichenbehafteten 32-Bit-Integer.

      IFD   fpa_a

      INCLUDE  "lvo/math.i"

      XDEF  FFPFPA

      XREF  _MathBase

FFPFPA
      ; Initialisiere.
      move.l   a0,a5                ; Zielzeiger
      move.l   d0,d7                ; FFP-Zahl
      move.l   _MathBase,a6         ; Library-Basis

      ; Ist die Zahl negativ ?
      moveq    #0,d6                ; Exponent
      bclr     #7,d7
      beq.s    1$
      move.b   #'-',(a5)+           ; ja, stelle Minus davor
      bra.s    1$

      ; Ziehe den negativen Exponenten.
3$    move.l   d7,d0
      move.l   #$A0000044,d1
      jsr      _LVOSPMul(a6)
      move.l   d0,d7                ; Zahl mal 10.0
      subq.l   #1,d6                ; dekrementiere Exponent
1$    move.l   d7,d0
      move.l   #$80000041,d1        ; vergleiche mit 1.0
      jsr      _LVOSPCmp(a6)
      bge.s    2$                   ; wenn größer gleich 1.0
      move.l   d7,d1
      jsr      _LVOSPTst(a6)
      bne.s    3$                   ; wenn ungleich Null
      bra.s    2$

      ; Ziehe den positiven Exponenten.
4$    move.l   d7,d0
      move.l   #$CCCCCD3D,d1
      jsr      _LVOSPMul(a6)
      move.l   d0,d7                ; Zahl mal 0.1
      addq.l   #1,d6                ; inkrementiere Exponent
2$    move.l   d7,d0
      move.l   #$A0000044,d1        ; vergleiche mit 10.0
      jsr      _LVOSPCmp(a6)
      bge.s    4$                   ; solange größer gleich 10.0

      ; Was steht vor dem Komma ?
      move.l   d7,d0
      jsr      _LVOSPFix(a6)
      move     d0,d1
      add.b    #'0',d1              ; ergibt ASCII-Ziffer
      move.b   d1,(a5)+
      jsr      _LVOSPFlt(a6)
      move.l   d0,d1
      move.l   d7,d0
      jsr      _LVOSPSub(a6)
      beq.s    FPAExp               ; wenn nichts mehr nach dem Komma kommt
      move.b   #'.',(a5)+
      moveq    #6-1,d5              ; maximale Nachkommastellen


      ; Gib die Nachkommastellen aus.
5$    move.l   d0,d7
      move.l   #$A0000044,d1
      jsr      _LVOSPMul(a6)        ; Zahl mal 10.0
      move.l   d0,d7
      jsr      _LVOSPFix(a6)
      move     d0,d1
      add.b    #'0',d1              ; ergibt ASCII-Ziffer
      move.b   d1,(a5)+
      jsr      _LVOSPFlt(a6)
      move.l   d0,d1
      move.l   d7,d0
      jsr      _LVOSPSub(a6)
      dbeq     d5,5$                ; wenn noch Nachkommastellen


FPAExp
      ; Ist der Exponent Null ?
      move.l   d6,d0                ; Rückgabewert
      beq.s    0$                   ; ja, dann nicht ausgeben und Ende

      ; Ist der Exponenten negativ ?
      move.b   #'e',(a5)+
      move.b   #'+',(a5)+
      tst.l    d6
      bpl.s    1$
      neg.l    d6                   ; ja
      move.b   #'-',-1(a5)          ; gib Minus aus

      ; Der Exponent ist zweistellig.
1$    divu     #10,d6
      add.b    #'0',d6
      move.b   d6,(a5)+             ; 10er-Stelle
      swap     d6
      add.b    #'0',d6
      move.b   d6,(a5)+             ; 1er-Stelle

      ; Fertig !
0$    clr.b    (a5)                 ; Stringende
      rts

      ENDC










      END

