我有一些 c 例程
int n_mandelbrot(double c_im, double c_re, int N_ITER)
{
static double re, im, re2, im2;
static int n;
im2=im=0;
re2=re=0;
for(n=0; n<N_ITER; n++)
{
im = (re+re)*im + c_im;
re = re2 - im2 + c_re;
im2=im*im;
re2=re*re;
if ( re2 + im2 > 4.0 ) break;
}
return n;
}
想将它重写为程序集,我设法写了
n_mandelbrot_fpu_double: ;; (double cre, double cim, int N_ITER)
mov edx, dword [esp+20] ;; N_ITER
mov ecx, 0
fld qword [esp+4+0] ;; cre
fld qword [esp+12+0] ;; cim
fld1
fadd st0, st0
fadd st0, st0 ;; 4.0
fldz ;; re = 0
fldz ;; im = 0
fldz ;; re2 = 0
fldz ;; im2 = 0
mlloopp:
;; here
;; im = (re+re)*im + c_im;
;; re = re2 - im2 + c_re;
;; im2=im*im;
;; re2=re*re;
;; if ( re2 + im2 > 4.0 ) break;
;; STACK: cre cim 4.0 re im re2 im2
fld st3
fadd st0, st0
fmul st3
fadd st6
fxch st3
fstp st0
fld st1
fsub st1
fadd st7
fxch st4
fstp st0
fld st2
fmul st0, st0
fxch st1
fstp st0
fld st3
fmul st0, st0
fxch st2
fstp st0
fld st0
fadd st2
fcomp st5
fnstsw ax
sahf
ja mloopout
inc ecx
cmp ecx,edx
jb mlloopp
mloopout:
fstp st0
fstp st0
fstp st0
fstp st0
fstp st0
fstp st0
fstp st0
mov eax, ecx
ret
c 例程使我的程序循环运行 150 毫秒,然后它下降到 105 毫秒,所以这更快(尽管在内部循环中计算两个像素的展开的 c 例程只需要 115,我不知道为什么以及如何展开它在 asm 中)
我认为这个 asm 代码效率不高,我尝试将所有变量加载到 fpu 堆栈上(在循环之前,我将 7 个 double 加载到它:cre cim 4.0 re im re2 im2 然后有一个将它加载到堆栈顶部的 tol 交换并用 fstp 弹出,所以我认为它可能效率不高
有人可以帮助改进吗(内部循环之外的值并不重要,但内部循环中的代码在这里很重要