计算多项式值组件 32 位

calculate polynom value assembly 32 bit

我需要使用协处理器计算某个点的多项式,但我在实现方面几乎没有问题。当我在堆栈上加载电源时,我的程序没有显示任何内容并且寄存器表现非常奇怪,我使用 MASM 32 位汇编

示例:对于 P(X) = 1.2 + 3X + 4.9X^3 + 8.27X^4 我将有以下变量: p DD 1.2, 3, 0, 4.9, 8.27 ,n EQU ($-p)/4 -1 输出为某点的多项式

我的代码:

    .386

    .model flat, stdcall
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    ;include libraries
    includelib msvcrt.lib
    extern exit: proc
    extern printf: proc
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


    public start
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    .data

    ;p is my array of coefficients
    p DD 1.2, 3, 0, 4.9, 8.27
    n equ ($-p)/type p

    ;x is the value in which I calculate the polynomial
    x dq 3.0
    zero dq 0.0
    doi dq 2.0
    power dd 0
    valoare dd 0
    format DB "%lf", 0
    .code
    start:
        ;move in ecx the numbers of coefficients
        mov ecx,n

        ;edx is the index for my array
        xor edx,edx

        ;ebx is my array
        mov ebx,offset p

        FINIT ;INITIALIZARE COPROCESOR

        fld zero
        polinom:
        ;calculate x to power
        fld power
        FLD x   ;st[0]=x, st[1]=power
        FYL2X ; st[1]=st[1]*log2(st[0])
        FLD1 ; st[0]=1, st[1] = FYL2X 
        FXCH st(1)
        FSUB  ST(0), ST(1); st[0]=st[0]-st[1]
        F2XM1 
        FLD1
        FADD ST(0), ST(1)
        FLD doi
        FMUL

        ;multiply it by the corresponding coefficient
        FLD QWORD ptr [ebx+edx]
        FMUL
        add eax,4
        inc power
        ;the value coeff* x ^ y will be in st (0) and the partial value of the polynomial will be in st(5)
        ;example for 3x^2+2x+1, in st(0) will be 3x^2 and in st(5) will be 2x+1

        FXCH ST(1)
        FXCH ST(5)
        FADD
        loop polinom

        ;FST ST[0]  ;SAVE RESULT
        lea edi,valoare
        FST QWORD ptr[edi]

        ;SHOW RESULT
        push dword ptr [valoare+4]
        push dword ptr [valoare]
        push offset format
        call printf
        add esp, 12


        ;terminarea programului
        push 0
        call exit
    end start

您将系数数组定义为双字,即 32 位 float

p DD 1.2, 3, 0, 4.9, 8.27

但随后您使用 FLD QWORD ptr [ebx+edx] 从中加载一个 qword(64 位 double)。因此,您将两个相邻 float 的位模式视为一个 double.

此外,您每次都加载相同的 double,因为您在设置 ebx=pedx=0 后从未修改 ebxedx

使用fmul dword ptr [ebx] / add ebx, 4


您还将溢出 x87 寄存器堆栈,因此 fld 产生 NaN,当 st(0) .. st(7) 已经正在使用。你似乎从来没有弹出任何东西。参见 http://www.ray.masmcode.com/tutorial/index.html, and other links in https://whosebug.com/tags/x86/info

使用 fmulpfaddpfstp 在完成后弹出值。 或者 fmul 使用内存操作数而不是 fld + fmulp.

我不知道您的代码可能还有哪些其他错误,但您肯定有这些错误,而这些错误都解释了在调试时在 FP 寄存器中看到的主要怪异现象。


顺便说一句,您可以使用 sub esp,8 / fstp qword ptr [esp] 将结果作为 printf 的参数直接存储到调用堆栈中。你不需要 valoare.


或者更好的是,将 SSE2 mulsd 用于标量 FP 数学,而不是 x87,但显然您的作业要求您使用 x87 fyl2x 以非常低效的方式执行此操作,并且显然与x87.

如果你不是被迫以低效的方式去做,你可以只做 power *= x 来循环获得 x, x^2, x^3, ...。一次乘以一个幂而不是重做每个幂被称为强度降低优化,比如将 tmp = i*10 变成 tmp += 10.