NASM 协处理器 - 舍入效果不佳

NASM coprocessor - rounding works badly

我写了一个计算子弹体积的程序。对于 1.2 的半径,我应该得到 7(7.23 向下舍入)。相反,我得到 9.

我逐行查看了程序,但看不出哪里出错了。我的代码如下所示:

section .text
global _start

_start:

FINIT

FLD dword [radius] ;; st0 - radius
FLDPI ;; st0 - pi, st1 - radius

xor eax,eax
mov eax,4
mov [operator],eax
FLD dword [operator] ;; st0 - operator, st1 - pi, st2 - radius

mov eax,3
mov [operator2],eax
FLD dword [operator2] ;; st0- operator2, st1- operator, st2- pi, st3- radius

FXCH st1 ;; st0- operator, st1- operator2, st2- pi, st3- radius
FDIV st0,st1 ;; st0- operator/operator2 = 4/3, st1- operator2,  st2- pi, st3- promien
FXCH st3 ;; radius, operator2, pi, operator/operator2
FMUL st0,st0 ;; st0- radius^2
FMUL st0,st0 ;; st0- radius^3
FMUL st0,st3 ;; st0- radius^3 * 4/3
FMUL st0,st2 ;; st0- radius^3 * 4/3 * pi

FISTP dword [result]

xor eax,eax
mov eax,[result]
add eax,48
mov [result],eax

mov eax,4
mov ebx,1
mov ecx,result
mov edx,4
int 80h

mov eax,1
int 80h

section .data
radius dd      1.2
operator dd     0
operator2 dd    0
result   dd      0

您在这里尝试加载几个整数,就好像它们是 32 位浮点值一样:

mov eax,4
mov [operator],eax
FLD dword [operator] ;; st0 - operator, st1 - pi, st2 - promien

mov eax,3
mov [operator2],eax
FLD dword [operator2] ;; st0- operator2, st1- operator, st2- pi, st3- promien

要加载 32 位整数并将其转换为浮点数,您应该使用 FILD dword [foo]

来自英特尔软件开发人员手册:

FILD—Load Integer
Converts the signed-integer source operand into double extended-precision floating-point format and pushes the value onto the FPU register stack. The source operand can be a word, doubleword, or quadword integer. It is loaded without rounding errors. The sign of the source operand is preserved.

除了 Michael 提到的问题之外,您似乎使用的是 radius4 而不是 radius3

FMUL st0,st0 ;; st0- radius^2
FMUL st0,st0 ;; st0- radius^3 // r2 * r2 = r4, not r3