⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 calmanfp.asm

📁 frasr200的win 版本源码(18.21),使用make文件,使用的vc版本较低,在我的环境下编译有问题! 很不错的分形程序代码!
💻 ASM
📖 第 1 页 / 共 3 页
字号:
	jmp     short end_pop_stack_87
no_emulation:                           ; if no emulation, then
	fninit                          ;   use the faster FNINIT
end_pop_stack_87:

	mov     color,ax

	cmp     orbit_ptr,0             ; any orbits to clear?
	je      calcmandfpasm_ret_87    ; 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_87:
	UNFRAME <si,di>                 ; pop stack frame
	fwait				; just to make sure
	ret

over_bailout_87:                        ; 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_87
; 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_87:
	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_87
	inc     ax                      ; if (ax == 0 ) ax = 1
zero_color_fix_87:
	mov     realcolor,ax            ; save unadjusted realcolor
	sub     kbdcount,ax             ; adjust the keyboard count

	cmp     outside,-1              ; iter ? (most common case)
	je      pop_stack_7_87
	cmp     outside,-2		; outside <= -2 ?
	jle     special_outside_87      ; yes, go do special outside options
	mov     ax,outside              ; use outside color
	jmp     short pop_stack_7_87
special_outside_87:
	call    near ptr special_outside
	jmp     short pop_stack_7_87

calcmandfpasm  ENDP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Since periodicity checking is used most of the time, I decided to
; separate the periodicity_check routines into a _287_387 version
; and an _87 version to achieve a slight increase in speed.  The
; epsilon_cross, show_orbit_xy, and special_outside routines are less
; frequently used and therefore have been implemented as single routines
; usable by the 8087 and up. -Wes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.286
.287
periodicity_check_287_387   PROC    NEAR
; REMEMBER, the cx counter is counting BACKWARDS from maxit to 0
					; fpu stack is either
					; y x Cx Cy b (387)
					; y 1 x Cx Cy b (287/emul)
	cmp     fpu,387
	jb      pc_load_x
	fld     st(1)                   ; if 387
	jmp     short pc_end_load_x
pc_load_x:
	fld     st(2)                   ; if 287/emul
pc_end_load_x:
					; x y ...
	test    cx,savedand             ; save on 0, check on anything else
	jnz     do_check_287_387        ;  time to save a new "old" value

; save last value                       ; fpu stack is
	fstp    savedx                  ; x y ...
	fst     savedy                  ; y ...
	dec     savedincr               ; time to lengthen the periodicity?
	jnz     per_check_287_387_ret   ; if not 0, then skip
	shl     savedand,1              ; savedand = (savedand << 1) + 1
	inc     savedand                ; for longer periodicity
	mov     savedincr,4             ; and restart counter
	ret                             ; y ...

do_check_287_387:                       ; fpu stack is
					; x y ...
	fsub    savedx                  ; x-savedx y ...
	fabs                            ; |x-savedx| y ...
	fcomp   closenuff               ; y ...
	fstsw   ax
	sahf
	ja      per_check_287_387_ret
	fld     st                      ; y y ...
	fsub    savedy                  ; y-savedy y ...
	fabs                            ; |y-savedy| y ...
	fcomp   closenuff               ; y ...
	fstsw   ax
	sahf
	ja      per_check_287_387_ret
					; caught a cycle!!!
	mov     oldcolor,0FFFFh         ; check periodicity immediately next time

	mov     ax,maxit
	mov     realcolor,ax            ; save unadjusted realcolor as maxit
	sub     ax,cx                   ; subtract half c
	sub     kbdcount,ax             ; adjust the keyboard count
	mov     ax,periodicity_color    ; set color
	sub     cx,cx                   ; flag to exit cx loop immediately

per_check_287_387_ret:
	ret
periodicity_check_287_387   ENDP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.8086
.8087
periodicity_check_87    PROC    NEAR
; just like periodicity_check_287_387 except for the use of
;       fstsw tmp_word
; instead of
;       fstsw ax

; REMEMBER, the cx counter is counting BACKWARDS from maxit to 0
	fld     st(2)                   ; x y ...
	test    cx,savedand             ; save on 0, check on anything else
	jnz     do_check_87             ;  time to save a new "old" value

; save last value                       ; fpu stack is
					; x y ...
	fstp    savedx                  ; y ...
	fst     savedy                  ; y ...
	dec     savedincr               ; time to lengthen the periodicity?
	jnz     per_check_87_ret        ; if not 0, then skip
	shl     savedand,1              ; savedand = (savedand << 1) + 1
	inc     savedand                ; for longer periodicity
	mov     savedincr,4             ; and restart counter
	ret                             ; y ...

do_check_87:                            ; fpu stack is
					; x y ...
	fsub    savedx                  ; x-savedx y ...
	fabs                            ; |x-savedx| y ...
	fcomp   closenuff               ; y ...
	fstsw   tmp_word
	fwait
	mov     ax,tmp_word
	sahf
	ja      per_check_87_ret
	fld     st                      ; y y ...
	fsub    savedy                  ; y-savedy y ...
	fabs                            ; |y-savedy| y ...
	fcomp   closenuff               ; y ...
	fstsw   tmp_word
	fwait
	mov     ax,tmp_word
	sahf
	ja      per_check_87_ret
					; caught a cycle!!!
	mov     oldcolor,0FFFFh         ; check periodicity immediately next time

	mov     ax,maxit
	mov     realcolor,ax            ; save unadjusted realcolor as maxit
	sub     ax,cx
	sub     kbdcount,ax             ; adjust the keyboard count

	mov     ax,periodicity_color    ; set color
	sub     cx,cx                   ; flag to exit cx loop immediately

per_check_87_ret:
	ret
periodicity_check_87       ENDP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.8086
.8087
epsilon_cross   PROC    NEAR
					; fpu stack is either
					; y x Cx Cy b (387)
					; y 1 x Cx Cy b (287/87/emul)
	cmp     fpu,387
	jb      ec_load_x
	fld     st(1)                   ; if 387
	jmp     short ec_end_load_x
ec_load_x:
	fld     st(2)                   ; if 287/87/emul
ec_end_load_x:                          ; x y ...

	fabs                            ; |x| y 1 x Cx Cy b
	fcomp   close                   ; y 1 x Cx Cy b
	fstsw   tmp_word
	fwait
	mov     ax,tmp_word
	sahf
	jae     no_x_epsilon_cross
	mov     ax,maxit                ; x is close to y axis
	sub     ax,cx                   ; leave 'times through loop' in ax
; zero color fix
	jnz     zero_color_fix_1
	inc     ax                      ; if (ax == 0 ) ax = 1
zero_color_fix_1:
	mov     realcolor,ax            ; save unadjusted realcolor
	sub     kbdcount,ax             ; adjust the keyboard count
	mov     ax,GREEN                ;
	sub     cx,cx                   ; flag to end loop
	mov     oldcolor,cx             ; don't check next time
	ret                             ; return
no_x_epsilon_cross:                     ; y 1 x Cx Cy b
	fld     st                      ; y y 1 x Cx Cy b
	fabs                            ; |y| y 1 x Cx Cy b
	fcomp   close                   ; y 1 x Cx Cy b
	fstsw   tmp_word
	fwait
	mov     ax,tmp_word
	sahf
	jae     no_y_epsilon_cross
	mov     ax,maxit                ; y is close to x axis
	sub     ax,cx                   ; leave 'times through loop' in ax
; zero color fix
	jnz     zero_color_fix_2
	inc     ax                      ; if (ax == 0 ) ax = 1
zero_color_fix_2:
	mov     realcolor,ax            ; save unadjusted realcolor
	sub     kbdcount,ax             ; adjust the keyboard count
	mov     ax,YELLOW
	sub     cx,cx                   ; flag to end loop
	mov     oldcolor,cx             ; don't check next time
	ret                             ; return
no_y_epsilon_cross:
	ret
epsilon_cross   ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.8086
.8087
show_orbit_xy   PROC NEAR USES cx si di
	local	tmp_ten_byte_0:tbyte	; stupid klooge for MASM 5.1 LOCAL bug
	local	tmp_ten_byte_1:tbyte
	local	tmp_ten_byte_2:tbyte
	local	tmp_ten_byte_3:tbyte
	local	tmp_ten_byte_4:tbyte
	local	tmp_ten_byte_5:tbyte
	local	tmp_ten_byte_6:tbyte
; USES is needed because in all likelyhood, plot_orbit surely
; uses these registers.  It's ok to have to push/pop's here in the
; orbits as speed is not crucial when showing orbits.

					; fpu stack is either
					; y x Cx Cy b (387)
					; y 1 x Cx Cy b (287/87/emul)
	cmp     fpu,387
	jb      so_load_x
	fld     st(1)                   ; if 387
	jmp     short so_end_load_x
so_load_x:
	fld     st(2)                   ; if 287/87/emul
so_end_load_x:
					; x y ...
					; and needs to returned as
					; y ...

	fstp    orbit_real              ; y ...
	fst     orbit_imag              ; y ...
	mov     ax,-1                   ; color for plot orbit
	push    ax                      ;       ...
; since the number fpu registers that plot_orbit() preserves is compiler
; dependant, it's best to fstp the entire stack into 10 byte memories
; and fld them back after plot_orbit() returns.
	fstp    tmp_ten_byte_1          ; store the stack in 80 bit form
	fstp    tmp_ten_byte_2
	fstp    tmp_ten_byte_3
	fstp    tmp_ten_byte_4
	fstp    tmp_ten_byte_5
	cmp     fpu,287                 ; with 287/87/emul the stack is 6 high
	jg      no_store_6              ; with 387 it is only 5 high
	fstp    tmp_ten_byte_6
no_store_6:
	fwait                           ; just to be safe
	push    word ptr orbit_imag+6   ; co-ordinates for plot orbit
	push    word ptr orbit_imag+4   ;       ...
	push    word ptr orbit_imag+2   ;       ...
	push    word ptr orbit_imag     ;       ...
	push    word ptr orbit_real+6   ; co-ordinates for plot orbit
	push    word ptr orbit_real+4   ;       ...
	push    word ptr orbit_real+2   ;       ...
	push    word ptr orbit_real     ;       ...
	call    far ptr plot_orbit      ; display the orbit
	add     sp,9*2                  ; clear out the parameters

        cmp     fpu,287
        jg      no_load_6
        fld     tmp_ten_byte_6          ; load them back in reverse order
no_load_6:
	fld	tmp_ten_byte_5
	fld	tmp_ten_byte_4
	fld	tmp_ten_byte_3
	fld	tmp_ten_byte_2
	fld	tmp_ten_byte_1
	fwait                           ; just to be safe
	ret
show_orbit_xy   ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.8086
.8087
special_outside PROC NEAR
; When type casting floating point variables to integers in C, the decimal
; is truncated.  When using FIST in asm, the value is rounded.  Using
; "FSUB round_down_half" causes the values to be rounded down.

	cmp     outside,-2
	jne     not_real
	fld     newx
	fsub    round_down_half
	fistp   tmp_word
	add     ax,7
	fwait
	add     ax,tmp_word
	jmp     short check_color
not_real:
	cmp     outside,-3
	jne     not_imag
	fld     newy
	fsub    round_down_half
	fistp   tmp_word
	add     ax,7
	fwait
	add     ax,tmp_word
	jmp     short check_color
not_imag:
	cmp     outside,-4
	jne     not_mult
	fld     newy
	ftst                    ; check to see if newy == 0
	fstsw   tmp_word
	push    ax              ; save current ax value
	fwait
	mov     ax,tmp_word
	sahf
	pop     ax              ; retrieve ax (does not affect flags)
	jne     non_zero_y
	ret                     ; if y==0, return with normal ax
non_zero_y:
	fdivr   newx            ; newx/newy
	mov     tmp_word,ax
	fimul   tmp_word        ; ax*newx/newy  (Use FIMUL instead of MUL
	fsub    round_down_half ; to make it match the C code.)
	fistp   tmp_word
	fwait
	mov     ax,tmp_word
	jmp     short check_color
not_mult:
	cmp     outside,-5      ; currently always equal, but put here
	jne     not_sum         ; for future outside types
	fld     newx
	fadd    newy            ; newx+newy
	fsub    round_down_half
	fistp   tmp_word
	fwait
	add     ax,tmp_word

not_sum:
check_color:
	cmp     ax,maxit                ; use UNSIGNED comparison
	jbe     special_outside_ret     ; color < 0 || color > maxit
	sub     ax,ax                   ; ax = 0
special_outside_ret:
	ret
special_outside ENDP

.8086   ;just to be sure
.8087
END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -