NASM协处理器 - 舍入工作非常糟糕

时间:2015-01-21 13:55:07

标签: assembly x86 nasm fpu

我写了一个计算子弹量的程序。对于半径为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

2 个答案:

答案 0 :(得分:2)

在这里,您尝试加载几个整数,就像它们是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
将有符号整数源操作数转换为双扩展精度浮点格式并推送   值到FPU寄存器堆栈上。源操作数可以是字,双字或四字整数。它已加载   没有舍入错误。保留源操作数的符号。

答案 1 :(得分:1)

除了Michael提到的问题之外,您似乎使用了半径 4 而不是radius 3

  

FMUL st0,st0 ;; st0-半径^ 2
  FMUL st0,st0 ;; st0- radius ^ 3 // r 2 * r 2 = r 4 ,而不是r 3