我需要使用协处理器在某一点计算多项式,但实际上我几乎没有问题。当我在堆栈上加载电源时,我的程序没有显示任何内容和寄存器表现得非常奇怪,我使用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
答案 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
因为您在设置ebx
和edx
之后永远不会修改ebx=p
或edx=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和其他链接。
完成后,使用fmulp
,faddp
和fstp
弹出值。
或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
。