汇编质数打印程序无输出问题排查及代码修改建议
问题排查与修改方案
核心问题分析
1. 质数打印循环的退出逻辑完全失效
你在showPrimes中用ECX同时承担了每行打印计数和总质数计数两个角色,导致循环无法终止:
- 当打印满10个质数后,
ECX被重置为0,此时判断CMP ECX, EBX(用户输入的质数数量≥1)永远成立,程序陷入无限循环。 - 退出判断的位置错误,应该在每次找到质数并更新总计数后检查是否达到用户要求,而非换行重置行计数之后。
2. isPrime函数的逻辑错误
DIV指令会破坏原始的EAX值(待检查的数),导致后续判断出错。比如检查2时,执行DIV 2后EAX变为1,会误判为非质数。- 质数边界判断错误:当除数等于待检查数时(如2÷2),余数为0,但这是质数的合法情况,不能直接判定为非质数。
修改方案
1. 修复showPrimes的循环逻辑
新增寄存器EDI记录已找到的总质数数量,ECX仅用于每行计数,调整退出判断的位置:
showPrimes PROC MOV EBX, userInput ; EBX = 用户要求的质数数量 MOV ECX, 0 ; ECX = 每行已打印的质数计数 MOV EDI, 0 ; EDI = 已找到的总质数计数 MOV EAX, 2 ; 从第一个质数2开始检查 printPrime: PUSH EAX ; 保存当前要检查的数 CALL isPrime POP EAX ; 恢复原数 CMP EAX, 1 ; 判断是否为质数 JNE notPrime ; 非质数则跳过 ; 打印质数 CALL WriteDec MOV EDX, OFFSET spacer call WriteString INC ECX ; 行计数+1 INC EDI ; 总计数+1 ; 检查是否达到用户要求的数量,达到则退出 CMP EDI, EBX JE exitShowPrimes ; 每行满10个则换行并重置行计数 CMP ECX, 10 JNE nextPrime CALL CrLf MOV ECX, 0 nextPrime: INC EAX JMP printPrime notPrime: INC EAX JMP printPrime exitShowPrimes: CALL CrLf ; 最后一行换行,格式更整齐 ret showPrimes ENDP
2. 修复isPrime函数的逻辑
保存原始待检查数,修正边界判断逻辑,同时优化检查效率:
isPrime PROC ; 处理边界情况:2是质数 CMP EAX, 2 JE prime ; 小于2的数不是质数 CMP EAX, 1 JLE notPrime ; 偶数(除了2)不是质数 TEST EAX, 1 JE notPrime MOV EBX, EAX ; EBX保存原始要检查的数 MOV ECX, 3 ; 从3开始检查奇数除数,提高效率 checkDivisor: MOV EDX, 0 MOV EAX, EBX DIV ECX ; 计算余数 CMP EDX, 0 ; 余数为0则非质数 JE notPrime INC ECX ; 只检查奇数,可优化为ADD ECX,2进一步提升效率 CMP ECX, EBX JGE prime ; 除数达到或超过原数,说明是质数 JMP checkDivisor notPrime: MOV EAX, 0 ret prime: MOV EAX, 1 ret isPrime ENDP
3. 修正范围校验的严谨性
validate函数中,将JL valid改为JLE valid,确保用户输入等于200时也能被判定为有效:
validate PROC MOV EBX, userInput CMP EBX, LOWER_BOUND JL rangeError CMP EBX, UPPER_BOUND JG rangeError JLE valid ; 改为JLE,包含等于200的情况 rangeError: MOV EDX, OFFSET outOfRange call WriteString JMP ending valid: MOV EAX, 1 MOV validNum, EAX ending: ret validate ENDP
测试验证
修改后输入15,会输出前15个质数:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 Results certified by Norman O'Brien. Goodbye.
内容的提问来源于stack exchange,提问作者Kneemo
相关产品推荐
相关产品推荐

