计算多项式值组件 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=p
和 edx=0
后从未修改 ebx
或 edx
。
使用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。
使用 fmulp
、faddp
和 fstp
在完成后弹出值。
或者 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
.
我需要使用协处理器计算某个点的多项式,但我在实现方面几乎没有问题。当我在堆栈上加载电源时,我的程序没有显示任何内容并且寄存器表现非常奇怪,我使用 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=p
和 edx=0
后从未修改 ebx
或 edx
。
使用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。
使用 fmulp
、faddp
和 fstp
在完成后弹出值。
或者 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
.