;From Fanny Pahlplatz - MATH-COPROCESSOR COM
COMMENT ~
> I've found 80xxx.zip and something else that has fp op-codes
> but I haven't found any examples of how to use them. (when and why)
Here's an example, with some how, when and why chat.
x = x(t) is a function of time, x' and x" first and second derivatives,
x" = -x + m(1-xx)x', m > 0
Calculate by taking small time steps, h, using
x(t+h) = x(t) + x(t)' * h
x(t+h)' = x(t)' + x(t)" * h
or, in short, writing y = x', using the diff.eq. above,
y = y + (m(1-xx)y - x)h
x = x + yh
The differential equation (named a "relaxation oscillation", formulated
by van der Pol for an electronic circuit) is interesting, because it has
a periodic "attractor" as a solution: normally you would have to take no
end of care to preserve precision as you step along the curve, but in this
case precision takes care of itself.
If you run it, to see what happens if attractiveness fails, try
m=0: then x(t) = a * cos t (for any a) would be a solution, but the
picture becomes a runaway.
Still, use of floating point is indicated, not for the precision,
but for the range: x' gets rather large (the curve gets steep)
while x remains small, about -2.1 < x < 2.1 That would be difficult
to manage in fixed point.
> It's that quest for that fast and simple 64 bit signed multiply
> and divide for those finer fractal images.
No quest here (though modern math does find much interest in these
nonlinear diff. eqs.), but it is an attractive family of curves, I
thought.
COMMENT ENDS ~
.286
.model small
.stack
.data
control dw 0
oldmode dw 0
m dw 1
c_100 dw 100
hinv dw 20h
; Initialize for gridlines at x = 2,1,0,-1,-2 (scale 100).
; Proc next_x will write calculated values into ix[].
ix LABEL WORD
REPT 128
dw -200,-100,0,100,200
ENDM
.code
; Comments show the copro stack, top at right. Capitals for results.
next_x PROC
FLD1 ; h m x y 1
FLD st(2) ; h m x y 1 x
FMUL st, st(3) ; h m x y 1 xx
FSUB ; h m x y 1-xx
FLD st(3) ; h m x y 1-xx m
FMUL ; h m x y M
FLD st(1) ; h m x y M y
FMUL ; h m x y My
FLD st(2) ; h m x y My x
FSUB ; h m x y My-x
FLD st(4) ; h m x y My-x h
FMUL ; h m x y (My-x)h
FLD st(1) ; h m x y (My-x)h y
FADD ; h m x y Y
FXCH ; h m x Y y
FLD st(4) ; h m x Y y h
FMUL ; h m x Y yh
FADDP st(2), st ; h m X Y
FLD st(1) ; h m X Y X
FILD c_100 ; h m X Y X 100
FMUL ; h m X Y 100X
FISTP ix[si] ; h m X Y
FWAIT
ret
next_x ENDP
@setport MACRO n, value
mov dx,3CEh
mov al,n
out dx,al
inc dx
mov al, value
out dx,al
ENDM
@SR MACRO color
@setport 0, color
ENDM
@ESR MACRO planes
@setport 1, planes
ENDM
@BM MACRO pixels
@setport 8, pixels
ENDM
setpixel PROC
mov cx, si ; si points to words, so
shr cx, 1 ; count by twos [cfr. below]
and cx, 0007 ; pixel position in byte
mov ah, 80h
shr ah, cl
@BM ah ; Bitmask
@SR bl ; set color
mov di, 240 ; address byte =
sub di, ix[si] ; (240-row)
shl di, 4
mov ax, di
shl ax, 2
add di, ax ; * 80
mov ax, si ;
shr ax, 4 ; [1 extra, counting by twos]
add di, ax ; + col >> 3
mov ah, es:[di] ; dummy read/write
mov es:[di], ah
ret
setpixel ENDP
; gray the old pixel, calculate x(t), color the new pixel, step -- until key
_display PROC
dismore: mov bl, 8 ; gray
call setpixel
call next_x
mov bl, 12 ; red
call setpixel
inc si
inc si
cmp si, 1280 ; 640 pixels wide; si points to words
jl L1
sub si, 1280
L1: mov ah, 11h
int 16h ; kbhit?
jz dismore
ret
_display ENDP
main:
mov ax, @DATA
mov ds, ax
mov ax, 0A000h
mov es, ax
mov ah, 0Fh ; getmode (be kind)
int 10h
xor ah, ah
mov [oldmode], ax
mov ax, 0012h ; setmode
int 10h
@ESR 0Fh ; access bitplanes
; check for copro; default 03FF -- for mine, anyway.
FINIT
FSTCW control
FWAIT
cmp control, 03FFh
jnz g_out
xor si, si ; timeline
FLD1 ; 1
FILD hinv ; 1 20hex
FDIV ; h=0.08hex
; First entry with m=1 (see data seg.)
; Initialize x small and level (x'=0), to see it 'find' the curve.
again: FILD m ; h m
FLD st(1) ; h m x=h
FLDZ ; h m x y=0
FWAIT
call _display
g_key: mov ah, 10h ; Esc or m = 0 .. 8
int 16h
cmp al, 1Bh
jz g_out
cmp al, '0' ; Notice the case m=0 is unstable
jb g_key
cmp al, '8'
ja g_key
sub al, '0'
mov byte ptr [m], al
FSTP st ; h m x
FSTP st ; h m
FSTP st ; h
jmp short again
g_out: mov ax, [oldmode]
int 10h
mov ax, 4C00h
int 21h
end main