【发布时间】:2020-11-19 06:36:18
【问题描述】:
我正在开发一个求解二次方程根的程序。我能够在 root1 子例程中获得第一个根。但是,当我尝试求解 root2 中的第二个根时,二次公式的“/2a”部分一直产生 NaN。
代码如下:
INCLUDE Irvine32.inc
INCLUDE macros.inc
.data
a real8 ?
b real8 ?
cc real8 ?
a2 real8 ?
b2 real8 ?
cc2 real8 ?
two real8 2.0
four real8 4.0
two2 real8 2.0
four2 real8 4.0
ten real8 1000.0
num real8 10.0
.code
main PROC
finit
mWrite "Enter coefficient (a): "
call ReadFloat
fst a
fstp a2
mWrite "Enter coefficient (b): "
call ReadFloat
fst b
fstp b2
mWrite "Enter coefficient (c): "
call ReadFloat
fst cc
fstp cc2
mWrite "Roots: "
call root1
call Crlf
call root2
;call showfpustack
exit
main ENDP
root1 PROC
; b^2
fld b
fmul b
fchs ; flip sign
fst b
; 4 * a * c
fld four
fmul a
fmul cc
fchs
fsub b
fsqrt
fst four
fld b
fchs
fsqrt
fchs
fadd four
fst b
fld two
fmul a
fst two
fld b
fdiv two
call WriteFloat
call showfpustack
ret
root1 endp
root2 PROC
fld b2
fmul b2
fchs
fst b2
fld four2
fmul a2
fmul cc2
fchs
fsub b2
fsqrt
fst four2
fld b2
fchs
fsqrt
fchs
fsub four2
fst b2
call Crlf
call WriteFloat
fld two2
fmul a2
fst two2
fld b2
fdiv two2
call showfpustack
ret
root2 endp
end main
我能够验证之前的计算结果。这只是我遇到问题的部分。
【问题讨论】:
-
而不是
fmul2,你可以fadd st0将当前栈顶值加倍。但是无论如何,当您单步执行调试器时,NaN 会出现在哪里?你在取负数的 sqrt 吗?或者你是否用所有那些fld堆栈推送而没有弹出堆栈溢出?另外,你为什么要用 fsqrt 结果覆盖你的常量4.0?这很奇怪,意味着你不能再次调用你的函数。 -
我仍然得到 NaN。调用 showFPUstack 时缺少 st(0)。
-
但不是来自
WriteFloat?WriteFloat是否修改 FP 寄存器?使用调试器来查找,而不是浪费时间只调用打印函数。或者你的意思是root2,它只使用showfpustack? -
当我将 a2 加载到 st(0) 上时,它变为 1#IND 。知道为什么会这样吗?
-
您还可以更好地利用 x87 堆栈,而不是一直存储到内存并重新加载,以及像
fdivr b2这样的东西来执行st0 = b2 / st0而不是存储/加载/fdiv。或者你可以fld b2/fxchg/fdivp或其他东西,但这显然更糟。就像我说的,你不需要覆盖你的常量,这会让任何阅读你代码的人感到困惑。
标签: assembly masm irvine32 x87