home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pcmagazi
/
1990
/
05
/
pp905
/
ftoa.asm
< prev
next >
Wrap
Assembly Source File
|
1989-10-26
|
11KB
|
279 lines
title FTOA - floating point to ASCII
page 55,132
; FTOA.ASM --- Convert Binary Floating Point
; Number on 80x87 Stack to ASCII
; (also requires FALOG from FALOG.ASM)
;
; Copyright (C) 1989 Ziff Davis Communications
; PC Magazine * Ray Duncan
;
; Call with: ST(0) = floating point number
; DS:SI = buffer to receive string
;
; Returns: DS:SI = address of converted string
; AX = length of string
; Coprocessor stack "popped"
;
; Uses: Nothing
;
; Make sure coprocessor has been properly initialized
; with a previous call to INIT87!
_DATA segment word public 'DATA'
sign dw 0 ; receives FXAM status
oldcw dw 0 ; previous rounding mode
newcw dw 0 ; new rounding mode
exp dw 0 ; extracted power of ten
status dw 0 ; receives FCOM status
mant dt 0 ; mantissa as BCD value
fp1e17 dq 1.0e17 ; constant for scaling
fp1e18 dq 1.0e18 ; constant for scaling
int10 dw 10 ; constant for scaling
pzstr db '+0.000000000000000000E+000' ; displayed if
pz_len equ $-pzstr ; ST(0) = +0
mzstr db '-0.000000000000000000E+000' ; displayed if
mz_len equ $-mzstr ; ST(0) = -0
pistr db '<+infinity>' ; displayed if ST(0)
pi_len equ $-pistr ; is positive infinity
mistr db '<-infinity>' ; displayed if ST(0)
mi_len equ $-mistr ; is negative infinity
nanstr db '<NaN>' ; displayed if ST(0)
nan_len equ $-nanstr ; contains Not-A-Number
unstr db '<unnormal>' ; displayed for positive
un_len equ $-unstr ; or negative unnormals
destr db '<denormal>' ; displayed for positive
de_len equ $-destr ; or negative denormals
empstr db '<empty>' ; displayed if ST(0)
emp_len equ $-empstr ; is tagged "empty"
; number types from
; condition code bits
typetab dw ftoa14 ; 0000 +unnormal
dw ftoa15 ; 0001 +NaN
dw ftoa14 ; 0010 -unnormal
dw ftoa15 ; 0011 -Nan
dw ftoa1 ; 0100 +normal
dw ftoa16 ; 0101 +infinity
dw ftoa1 ; 0110 -normal
dw ftoa17 ; 0111 -infinity
dw ftoa10 ; 1000 +zero
dw ftoa12 ; 1001 empty
dw ftoa11 ; 1010 -zero
dw ftoa12 ; 1011 empty
dw ftoa13 ; 1100 +denormal
dw ftoa12 ; 1101 empty
dw ftoa13 ; 1110 -denormal
dw ftoa12 ; 1111 empty
_DATA ends
_TEXT segment word public 'CODE'
assume cs:_TEXT,ds:_DATA
extrn falog:near ; we need FALOG routine
public ftoa
ftoa proc near ; floating point to ASCII
push bx ; save registers
push cx
push dx
push di
push es
push ds ; let ES point to _DATA
pop es
fxam ; test type of number
fstsw sign ; unload FXAM status
fwait
mov bx,sign ; retrieve status and
and bx,4700h ; shift C3, C2, C1, C0
rol bx,1 ; status bits to form
rol bx,1 ; value 0-15, then
shl bh,1 ; *2 for jump index
shl bh,1
shl bh,1
rol bx,1
rol bx,1
rol bx,1
shl bx,1
jmp [typetab+bx] ; branch by number type
ftoa1: fabs ; force number positive
fxtract ; extract exponent
fxch st(1) ; put exponent on top
fldlg2 ; form power of 10
fmulp st(1),st(0)
fstcw oldcw ; save current rounding mode
fwait
mov ax,oldcw ; set bit field for rounding
or ax,0c00h ; mode to "chop"
mov newcw,ax
fldcw newcw ; force new rounding mode
fld st(0) ; duplicate power of ten
frndint ; find integer part of
fist exp ; exponent and save it
fldcw oldcw ; restore old rounding mode
fsubp st(1),st(0) ; find fractional part of
call falog ; power of ten
fmulp st(1),st(0) ; then times mantissa
fmul fp1e18 ; scale mantissa for BCD
frndint ; zap any remaining fraction
ftoa2: fcom fp1e17 ; is mantissa < 1.0e17?
fstsw status
fwait
mov ax,status
sahf
jae ftoa3 ; no, proceed
fimul int10 ; yes, mantissa * 10
dec exp ; and decrement exponent
jmp ftoa2
ftoa3: fcom fp1e18 ; is mantissa < 1.0e18?
fstsw status
fwait
mov ax,status
sahf
jb ftoa4 ; yes, proceed
fidiv int10 ; yes, mantissa / 10
inc exp ; and increment exponent
jmp ftoa3
ftoa4: fbstp mant ; unload mantissa in BCD
fwait
mov di,si ; address for ASCII string
mov al,'+' ; assume positive
test sign,200h ; check FXAM flags
jz ftoa5 ; jump, value was positive
mov al,'-'
ftoa5: stosb ; store + or - sign
mov al,'0' ; store leading zero
stosb
mov al,'.' ; store decimal point
stosb
mov bx,8 ; point to last BCD digits
ftoa6: mov al,byte ptr [bx+mant] ; convert BCD byte to
shr al,1 ; two ASCII digits
shr al,1
shr al,1
shr al,1
call digit ; convert high nibble
mov al,byte ptr [bx+mant]
call digit ; convert low nibble
dec bx ; back up through BCD value
jns ftoa6 ; until 18 digits converted
mov al,'E' ; store 'E' for exponent
stosb
mov bx,exp ; test sign of exponent
mov al,'+'
or bx,bx
jns ftoa7 ; jump, exponent positive
mov al,'-'
neg bx ; abs. value of exponent
ftoa7: stosb ; store sign of exponent
mov ax,bx ; convert exponent to
cwd ; three ASCII digits
mov cx,100
div cx
call digit ; exponent hundreds digit
mov ax,dx
cwd
mov cx,10
div cx
call digit ; exponent tens digit
mov ax,dx
call digit ; exponent ones digit
ftoa8: mov ax,di ; return AX = string length
sub ax,si ; and DS:SI = string address
pop es ; restore registers
pop di
pop dx
pop cx
pop bx
ret
ftoa10: mov di,offset pzstr ; +zero value
mov cx,pz_len
jmp ftoa20
ftoa11: mov di,offset mzstr ; -zero value
mov cx,mz_len
jmp ftoa20
ftoa12: mov di,offset empstr ; empty value
mov cx,emp_len
jmp ftoa20
ftoa13: mov di,offset destr ; denormal value
mov cx,de_len
jmp ftoa20
ftoa14: mov di,offset unstr ; unnormal value
mov cx,un_len
jmp ftoa20
ftoa15: mov di,offset nanstr ; NaN value
mov cx,nan_len
jmp ftoa20
ftoa16: mov di,offset pistr ; +infinity value
mov cx,pi_len
jmp ftoa20
ftoa17: mov di,offset mistr ; -infinity value
mov cx,mi_len
ftoa20: xchg si,di ; SI = canned string
push di ; DI = caller's buffer
rep movsb ; copy canned string
pop si ; restore SI
fstp st(0) ; discard original value
jmp ftoa8 ; go to common exit point
ftoa endp
;
; DIGIT: Convert low nibble of AL to ASCII digit
; and store at address given by DS:DI
; Call with: AL = value to be converted in bits 0-3
; ES:DI = address to store ASCII character
; Returns: AL = unchanged
; ES:DI = address+1
;
digit proc near ; nibble to ASCII digit
push ax ; save register
and al,0fh ; isolate nibble
add al,'0' ; convert to ASCII char
stosb ; store the character
pop ax ; restore register
ret
digit endp
_TEXT ends
end