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

📄 calmanfp.asm

📁 frasr200的win 版本源码(18.21),使用make文件,使用的vc版本较低,在我的环境下编译有问题! 很不错的分形程序代码!
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; calmanfp.asm - floating point version of the calcmand.asm file
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The following code was adapted from a little program called "Mandelbrot
; Sets by Wesley Loewer" which had a very limited distribution (my
; Algebra II class).  It didn't have any of the fancy integer math, but it
; did run floating point stuff pretty fast.
;
; The code was originally optimized for a 287 ('cuz that's what I've got)
; and for a large maxit (ie: use of generous overhead outside the loop to get
; slightly faster code inside the loop), which is generally the case when
; Fractint chooses to use floating point math.  This code also has the
; advantage that once the initial parameters are loaded into the fpu
; register, no transfers of fp values to/from memory are needed except to
; check periodicity and to show orbits and the like.  Thus, values keep all
; the significant digits of the full 10 byte real number format internal to
; the fpu.  Intermediate results are not rounded to the normal IEEE 8 byte
; format (double) at any time.
;
; The non fpu specific stuff, such as periodicity checking and orbits,
; was adapted from CALCFRAC.C and CALCMAND.ASM.
;
; This file must be assembled with floating point emulation turned on.  I
; suppose there could be some compiler differences in the emulation
; libraries, but this code has been successfully tested with the MSQC 2.51
; and MSC 5.1 emulation libraries.
;
;                                               Wes Loewer
;
; and now for some REAL fractal calculations...
; (get it, real, floating point..., never mind)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;                        required for compatibility if Turbo ASM
IFDEF ??version
MASM51
QUIRKS
ENDIF

.8086
.8087

.MODEL medium,c

; external functions
EXTRN   keypressed:FAR          ; this routine is in 'general.asm'
EXTRN   getakey:FAR             ; this routine is in 'general.asm'
EXTRN   plot_orbit:FAR          ; this routine is in 'fracsubr.c'
EXTRN   scrub_orbit:FAR         ; this routine is in 'fracsubr.c'

; external data
EXTRN init:WORD                 ; declared as type complex
EXTRN parm:WORD                 ; declared as type complex
EXTRN new:WORD                  ; declared as type complex
EXTRN maxit:WORD
EXTRN inside:WORD
EXTRN outside:WORD
EXTRN fpu:WORD                  ; fpu type: 87, 287, or 387
EXTRN rqlim:QWORD               ; bailout (I never did figure out
				;   what "rqlim" stands for. -Wes)
EXTRN color:WORD
EXTRN oldcolor:WORD
EXTRN realcolor:WORD
EXTRN periodicitycheck:WORD
EXTRN reset_periodicity:WORD
EXTRN closenuff:QWORD
EXTRN fractype:WORD             ; Mandelbrot or Julia
EXTRN kbdcount:WORD             ; keyboard counter
EXTRN dotmode:WORD
EXTRN show_orbit:WORD           ; "show-orbit" flag
EXTRN orbit_ptr:WORD            ; "orbit pointer" flag
EXTRN potflag:WORD              ; potential flag
EXTRN magnitude:QWORD           ; when using potential

JULIAFP  EQU 6                  ; from FRACTYPE.H
MANDELFP EQU 4
GREEN    EQU 2                  ; near y-axis
YELLOW   EQU 6                  ; near x-axis

initx    EQU <qword ptr init>   ; just to make life easier
inity    EQU <qword ptr init+8>
parmx    EQU <qword ptr parm>
parmy    EQU <qword ptr parm+8>
newx     EQU <qword ptr new>
newy     EQU <qword ptr new+8>

; Apparently, these might be needed for TC++ overlays. I don't know if
; these are really needed here since I am not familiar with TC++. -Wes
FRAME   MACRO regs
	push    bp
	mov     bp, sp
	IRP     reg, <regs>
	  push  reg
	  ENDM
	ENDM

UNFRAME MACRO regs
	IRP     reg, <regs>
	  pop reg
	  ENDM
	pop bp
	ENDM


.DATA
	align   2
savedx                  DQ  ?
savedy                  DQ  ?
orbit_real              DQ  ?
orbit_imag              DQ  ?
close                   DD  0.01
round_down_half         DD  0.5
tmp_word                DW  ?
inside_color            DW  ?
periodicity_color       DW  ?
;savedand               DW  ?
;savedincr              DW  ?
savedand                EQU     SI      ; this doesn't save much time or
savedincr               EQU     DI      ; space, but it doesn't hurt either

.CODE

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This routine is called once per image.
; Put things here that won't change from one pixel to the next.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PUBLIC calcmandfpasmstart
calcmandfpasmstart   PROC
					; not sure if needed here
	FRAME   <di,si>                 ; std frame, for TC++ overlays

	mov     ax,inside
	cmp     ax,0                    ; if (inside color == maxiter)
	jnl     non_neg_inside
	mov     ax,maxit                ;   use maxit as inside_color

non_neg_inside:                         ; else
	mov     inside_color,ax         ;   use inside as inside_color

	cmp     periodicitycheck,0      ; if periodicitycheck < 0
	jnl     non_neg_periodicitycheck
	mov     ax,7                    ;   use color 7 (default white)
non_neg_periodicitycheck:               ; else
	mov     periodicity_color,ax    ;   use inside_color still in ax
	mov     oldcolor,0              ; no periodicity checking on 1st pixel
	sub     ax,ax                   ; ax=0
	UNFRAME <si,di>                 ; pop stack frame
	ret
calcmandfpasmstart       ENDP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; floating point version of calcmandasm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PUBLIC calcmandfpasm
calcmandfpasm  PROC
	FRAME   <di,si>                 ; std frame, for TC++ overlays
; initialization stuff
	sub     ax,ax                   ; clear ax
	cmp     periodicitycheck,ax     ; periodicity checking?
	je      initoldcolor            ;  no, set oldcolor 0 to disable it
	cmp     inside,-59              ; zmag?
	je      initoldcolor            ;  set oldcolor to 0
	cmp     reset_periodicity,ax    ; periodicity reset?
	je      short initparms         ;  no, inherit oldcolor from prior invocation
	mov     ax,maxit                ; yup.  reset oldcolor to maxit-250
	sub     ax,250                  ; (avoids slowness at high maxits)
initoldcolor:
	mov     oldcolor,ax             ; reset oldcolor

initparms:
	sub     ax,ax                   ; clear ax
	mov     word ptr savedx,ax      ; savedx = 0.0
	mov     word ptr savedx+2,ax    ; needed since savedx is a QWORD
	mov     word ptr savedx+4,ax
	mov     word ptr savedx+6,ax
	mov     word ptr savedy,ax      ; savedy = 0.0
	mov     word ptr savedy+2,ax    ; needed since savedy is a QWORD
	mov     word ptr savedy+4,ax
	mov     word ptr savedy+6,ax
	inc     ax                      ; ax = 1
	mov     savedand,ax             ; savedand = 1
	mov     savedincr,ax            ; savedincr = 1
	mov     orbit_ptr,0             ; clear orbits
	dec     kbdcount                ; decrement the keyboard counter
	jns     short nokey             ;  skip keyboard test if still positive
	mov     kbdcount,10             ; stuff in a low kbd count
	cmp     show_orbit,0            ; are we showing orbits?
	jne     quickkbd                ;  yup.  leave it that way.
;this may need to be adjusted, I'm guessing at the "appropriate" values -Wes
	mov     kbdcount,5000           ; else, stuff an appropriate count val
	cmp     fpu,387                 ; ("appropriate" to the FPU)
	je      short kbddiskadj        ;     ...
	mov     kbdcount,3000           ;     ...
	cmp     fpu,287                 ;     ...
	je      short kbddiskadj        ;     ...
	mov     kbdcount,1000           ;     ...
	cmp     fpu,87                  ;     ...
	je      short kbddiskadj        ;     ...
	mov     kbdcount,500            ; emulation
kbddiskadj:
	cmp     dotmode,11              ; disk video?
	jne     quickkbd                ;  no, leave as is
	mov     cl,2                    ; yes, reduce count
	shr     kbdcount,cl             ;  ...

quickkbd:
	call    far ptr keypressed      ; has a key been pressed?
	cmp     ax,0                    ;  ...
	je      nokey                   ; nope.  proceed
	mov     kbdcount,0              ; make sure it goes negative again
	cmp     ax,'o'                  ; orbit toggle hit?
	je      orbitkey                ;  yup.  show orbits
	cmp     ax,'O'                  ; orbit toggle hit?
	jne     keyhit                  ;  nope.  normal key.
orbitkey:
	call    far ptr getakey         ; read the key for real
	mov     ax,1                    ; reset orbittoggle = 1 - orbittoggle
	sub     ax,show_orbit           ;  ...
	mov     show_orbit,ax           ;  ...
	jmp     short nokey             ; pretend no key was hit
keyhit:
	mov     ax,-1                   ; return with -1
	mov     color,ax                ; set color to -1
	UNFRAME <si,di>                 ; pop stack frame
	ret                             ; bail out!
nokey:

; OK, here's the heart of the floating point code.
; In my original program, the bailout value was loaded once per image and
; was left on the floating point stack after each pixel, and finally popped
; off the stack when the fractal was finished.  A lot of overhead for very
; little gain in my opinion, so I changed it so that it loads and unloads
; per pixel. -Wes

	fld     rqlim                   ; everything needs bailout first
	mov     cx,maxit                ; using cx as loop counter
	cmp     fpu,387                 ; jump to fpu specific code
	je      start_387               ; 387, slight efficiency tweeking
	cmp     fpu,287                 ;
	je      to_start_287            ; 287 (original version)
	jmp     start_87                ; else must be 87/emulation
to_start_287:
	jmp     start_287               ; needs a long jump here


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; _387 code is just like _287 code except that it uses an FADD instead
; of an FSCALE per orbit and also saves an FLD1 per pixel.
;
; You could use .386/.387 here, but it is not necessary.  The _387 floating
; point routines in this file do not have any 387 specific op-codes,
; only 387 specific optimizations.  (And plus my MS QuickAssembler does not
; recognize the .386/.387 directives.) -Wes
;
.286
.287

start_387:
	cmp     fractype,JULIAFP        ; julia or mandelbrot set?
	je      short dojulia_387       ; julia set - go there

; Mandelbrot _387 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
	fld     st                      ; Py+Cy Py+Cy Cx Cy b
	fmul    st,st                   ; (Py+Cy)^2 Py+Cy Cx Cy b
	fld     st(2)                   ; Cx (Py+Cy)^2 Py+Cy Cx Cy b
	fadd    parmx                   ; Px+Cx (Py+Cy)^2 Py+Cy Cx Cy b
	fmul    st(2),st                ; Px+Cx (Py+Cy)^2 (Py+Cy)(Px+Cx) Cx Cy b
	fmul    st,st                   ; (Px+Cx)^2 (Py+Cy)^2 (Py+Cy)(Px+Cx) Cx Cy b
	; which is the next               x^2 y^2 xy Cx Cy b
	jmp     short top_of_cx_loop_387 ; branch around the julia switch

dojulia_387:
					; Julia 387 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
	fld     st                      ; y y Cx Cy b
	fmul    st,st                   ; y^2 y Cx Cy b
	fld     initx                   ; x y^2 y Cx Cy b
	fmul    st(2),st                ; x y^2 xy Cx Cy b
	fmul    st,st                   ; x^2 y^2 xy Cx Cy b

top_of_cx_loop_387:                     ; x^2 y^2 xy Cx Cy b
	fsubr                           ; x^2-y^2 xy Cx Cy b
	fadd    st,st(2)                ; x^2-y^2+Cx xy Cx Cy b
	fxch                            ; xy x^2-y^2+Cx Cx Cy b
; FADD is faster than FSCALE for 387
	fadd    st,st                   ; 2xy x^2-y^2+Cx Cx Cy b
	fadd    st,st(3)                ; 2xy+Cy x^2-y^2+Cx Cx Cy b
					; now same as the new
					; y x Cx Cy b

	cmp     outside,-2              ; real, imag, mult, or sum ?
	jg      no_save_new_xy_387      ; if not, then skip this
	fld     st(1)                   ; x y x Cx Cy b
	fstp    newx                    ; y x Cx Cy b
	fst     newy                    ; y x Cx Cy b
no_save_new_xy_387:

	cmp     inside,-100                     ; epsilon cross ?
	jne     end_epsilon_cross_387
	call    near ptr epsilon_cross          ; y x Cx Cy b
	jcxz    pop_stack_387                   ; if cx=0, pop stack
end_epsilon_cross_387:

	cmp     cx,oldcolor                     ; if cx >= oldcolor
	jae     end_periodicity_check_387       ; don't check periodicity
	call    near ptr periodicity_check_287_387  ; y x Cx Cy b
	jcxz    pop_stack_387                   ; if cx=0, pop stack
end_periodicity_check_387:

	cmp     show_orbit,0            ; is show_orbit clear
	je      no_show_orbit_387       ; if so then skip
	call    near ptr show_orbit_xy  ; y x Cx Cy b
no_show_orbit_387:

					; y x Cx Cy b
	fld     st(1)                   ; x y x Cx Cy b
	fld     st(1)                   ; y x y x Cx Cy b
	fmul    st(3),st                ; y x y xy Cx Cy b
	fmulp   st(2),st                ; x y^2 xy Cx Cy b
	fmul    st,st                   ; x^2 y^2 xy Cx Cy b
	fld     st                      ; x^2 x^2 y^2 xy Cx Cy b
	fadd    st,st(2)                ; x^2+y^2 x^2 y^2 xy Cx Cy b

	cmp     potflag,0               ; check for potential
	je      no_potflag_387
	fst     magnitude               ; if so, save magnitude
no_potflag_387:

	fcomp   st(6)                   ; x^2 y^2 xy Cx Cy b
	fstsw   ax
	sahf
	ja      over_bailout_387

;less than or equal to bailout
	loop    top_of_cx_loop_387      ; x^2 y^2 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_387
	fadd    st,st(1)                ; x^2+y^2 y^2 xy Cx Cy b
	fimul   maxit                   ; maxit*|z^2| x^2 y^2 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_387:

pop_stack_387:

⌨️ 快捷键说明

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