HLA二次方程求解汇编程序报错:值超出范围问题求助
问题分析与修复
你的代码出现"Value out of range"错误,且结果不符合预期,核心问题集中在栈操作、计算逻辑和变量使用三个方面:
1. 栈操作非法(直接触发范围错误)
计算b²时,你执行了fmul(st0, st1),但此时栈中仅通过fld(b)压入了一个元素,st1作为栈的第二个元素不存在。这个非法操作会破坏栈状态,生成无效浮点数,后续计算自然触发范围错误。
正确的b²计算应该是栈顶元素自乘:fmul st0, st0。
2. 判别式计算逻辑错误
二次方程判别式应为b² - 4ac,但你的代码逻辑完全偏离:
- 原代码在得到
a*c后执行fadd(st0, st1),实际是将a*c与之前压入的a相加,得到的不是2ac,更不是4ac; - 整个判别式计算步骤混乱,最终得到的数值完全错误。
3. 负根计算时的变量覆盖错误
你将sqrt(discriminant)存入root1,但计算第一个正根后,root1被覆盖为第一个根的值。计算负根时再读取root1,此时它已经不是根号判别式,导致负根计算完全错误。
修复后的完整代码
program solveQuadratic; #include( "stdlib.hhf" ); static a: real32; b: real32; c: real32; discriminant: real32; sqrtDisc: real32; // 单独存储根号判别式,避免被覆盖 root1: real32; root2: real32; begin solveQuadratic; // 输入a、b、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); // 计算判别式:b² - 4ac fld(b); fmul(st0, st0); // 计算b²,栈状态: [b²] fld(a); fmul(c); // 计算a*c,栈状态: [b², a*c] fld(4.0); fmul(st0, st1); // 计算4*a*c,栈状态: [b², 4ac] fsub(st1, st0); // 计算b² - 4ac,栈状态: [discriminant] fstp(discriminant); // 计算判别式的平方根 fld(discriminant); fsqrt(); fstp(sqrtDisc); // 存储到单独变量 // 计算正根:(-b + sqrt(disc)) / (2a) fld(b); fchs(); // 取-b,栈状态: [-b] fld(sqrtDisc); fadd(); // -b + sqrt(disc),栈状态: [-b+sqrtDisc] fld(a); fadd(st0, st0); // 计算2a,栈状态: [-b+sqrtDisc, 2a] fdiv(st1, st0); // 执行除法,栈状态: [root1] fstp(root1); // 计算负根:(-b - sqrt(disc)) / (2a) fld(b); fchs(); // 取-b,栈状态: [-b] fld(sqrtDisc); fsub(st0, st1); // -b - sqrt(disc),栈状态: [-b-sqrtDisc] fld(a); fadd(st0, st0); // 计算2a,栈状态: [-b-sqrtDisc, 2a] fdiv(st1, st0); // 执行除法,栈状态: [root2] fstp(root2); // 输出结果 stdout.put("x is ", root1:0:5, " and x is also ", root2:0:5, "\n"); end solveQuadratic;
修复说明
- 新增
sqrtDisc变量专门存储根号判别式,避免后续计算覆盖关键值; - 修正
b²的计算方式,消除栈下溢风险; - 重新梳理判别式计算逻辑,确保得到正确的
b²-4ac; - 使用带明确操作数的栈指令(如
fsub(st1, st0)),避免计算歧义。
输入a=2.1、b=3.1、c=-5.0时,运行结果将符合预期:x is 0.97238 and x is also -2.44857。
内容的提问来源于stack exchange,提问作者Tiburcio
相关产品推荐
相关产品推荐

