NASM二次方程求根程序printf输出-nan问题排查
-nan 的问题 嘿,我来帮你捋捋这个输出 -nan 的问题——这种情况在写NASM浮点运算程序时挺常见的,大概率是下面几个环节出了问题:
输入与变量类型不匹配
你用了scanf读取a、b、c的值,但如果格式字符串和变量的存储类型对不上,读取的就是垃圾数据,后续计算自然全乱套。比如你要是把a定义成了双字整数(dd),却用%f来读取浮点数,那存进去的数值完全不是你输入的数,计算判别式的时候很容易出现负数或者非法值,最后就输出NaN。记得要对应好:单精度浮点数用dd搭配%f,双精度用dq搭配%lf。判别式计算出错
二次方程的核心是判别式b² - 4ac,如果这个值是负数,实数范围内开根号就会得到NaN;但更常见的是你计算判别式的逻辑写错了——比如搞反了减法顺序写成4ac - b²,或者乘法的寄存器/变量用错了,甚至a的值是0(这时候根本不是二次方程,计算1/(2a)会触发除以0),这些都会导致判别式无效,最终根变成NaN。浮点运算的寄存器/栈处理错误
用x87浮点栈的时候,栈的操作顺序错一步就全乱。比如你计算平方根时,栈顶的判别式是不是个负数?或者你在调用printf前,没有把计算好的根正确加载到对应的寄存器里?比如System V ABI下,用printf输出双精度浮点数得把值放到xmm0、xmm1这类寄存器里,要是你直接把内存里的垃圾数据传进去,输出肯定是NaN。变量存储结果时出错
就算你计算出了正确的根,要是没把结果正确存到root1和root2里也白搭。比如你用fstp指令把栈顶的浮点数存到变量时,是不是写错了变量的大小?比如root1是双精度(dq),你却用了fstp dword [root1],这样存进去的数值是截断的,自然也是无效的NaN。
举个简单的判别式计算正确示例参考下:
section .data four dq 4.0 a dq 0.0 b dq 0.0 c dq 0.0 ; 计算判别式 b² - 4ac fld qword [b] fmul qword [b] ; 栈顶: b² fld qword [a] fmul qword [c] ; 栈顶: a*c, 下一层: b² fmul qword [four] ; 栈顶: 4ac, 下一层: b² fsubp ; 栈顶: b² - 4ac
内容的提问来源于stack exchange,提问作者Arjun

