我在二次公式组装程序 (HLA) 上找不到错误

问题描述 投票:0回答:1

当我尝试执行代码时,出现错误,告诉我“值超出范围”。

program solveQuadratic;
#include( "stdlib.hhf" );

static
  a: real32;
  b: real32;
  c: real32;
  discriminant: real32;
  root1: real32;
  root2: real32;

begin solveQuadratic;

  // Prompt and read values for a, b, and c
  stdout.put("Gimme a value for a: ");
  stdin.get(a);
  stdout.put("Gimme a value for b: ");
  stdin.get(b);
  stdout.put("Gimme a value for c: ");
  stdin.get(c);

  // Calculate the discriminant
  fld(b);
  fmul(st0, st1);      // b^2
  fld(a);
  fld(c);
  fmul(st0, st1);      // a * c
  fadd(st0, st1);      // 2ac
  fsub();              // b^2 - 4ac
  fstp(discriminant);

    // Compute the roots
    fld(discriminant);
    fsqrt();
    fstp(root1);       // store sqrt(discriminant) in root1

    // Calculate the positive root
    fld(b);
    fchs();            // -b
    fld(root1);
    fadd();            // -b + sqrt(discriminant)
    fld(a);
    fadd(st0, st0);    // 2a
    fdiv();            // (-b + sqrt(discriminant)) / (2a)
    fstp(root1);

    // Calculate the negative root
    fld(b);
    fchs();            // -b
    fld(root1);
    fsub();            // -b - sqrt(discriminant)
    fld(a);
    fadd(st0, st0);    // 2a
    fdiv();            // (-b - sqrt(discriminant)) / (2a)
    fstp(root2);

    // Output the roots
    stdout.put("x is ", root1:0:5, " and x is also ", root2:0:5, "\n");

end solveQuadratic;

我期待这个输出

给我一个值:2.1
给我一个 b 值:3.1
给我一个 c 值:-5.0
x 是 -2.44857 并且 x 也是 0.97238

但我得到的只是一个转换错误,我不知道为什么。

assembly x86 x87 hla
1个回答
0
投票

您的 FPU 操作存在缺陷。

您已将

sqrt(discriminant)
存储在 root1 中,但这样做使负根的计算变得不可能!

fld(b);
fmul(st0, st1);      // b^2

如果您没有加载该寄存器,则无法乘以 ST1!

fmul(b)
就可以了。

fld(a);
fld(c);
fmul(st0, st1);      // a * c
fadd(st0, st1);      // 2ac

这个乘法没问题,但加法确实如此

a * c + a
,因为 ST1 仍然保留 a 值,您也应该删除该值,否则 fpu 堆栈在某些时候会溢出。另外,当你应该去
2ac
时,为什么你却去
4ac

使用
faddp()
fsubp
fdivp
丢弃不再需要的值。

这非常重要,因为 fpu 堆栈只有 8 个寄存器可供使用!

fld(b);
fmul(b);            // b^2
fld(a);
fmul(c);            // a * c
fadd(st0, st0);     // 2ac
fadd(st0, st0);     // 4ac
fsubp();            // b^2 - 4ac
// fstp(discriminant);

// fld(discriminant);
fsqrt();
fst(root2);        // store sqrt(discriminant) in root2
fstp(root1);       // store sqrt(discriminant) in root1

// Calculate the positive root
fld(b);
fchs();            // -b
fld(root1);
faddp();           // -b + sqrt(discriminant)
fld(a);
fadd(st0, st0);    // 2a
fdivp();           // (-b + sqrt(discriminant)) / (2a)
fstp(root1);

// Calculate the negative root
fld(b);
fchs();            // -b
fld(root2);
fsubp();           // -b - sqrt(discriminant)
fld(a);
fadd(st0, st0);    // 2a
fdivp();           // (-b - sqrt(discriminant)) / (2a)
fstp(root2);

更短。

您可以更换:

fld(root1);
faddp();           // -b + sqrt(discriminant)

fadd(root1);

此外,您还可以替换:

fld(root2);
fsubp();           // -b - sqrt(discriminant)

fsub(root2);
© www.soinside.com 2019 - 2024. All rights reserved.