📄 calmanfp.asm
字号:
fninit
mov color,ax
cmp orbit_ptr,0 ; any orbits to clear?
je calcmandfpasm_ret_387 ; nope.
call far ptr scrub_orbit ; clear out any old orbits
mov ax,color ; restore color
; speed not critical here in orbit land
calcmandfpasm_ret_387:
UNFRAME <si,di> ; pop stack frame
fwait ; just to make sure
ret
over_bailout_387: ; x^2 y^2 xy Cx Cy b
; outside
mov ax,cx
sub ax,10 ; 10 more next time before checking
jns no_fix_underflow_387
; if the number of iterations was within 10 of maxit, then subtracting
; 10 would underflow and cause periodicity checking to start right
; away. Catching a period doesn't occur as often in the pixels at
; the edge of the set anyway.
sub ax,ax ; don't check next time
no_fix_underflow_387:
mov oldcolor,ax ; check when past this - 10 next time
mov ax,maxit
sub ax,cx ; leave 'times through loop' in ax
; zero color fix
jnz zero_color_fix_387
inc ax ; if (ax == 0 ) ax = 1
zero_color_fix_387:
mov realcolor,ax ; save unadjusted realcolor
sub kbdcount,ax ; adjust the keyboard count
cmp outside,-1 ; iter ? (most common case)
je pop_stack_387
cmp outside,-2 ; outside <= -2 ?
jle special_outside_387 ; yes, go do special outside options
mov ax,outside ; use outside color
jmp short pop_stack_387
special_outside_387:
call near ptr special_outside
jmp short pop_stack_387
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; _287 version (closely resembles original code)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.286
.287
start_287: ; 287
cmp fractype,JULIAFP ; julia or mandelbrot set?
je short dojulia_287 ; julia set - go there
; Mandelbrot _287 initialization of stack
dec cx ; always requires at least 1 iteration
; the fpu stack is shown below
; st(0) ... st(7)
; b (already on stack)
fld inity ; Cy b
fld initx ; Cx Cy b
fld st(1) ; Cy Cx Cy b
fadd parmy ; Py+Cy Cx Cy b
fld1 ; 1 Py+Cy Cx Cy b
fld st(1) ; Py+Cy 1 Py+Cy Cx Cy b
fmul st,st ; (Py+Cy)^2 1 Py+Cy Cx Cy b
fld st(3) ; Cx (Py+Cy)^2 1 Py+Cy Cx Cy b
fadd parmx ; Px+Cx (Py+Cy)^2 1 Py+Cy Cx Cy b
fmul st(3),st ; Px+Cx (Py+Cy)^2 1 (Py+Cy)(Px+Cx) Cx Cy b
fmul st,st ; (Px+Cx)^2 (Py+Cy)^2 1 (Py+Cy)(Px+Cx) Cx Cy b
; which is the next x^2 y^2 1 xy Cx Cy b
jmp short top_of_cx_loop_287 ; branch around the julia switch
dojulia_287:
; Julia 287 initialization of stack
; note that init and parm are "reversed"
; b (already on stack)
fld parmy ; Cy b
fld parmx ; Cx Cy b
fld inity ; y Cx Cy b
fld1 ; 1 y Cx Cy b
fld st(1) ; y 1 y Cx Cy b
fmul st,st ; y^2 1 y Cx Cy b
fld initx ; x y^2 1 y Cx Cy b
fmul st(3),st ; x y^2 1 xy Cx Cy b
fmul st,st ; x^2 y^2 1 xy Cx Cy b
top_of_cx_loop_287: ; x^2 y^2 1 xy Cx Cy b
fsubr ; x^2-y^2 1 xy Cx Cy b
fadd st,st(3) ; x^2-y^2+Cx 1 xy Cx Cy b
fxch st(2) ; xy 1 x^2-y^2+Cx Cx Cy b
; FSCALE is faster than FADD for 287
fscale ; 2xy 1 x^2-y^2+Cx Cx Cy b
fadd st,st(4) ; 2xy+Cy 1 x^2-y^2+Cx Cx Cy b
; now same as the new
; y 1 x Cx Cy b
cmp outside,-2 ; real, imag, mult, or sum ?
jg no_save_new_xy_287 ; if not, then skip this
fld st(2) ; x y 1 x Cx Cy b
fstp newx ; y 1 x Cx Cy b
fst newy ; y 1 x Cx Cy b
no_save_new_xy_287:
cmp inside,-100 ; epsilon cross ?
jne end_epsilon_cross_287
call near ptr epsilon_cross ; y 1 x Cx Cy b
jcxz pop_stack_287 ; if cx=0, pop stack
end_epsilon_cross_287:
cmp cx,oldcolor ; if cx >= oldcolor
jae end_periodicity_check_287 ; don't check periodicity
call near ptr periodicity_check_287_387 ; y 1 x Cx Cy b
jcxz pop_stack_287 ; if cx=0, pop stack
end_periodicity_check_287:
cmp show_orbit,0 ; is show_orbit clear
je no_show_orbit_287 ; if so then skip
call near ptr show_orbit_xy ; y 1 x Cx Cy b
no_show_orbit_287:
; y 1 x Cx Cy b
fld st(2) ; x y 1 x Cx Cy b
fld st(1) ; y x y 1 x Cx Cy b
fmul st(4),st ; y x y 1 xy Cx Cy b
fmulp st(2),st ; x y^2 1 xy Cx Cy b
fmul st,st ; x^2 y^2 1 xy Cx Cy b
fld st ; x^2 x^2 y^2 1 xy Cx Cy b
fadd st,st(2) ; x^2+y^2 x^2 y^2 1 xy Cx Cy b
cmp potflag,0 ; check for potential
je no_potflag_287
fst magnitude ; if so, save magnitude
no_potflag_287:
fcomp st(7) ; x^2 y^2 1 xy Cx Cy b
fstsw ax
sahf
ja over_bailout_287
;less than or equal to bailout
loop top_of_cx_loop_287 ; x^2 y^2 1 xy Cx Cy b
; reached maxit, inside
mov oldcolor,0FFFFh ; check periodicity immediately next time
mov ax,maxit
sub kbdcount,ax ; adjust the keyboard count
mov realcolor,ax ; save unadjusted realcolor
mov ax,inside_color
cmp inside,-59 ; zmag ?
jne no_zmag_287
fadd st,st(1) ; x^2+y^2 y^2 1 xy Cx Cy b
fimul maxit ; maxit*|z^2| x^2 y^2 1 xy Cx Cy b
; When type casting floating point variables to integers in C, the decimal
; is truncated. When using FIST in asm, the value is rounded. The following
; line cause the positive value to be truncated.
fsub round_down_half
fist tmp_word ; tmp_word = |z^2|*maxit
fwait
mov ax,tmp_word
shr ax,1 ; |z^2|*maxit/2
inc ax ; |z^2|*maxit/2+1
no_zmag_287:
pop_stack_287:
fninit
mov color,ax
cmp orbit_ptr,0 ; any orbits to clear?
je calcmandfpasm_ret_287 ; nope.
call far ptr scrub_orbit ; clear out any old orbits
mov ax,color ; restore color
; speed not critical here in orbit land
calcmandfpasm_ret_287:
UNFRAME <si,di> ; pop stack frame
fwait ; just to make sure
ret
over_bailout_287: ; x^2 y^2 1 xy Cx Cy b
; outside
mov ax,cx
sub ax,10 ; 10 more next time before checking
jns no_fix_underflow_287
; if the number of iterations was within 10 of maxit, then subtracting
; 10 would underflow and cause periodicity checking to start right
; away. Catching a period doesn't occur as often in the pixels at
; the edge of the set anyway.
sub ax,ax ; don't check next time
no_fix_underflow_287:
mov oldcolor,ax ; check when past this - 10 next time
mov ax,maxit
sub ax,cx ; leave 'times through loop' in ax
; zero color fix
jnz zero_color_fix_287
inc ax ; if (ax == 0 ) ax = 1
zero_color_fix_287:
mov realcolor,ax ; save unadjusted realcolor
sub kbdcount,ax ; adjust the keyboard count
cmp outside,-1 ; iter ? (most common case)
je pop_stack_287
cmp outside,-2 ; outside <= -2 ?
jle special_outside_287 ; yes, go do special outside options
mov ax,outside ; use outside color
jmp short pop_stack_287
special_outside_287:
call near ptr special_outside
jmp short pop_stack_287
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; _87 code is just like 287 code except that it must use
; fstsw tmp_word
; fwait
; mov ax,tmp_word
; instead of
; fstsw ax
;
.8086
.8087
start_87:
; let emulation fall through to the 87 code here
; as it seems not emulate correctly on an 8088/86 otherwise
cmp fractype,JULIAFP ; julia or mandelbrot set?
je short dojulia_87 ; julia set - go there
; Mandelbrot _87 initialization of stack
dec cx ; always requires at least 1 iteration
; the fpu stack is shown below
; st(0) ... st(7)
; b (already on stack)
fld inity ; Cy b
fld initx ; Cx Cy b
fld st(1) ; Cy Cx Cy b
fadd parmy ; Py+Cy Cx Cy b
fld1 ; 1 Py+Cy Cx Cy b
fld st(1) ; Py+Cy 1 Py+Cy Cx Cy b
fmul st,st ; (Py+Cy)^2 1 Py+Cy Cx Cy b
fld st(3) ; Cx (Py+Cy)^2 1 Py+Cy Cx Cy b
fadd parmx ; Px+Cx (Py+Cy)^2 1 Py+Cy Cx Cy b
fmul st(3),st ; Px+Cx (Py+Cy)^2 1 (Py+Cy)(Px+Cx) Cx Cy b
fmul st,st ; (Px+Cx)^2 (Py+Cy)^2 1 (Py+Cy)(Px+Cx) Cx Cy b
; which is the next x^2 y^2 1 xy Cx Cy b
jmp short top_of_cx_loop_87 ; branch around the julia switch
dojulia_87:
; Julia 87 initialization of stack
; note that init and parm are "reversed"
; b (already on stack)
fld parmy ; Cy b
fld parmx ; Cx Cy b
fld inity ; y Cx Cy b
fld1 ; 1 y Cx Cy b
fld st(1) ; y 1 y Cx Cy b
fmul st,st ; y^2 1 y Cx Cy b
fld initx ; x y^2 1 y Cx Cy b
fmul st(3),st ; x y^2 1 xy Cx Cy b
fmul st,st ; x^2 y^2 1 xy Cx Cy b
top_of_cx_loop_87: ; x^2 y^2 1 xy Cx Cy b
fsubr ; x^2-y^2 1 xy Cx Cy b
fadd st,st(3) ; x^2-y^2+Cx 1 xy Cx Cy b
fxch st(2) ; xy 1 x^2-y^2+Cx Cx Cy b
; FSCALE is faster than FADD for 87
fscale ; 2xy 1 x^2-y^2+Cx Cx Cy b
fadd st,st(4) ; 2xy+Cy 1 x^2-y^2+Cx Cx Cy b
; now same as the new
; y 1 x Cx Cy b
cmp outside,-2 ; real, imag, mult, or sum ?
jg no_save_new_xy_87 ; if not, then skip this
fld st(2) ; x y 1 x Cx Cy b
fstp newx ; y 1 x Cx Cy b
fst newy ; y 1 x Cx Cy b
no_save_new_xy_87:
cmp inside,-100 ; epsilon cross ?
jne end_epsilon_cross_87
call near ptr epsilon_cross ; y 1 x Cx Cy b
test cx,cx ; if cx=0, pop stack
jnz end_epsilon_cross_87 ; replaces jcxz
jmp pop_stack_6_87 ; with a long jump
end_epsilon_cross_87:
cmp cx,oldcolor ; if cx >= oldcolor
jae no_periodicity_check_87 ; don't check periodicity
call near ptr periodicity_check_87 ; y 1 x Cx Cy b
jcxz pop_stack_6_87 ; if cx=0, pop stack
no_periodicity_check_87:
cmp show_orbit,0 ; is show_orbit clear
je no_show_orbit_87 ; if so then skip
call near ptr show_orbit_xy ; y 1 x Cx Cy b
no_show_orbit_87:
; y 1 x Cx Cy b
fld st(2) ; x y 1 x Cx Cy b
fld st(1) ; y x y 1 x Cx Cy b
fmul st(4),st ; y x y 1 xy Cx Cy b
fmulp st(2),st ; x y^2 1 xy Cx Cy b
fmul st,st ; x^2 y^2 1 xy Cx Cy b
fld st ; x^2 x^2 y^2 1 xy Cx Cy b
fadd st,st(2) ; x^2+y^2 x^2 y^2 1 xy Cx Cy b
cmp potflag,0 ; check for potential
je no_potflag_87
fst magnitude ; if so, save magnitude
no_potflag_87:
fcomp st(7) ; x^2 y^2 1 xy Cx Cy b
fstsw tmp_word
fwait
mov ax,tmp_word
sahf
ja over_bailout_87
;less than or equal to bailout
loop top_of_cx_loop_87 ; x^2 y^2 1 xy Cx Cy b
; reached maxit
mov oldcolor,0FFFFh ; check periodicity immediately next time
mov ax,maxit
sub kbdcount,ax ; adjust the keyboard count
mov realcolor,ax ; save unadjusted realcolor
mov ax,inside_color
cmp inside,-59 ; zmag ?
jne no_zmag_87
fadd st,st(1) ; x^2+y^2 y^2 1 xy Cx Cy b
fimul maxit ; maxit*|z^2| x^2 y^2 1 xy Cx Cy b
; When type casting floating point variables to integers in C, the decimal
; is truncated. When using FIST in asm, the value is rounded. The following
; line cause the positive value to be truncated.
fsub round_down_half
fist tmp_word ; tmp_word = |z^2|*maxit
fwait
mov ax,tmp_word
shr ax,1 ; |z^2|*maxit/2
inc ax ; |z^2|*maxit/2+1
no_zmag_87:
pop_stack_7_87:
; The idea here is just to clear the floating point stack. There was a
; problem using FNINIT with the emulation library. It didn't seem to
; properly clear the emulated stack, resulting in "stack overflow"
; messages. Therefore, if emulation is being used, then FSTP's are used
; instead.
cmp fpu,0 ; are we using emulation?
jne no_emulation ; if not, then jump
fstp st
; you could just jump over this next check, but its faster to just check again
pop_stack_6_87:
cmp fpu,0 ; are we using emulation?
jne no_emulation ; if not, then jump
fstp st
fstp st
fstp st
fstp st
fstp st
fstp st
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -