home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
DRI-archive
/
roche
/
FLTOUT.ASM
< prev
next >
Wrap
Assembly Source File
|
2009-12-11
|
10KB
|
466 lines
; FLTOUT.ASM
; ----------
;
; See FALCONER.WS4 for doc.
;
; (Retyped by Emmanuel ROCHE.)
;
;--------------------------------
; External calls required
;
extrn derc,dten ; in INTARITH
extrn fdivt,fload,fmult ; in FLTARITH
;
;--------------------------------
; External connectors to list and console drivers
;
extrn lout,cout ; Undefined in system,
; output (C), Set (A) := (C).
;
;--------------------------------
; Entry points allowed
;
entry lflt,tflt,oflt,fmat
;
;--------------------------------
; Entry points to utility routines
;
entry exdg,otcbk,otccl
entry opt,oneg,odzs
;
;--------------------------------
; Macro definitions
;--------------------------------
;
; Load (reg) from TOS and leave on stack (reg)
;
ltos macro reg
pop reg
push reg
endm
;
; "Return" and check stacl level zero
;
rtn macro
if .lvl
error "0"+.lvl
.lvl set 0
endif
ret
endm
;
; Trade (A) digits, leave LSB in Carry (A,F)
;
tdig macro
rlc
rlc
rlc
rlc
endm
;
;--------------------------------è; Utility routines
;--------------------------------
;
; Output blank to console/lister
; Use lister if (A) sign bit=1; else console
; A,F,C
;
otcbk: mvi c,' ' ;
;
; Output a character
; Use lister if (A) sign bit=1; else console
; A,F,C
;
otccl: rlc ;
jc lout ;
jmp cout ; On console
;
; Output (A) blanks
; Use lister if (A) sign bit=1; else console
; A,F
;
hblk: push b ;
mov b,a ;
jmp hblk2 ; Check for zero
hblk1: mov a,b ;
call otcbk ;
dcr b ;
mov a,b ;
hblk2: ani 7FH ;
jnz hblk1 ;
pop b ;
rtn ;
;
; Output a decimal point
; Use lister if (A) sign bit=1; else console
; A,F,C
;
opt: mvi c,'.' ; Decimal point
jmp otccl ;
;
; Output "-"
; Use lister if (A) sign bit=1; else console
; A,F,C
;
oneg: mvi c,'-' ; Negative sign
jmp otccl ;
;
; Output (HL) in decimal, suppress leading zeros
; Use lister if (A) sign bit=1; else console
;
odzs: push b ;
mvi b,5 ;
push psw ; Preserve
odzs2: call exdg ; Extract a digit
jnz odzs4 ; Non-zero, end suppress
dcr b ;
jnz odzs2 ; Continue suppression
inr b ; Re-extract final zero and output
odzs3: call exdg ; Get next digit
odzs4: ltos psw ; è call otccl ; Output to console or lister
dcr b ;
jnz odzs3 ;
pop psw ;
pop b ;
rtn ;
;
; Extract a decimal digit, 10^((B)-1), from (HL).
; ASCII digit returned in (C) and (A)
; with Zero flag for digit=zero.
; A,F,C
;
exdg: push h ;
push b ;
exdg1: call dten ;
dcr b ;
jnz exdg1 ;
adi '0' ;
cpi '0' ;
pop b ;
pop h ;
mov c,a ;
rtn ;
;
;--------------------------------
; End utility routines
;--------------------------------
;
; "Fixed" point representation consist of a 16 bit positive
; integer (in the range 0 to 65535), and a 7 bit offset (by
; 40H) integer exponent, which represents a power of ten
; multiplier. The eighth exponent bit represents the sign
; of the mantissa. This representation is used for input/
; output only.
;
; Convert "real" format to "fixed" format
; A,F,D,E,H
;
fix: mov a,h ;
ora a ;
jnz fix1 ; Value not zero
mvi h,40H ; 00000
lxi d,0 ;
rtn ;
fix1: cpi 91H ;
push b ;
mvi b,40H ; Decimal exponent
@01 set .lvl ;
jnc fix5 ; > 65535, integer
cpi 8EH ;
jnc fix6 ; Treat as left shifted integer
fix2: call fmult ; < 32768
dcr b ;
mov a,h ;
sui 90H ;
jc fix2 ; Still fractional segment
jnz fix5 ; Not now integer
fix3: mov a,d ;
ani 80H ; Extract sign
ora b ; è mov h,a ;
mov a,d ;
ori 80H ; Set MSbit, range 32768/65535
mov d,a ;
pop b ;
rtn ;
.lvl set @01 ;
fix5: call fdivt ; Integer > 65535
inr b ;
mov a,h ;
fix6: sui 90H ;
jz fix3 ; Now integer representation
jnc fix5 ;
mov h,a ; Range -1 to -4
mov a,d ;
ani 80H ; Result sign
ora b ;
mov b,a ;
mov a,d ;
ori 80H ;
mov d,a ;
fix7: ora a ; Reset Carry
call derc ;
inr h ;
jnz fix7 ; Shift off fractional segment
jnc fix8 ; No rounding needed
inx d ;
fix8: mov h,b ;
pop b ;
ora a ; Reset Carry
rtn ;
;
; ***** Output routines *****
;
; Output (DE.H) in "fixed" form
; Suppress leading zeroes
; If A >= 0, to console. If a < 0, to lister.
; A,F,B,C,D,E,H,L
;
ofix: push psw ;
mov a,h ;
ani 80H ;
jp ofix1 ; Positive
ltos psw ; Output "-" sign
call oneg ; Send a "-" sign
ofix1: mov a,h ;
ani 7FH ; Remove sign
sui 40H-6 ; Signed decimal exponent
mov h,a ;
xchg ; Value in HL, exponent in D
mvi b,6 ; First digit
ofix2: dcr b ;
@01 set .lvl ;
jz ofixa ; Done, all digits 0
dcr d ;
jz ofix7 ; Decimal point here
jm ofix7 ; xxxxE-xx
call exdg ;
jz ofix2 ; Suppress a zero
ofix3: ltos psw ;
call otccl ; List a digitè dcr d ;
jnz ofix4 ;
ltos psw ;
call opt ; Decimal point here
ofix4: dcr b ;
jz ofix5 ; All digits listed
call exdg ;
jmp ofix3 ; List next digit
ofix5: xra a ;
sub d ;
jp ofixb ; Not xxxx.E+xx
adi 3 ;
jm ofix6 ; > 9999000
mvi c,"0" ;
ltos psw ;
call otccl ;
dcr d ;
jmp ofix5 ;
ofix6: mvi c,'E' ;
ltos psw ;
call otccl ;
mov l,d ;
mvi h,0 ;
pop psw ;
jmp odzs ; List exponent
.lvl set @01 ;
ofix7: ltos psw ;
call opt ; .xxxxE-xx
ofix8: mov a,d ;
ora a ;
jz ofix9 ; Zero exponent
adi 3 ;
jm ofix9 ; Range -1 to -3, insert 0's
mvi c,"0" ;
ltos psw ;
call otccl ;
inr d ;
jmp ofix8 ; Check for more 0's
ofix9: call exdg ;
ltos psw ;
call otccl ;
dcr b ;
jnz ofix9 ;
xra a ;
mov h,a ;
sub d ;
mov l,a ;
jz ofixb ; Ignore zero exponent
mvi c,'E' ;
ltos psw ;
call otccl ;
ltos psw ;
call oneg ;
pop psw ;
jmp odzs ; List exponent and exit
.lvl set @01 ;
ofixa: ltos psw ;
call otccl ; List a zero
ofixb: pop psw ;
rtn ;
;
; Output "real" (DE.H) to listerè;
lflt: push psw ;
mvi a,-1 ; Identify as lister output
call oflt ;
pop psw ;
rtn ;
;
; Output "real" (DE.H) to console
;
tflt: push psw ;
mvi a,0 ; Identify as console output
call oflt ;
pop psw ;
rtn ;
;
; Output "real"
; If A < 0, to lister. If A >= 0, to console.
; A
;
oflt: push b ;
push d ;
push h ;
push psw ;
call fix ;
pop psw ; Get destination
call ofix ;
pop h ;
pop d ;
pop b ;
rtn ;
;
; Output (DE.H) with format specification in (A)
;
; (A) bit field Meaning
; ------------- -------
; 0:1 (LH bit) 1=to lister, 0=to console
; 1:3 (3 bits) Places to left of decimal point
; 4:1 (1 bit) Use free format, ignore places spec
; 5:3 (3 RH bits) Places to right of decimal point
;
fmat: push psw ;
push b ;
push d ;
push h ;
push psw ; Save places
call fix ;
ltos psw ;
call ajfx ; Adjust on right of dec point
call tpsn ; Position the field
pop psw ; For list/console destination
call ofix ; Output the data
pop h ; and restore registers.
pop d ;
pop b ;
pop psw ;
rtn ;
;
; Adjust "fixed" format for (A) digits after decimal point
; Max digits=7, 8 bit for floating format
; Round the result
; D,E,Hè;
ajfx: push psw ;
push b ;
push h ; Save BC.L
ani 15 ;
cpi 8 ;
jnc ajfx4 ; Floating format, no adjust
ani 7 ; 7 digits max
mov c,a ; Digits required
ajfx1: mov a,h ;
ani 7FH ; Remove sign
sui 40H ;
add c ;
jp ajfx4 ; No excess fractional segment
mov b,a ;
xchg ;
ajfx2: call dten ; Remove a digit
inr d ; Adjust decimal exponent
inr b ;
jm ajfx2 ; Remove more
cpi 5 ;
jc ajfx3 ; No rounding
inx h ;
ajfx3: xchg ;
jmp ajfx1 ; In case rounding added digit
ajfx4: pop b ; Reload BC.L
mov l,c ;
pop b ;
pop psw ;
rtn ;
;
; Control leading blanks via bits 1:3 of (A)
; Bit 4:1 specifies free format else output blanks
; required to place the decimal point at the
; field position to right of starting point.
;
tpsn: push psw ;
push b ;
push psw ;
ani 8 ;
jnz tpsn9 ; Free format
pop psw ;
ani 0F0H ;
mov b,a ;
ani 70H ;
tdig ;
mov c,a ; Count of places needed
push b ;
mov a,h ;
ani 7FH ;
sui 40H ; Form dp loc wrt right digit
jm tpsn5 ; Fract segment
inr a ;
cmp b ;
jnc tpsn9 ; Too large, use free format
mvi a,0 ; Use value zero?
tpsn5: mov b,a ; Negative value
call ndig ; Count of sig digits in value
add b ; to left of decimal point
jp tpsn6 ; There are someè mvi a,0 ; One + zeroes after dec point
tpsn6: pop b ;
cma ;
inr a ;
add c ; Spaces required
jp tpsn8 ;
mvi a,0 ; Can't allow negative count
tpsn8: mov c,a ;
mov a,h ;
ora a ;
jp tpsn7 ; Positive value
dcr c ; Allow for - sign
jp tpsn7 ; Room
inr c ; No room, move all right
tpsn7: mov a,b ;
ani 80H ; File flag
ora c ;
call hblk ; Space as required
push psw ;
tpsn9: pop psw ;
pop b ;
pop psw ;
rtn ;
;
; Return count of significant digits in (DE)
; Treating (DE) as decimal integer with leading
; zeroes suppressed. Return 1 for value 00000.
; A,F
;
ndig: push b ;
push d ;
xchg ;
mvi b,0 ;
ndig1: inr b ;
call dten ;
mov a,h ;
ora l ;
jnz ndig1 ; More digits left
mov a,b ;
xchg ;
pop d ;
pop b ;
rtn ;
;
;--------------------------------
;
end ; of FLTOUT.ASM