home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1990 / 05 / pp905 / ftoa.asm < prev    next >
Assembly Source File  |  1989-10-26  |  11KB  |  279 lines

  1.         title   FTOA - floating point to ASCII
  2.         page    55,132
  3.  
  4. ; FTOA.ASM ---  Convert Binary Floating Point
  5. ;               Number on 80x87 Stack to ASCII                  
  6. ;               (also requires FALOG from FALOG.ASM)
  7. ;
  8. ; Copyright (C) 1989 Ziff Davis Communications
  9. ; PC Magazine * Ray Duncan
  10. ;
  11. ; Call with:    ST(0) = floating point number
  12. ;               DS:SI = buffer to receive string
  13. ;
  14. ; Returns:      DS:SI = address of converted string
  15. ;               AX    = length of string
  16. ;               Coprocessor stack "popped"
  17. ;
  18. ; Uses:         Nothing
  19. ;
  20. ; Make sure coprocessor has been properly initialized
  21. ; with a previous call to INIT87!
  22.  
  23. _DATA   segment word public 'DATA'
  24.  
  25. sign    dw      0                       ; receives FXAM status
  26. oldcw   dw      0                       ; previous rounding mode
  27. newcw   dw      0                       ; new rounding mode
  28. exp     dw      0                       ; extracted power of ten
  29. status  dw      0                       ; receives FCOM status
  30. mant    dt      0                       ; mantissa as BCD value
  31.  
  32. fp1e17  dq      1.0e17                  ; constant for scaling
  33. fp1e18  dq      1.0e18                  ; constant for scaling
  34. int10   dw      10                      ; constant for scaling
  35.  
  36. pzstr   db      '+0.000000000000000000E+000'    ; displayed if
  37. pz_len  equ     $-pzstr                         ; ST(0) = +0
  38.  
  39. mzstr   db      '-0.000000000000000000E+000'    ; displayed if
  40. mz_len  equ     $-mzstr                         ; ST(0) = -0
  41.  
  42. pistr   db      '<+infinity>'           ; displayed if ST(0)
  43. pi_len  equ     $-pistr                 ; is positive infinity
  44.  
  45. mistr   db      '<-infinity>'           ; displayed if ST(0)
  46. mi_len  equ     $-mistr                 ; is negative infinity
  47.  
  48. nanstr  db      '<NaN>'                 ; displayed if ST(0)
  49. nan_len equ     $-nanstr                ; contains Not-A-Number
  50.  
  51. unstr   db      '<unnormal>'            ; displayed for positive
  52. un_len  equ     $-unstr                 ; or negative unnormals
  53.  
  54. destr   db      '<denormal>'            ; displayed for positive
  55. de_len  equ     $-destr                 ; or negative denormals
  56.  
  57. empstr  db      '<empty>'               ; displayed if ST(0)
  58. emp_len equ     $-empstr                ; is tagged "empty"
  59.  
  60.                                         ; number types from
  61.                                         ; condition code bits
  62. typetab dw      ftoa14                  ; 0000 +unnormal
  63.         dw      ftoa15                  ; 0001 +NaN
  64.         dw      ftoa14                  ; 0010 -unnormal
  65.         dw      ftoa15                  ; 0011 -Nan
  66.         dw      ftoa1                   ; 0100 +normal
  67.         dw      ftoa16                  ; 0101 +infinity
  68.         dw      ftoa1                   ; 0110 -normal
  69.         dw      ftoa17                  ; 0111 -infinity
  70.         dw      ftoa10                  ; 1000 +zero
  71.         dw      ftoa12                  ; 1001 empty
  72.         dw      ftoa11                  ; 1010 -zero
  73.         dw      ftoa12                  ; 1011 empty
  74.         dw      ftoa13                  ; 1100 +denormal
  75.         dw      ftoa12                  ; 1101 empty
  76.         dw      ftoa13                  ; 1110 -denormal
  77.         dw      ftoa12                  ; 1111 empty
  78.  
  79. _DATA   ends
  80.  
  81. _TEXT   segment word public 'CODE'
  82.  
  83.         assume  cs:_TEXT,ds:_DATA
  84.  
  85.         extrn   falog:near              ; we need FALOG routine 
  86.  
  87.         public  ftoa
  88. ftoa    proc    near                    ; floating point to ASCII
  89.  
  90.         push    bx                      ; save registers
  91.         push    cx
  92.         push    dx
  93.         push    di
  94.         push    es
  95.  
  96.         push    ds                      ; let ES point to _DATA
  97.         pop     es
  98.  
  99.         fxam                            ; test type of number
  100.         fstsw   sign                    ; unload FXAM status
  101.         fwait
  102.         mov     bx,sign                 ; retrieve status and
  103.         and     bx,4700h                ; shift C3, C2, C1, C0
  104.         rol     bx,1                    ; status bits to form
  105.         rol     bx,1                    ; value 0-15, then
  106.         shl     bh,1                    ; *2 for jump index
  107.         shl     bh,1
  108.         shl     bh,1
  109.         rol     bx,1
  110.         rol     bx,1
  111.         rol     bx,1
  112.         shl     bx,1
  113.         jmp     [typetab+bx]            ; branch by number type
  114.  
  115. ftoa1:  fabs                            ; force number positive
  116.         fxtract                         ; extract exponent
  117.         fxch    st(1)                   ; put exponent on top
  118.         fldlg2                          ; form power of 10
  119.         fmulp   st(1),st(0)
  120.         fstcw   oldcw                   ; save current rounding mode
  121.         fwait
  122.         mov     ax,oldcw                ; set bit field for rounding
  123.         or      ax,0c00h                ; mode to "chop"
  124.         mov     newcw,ax
  125.         fldcw   newcw                   ; force new rounding mode
  126.         fld     st(0)                   ; duplicate power of ten
  127.         frndint                         ; find integer part of 
  128.         fist    exp                     ; exponent and save it
  129.         fldcw   oldcw                   ; restore old rounding mode
  130.         fsubp   st(1),st(0)             ; find fractional part of
  131.         call    falog                   ; power of ten
  132.         fmulp   st(1),st(0)             ; then times mantissa
  133.         fmul    fp1e18                  ; scale mantissa for BCD
  134.         frndint                         ; zap any remaining fraction
  135.         
  136. ftoa2:  fcom    fp1e17                  ; is mantissa < 1.0e17?
  137.         fstsw   status
  138.         fwait
  139.         mov     ax,status
  140.         sahf
  141.         jae     ftoa3                   ; no, proceed
  142.         fimul   int10                   ; yes, mantissa * 10
  143.         dec     exp                     ; and decrement exponent
  144.         jmp     ftoa2
  145.  
  146. ftoa3:  fcom    fp1e18                  ; is mantissa < 1.0e18?
  147.         fstsw   status
  148.         fwait
  149.         mov     ax,status
  150.         sahf
  151.         jb      ftoa4                   ; yes, proceed
  152.         fidiv   int10                   ; yes, mantissa / 10
  153.         inc     exp                     ; and increment exponent
  154.         jmp     ftoa3
  155.  
  156. ftoa4:  fbstp   mant                    ; unload mantissa in BCD
  157.         fwait
  158.         mov     di,si                   ; address for ASCII string
  159.         mov     al,'+'                  ; assume positive
  160.         test    sign,200h               ; check FXAM flags
  161.         jz      ftoa5                   ; jump, value was positive
  162.         mov     al,'-'
  163.  
  164. ftoa5:  stosb                           ; store + or - sign
  165.         mov     al,'0'                  ; store leading zero
  166.         stosb
  167.         mov     al,'.'                  ; store decimal point
  168.         stosb
  169.         mov     bx,8                    ; point to last BCD digits
  170.  
  171. ftoa6:  mov     al,byte ptr [bx+mant]   ; convert BCD byte to
  172.         shr     al,1                    ; two ASCII digits
  173.         shr     al,1
  174.         shr     al,1
  175.         shr     al,1
  176.         call    digit                   ; convert high nibble
  177.         mov     al,byte ptr [bx+mant]
  178.         call    digit                   ; convert low nibble
  179.         dec     bx                      ; back up through BCD value
  180.         jns     ftoa6                   ; until 18 digits converted
  181.  
  182.         mov     al,'E'                  ; store 'E' for exponent
  183.         stosb
  184.         mov     bx,exp                  ; test sign of exponent
  185.         mov     al,'+'
  186.         or      bx,bx
  187.         jns     ftoa7                   ; jump, exponent positive
  188.         mov     al,'-'
  189.         neg     bx                      ; abs. value of exponent
  190.  
  191. ftoa7:  stosb                           ; store sign of exponent
  192.  
  193.         mov     ax,bx                   ; convert exponent to
  194.         cwd                             ; three ASCII digits
  195.         mov     cx,100
  196.         div     cx
  197.         call    digit                   ; exponent hundreds digit
  198.         mov     ax,dx                      
  199.         cwd
  200.         mov     cx,10
  201.         div     cx
  202.         call    digit                   ; exponent tens digit
  203.         mov     ax,dx
  204.         call    digit                   ; exponent ones digit
  205.  
  206. ftoa8:  mov     ax,di                   ; return AX = string length
  207.         sub     ax,si                   ; and DS:SI = string address
  208.         
  209.         pop     es                      ; restore registers
  210.         pop     di
  211.         pop     dx
  212.         pop     cx
  213.         pop     bx
  214.         ret
  215.  
  216. ftoa10: mov     di,offset pzstr         ; +zero value
  217.         mov     cx,pz_len
  218.         jmp     ftoa20
  219.  
  220. ftoa11: mov     di,offset mzstr         ; -zero value
  221.         mov     cx,mz_len
  222.         jmp     ftoa20
  223.  
  224. ftoa12: mov     di,offset empstr        ; empty value
  225.         mov     cx,emp_len
  226.         jmp     ftoa20
  227.  
  228. ftoa13: mov     di,offset destr         ; denormal value
  229.         mov     cx,de_len
  230.         jmp     ftoa20
  231.  
  232. ftoa14: mov     di,offset unstr         ; unnormal value
  233.         mov     cx,un_len
  234.         jmp     ftoa20
  235.  
  236. ftoa15: mov     di,offset nanstr        ; NaN value
  237.         mov     cx,nan_len
  238.         jmp     ftoa20
  239.  
  240. ftoa16: mov     di,offset pistr         ; +infinity value
  241.         mov     cx,pi_len
  242.         jmp     ftoa20
  243.  
  244. ftoa17: mov     di,offset mistr         ; -infinity value
  245.         mov     cx,mi_len
  246.  
  247. ftoa20: xchg    si,di                   ; SI = canned string
  248.         push    di                      ; DI = caller's buffer
  249.         rep movsb                       ; copy canned string
  250.         pop     si                      ; restore SI
  251.         fstp    st(0)                   ; discard original value
  252.         jmp     ftoa8                   ; go to common exit point
  253.  
  254. ftoa    endp
  255.  
  256. ;
  257. ; DIGIT:        Convert low nibble of AL to ASCII digit
  258. ;               and store at address given by DS:DI
  259. ; Call with:    AL    = value to be converted in bits 0-3
  260. ;               ES:DI = address to store ASCII character
  261. ; Returns:      AL    = unchanged
  262. ;               ES:DI = address+1
  263. ;
  264. digit   proc    near                    ; nibble to ASCII digit
  265.  
  266.         push    ax                      ; save register
  267.         and     al,0fh                  ; isolate nibble
  268.         add     al,'0'                  ; convert to ASCII char
  269.         stosb                           ; store the character
  270.         pop     ax                      ; restore register
  271.         ret
  272.  
  273. digit   endp
  274.  
  275. _TEXT   ends
  276.  
  277.         end
  278.  
  279.