计算多项值汇编32位

时间:2018-05-06 14:43:50

标签: assembly masm 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

1 个答案:

答案 0 :(得分:2)

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

p DD 1.2, 3, 0, 4.9, 8.27

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

此外,您每次都加载相同的double因为您在设置ebxedx之后永远不会修改ebx=pedx=0

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

fld .. st(0)已被使用时,您还将溢出x87寄存器堆栈,以便st(7)生成NaN 。你似乎没有弹出任何东西。请参阅http://www.ray.masmcode.com/tutorial/index.html中的https://stackoverflow.com/tags/x86/info和其他链接。

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

我不知道你的代码可能有什么其他错误,但你肯定有这些错误,并且这些错误都解释了在调试时看到FP寄存器中的主要怪异。

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

或者更好的是,使用SSE2 mulsd进行标量FP数学,而不是x87,但显然你的任务要求你使用x87 fyl2x以非常低效的方式执行此操作,显然使用x87。

如果您没有被迫以低效的方式执行此操作,您可以power *= x在循环中获取x,x ^ 2,x ^ 3,....建立一个一次乘法而不是重新分配每个幂的功能称为强度降低优化,例如将tmp = i*10转换为tmp += 10