Nand2Tetris汇编阶乘程序结果异常求助:输出值偏高
阶乘程序调试问题求助
正在学习Nand2Tetris的汇编语言章节,已经完成mult.asm任务,现在尝试编写一个计算任意输入数阶乘的程序:用户将n输入至R0,程序计算n!并将结果存入R1(需处理F(0)情况)。目前程序的循环计数器能正常终止,但输出结果始终偏高,例如输入3时得到8而非6,附上当前代码,寻求解决建议。
// ================================= Factorial ================================== // This program calculates the Factorial F of a given number n // At run time: // - The user should enter the value of n into R0. R0.e. RAM[0] // - The program then calculate the factorial of n R0.e. F(n)=n! // F(n) = n*(n-1)*(n-2)*......*2*1 // - The result F(n) should be saved in RAM[1] // -- You should also consider the F(0) case. // ============================================================================== // put your code here //set tracker for current loop @R1 M=0 @R2 M=1 @R3 M=0 @R4 M=0 @R5 M=0 @R6 M=0 (LOOP) @R6 D=M //D=R6 @R1 M=M+D @R2 D=M //D = R2 @R4 M=D //R4 = R2 @R0 D=D-M //D = R2 - R0 @END D;JGE //If (R2-R0) > 0 goto END @STEP D;JLT //If (R2-R0) < 0 goto STEP (STEP) //Multiplication begins // Gets R4 from R6. @R6 D=M // wrting data of r6 into d register // Add R1 to it. @R1 D=D+M // And write the result back to R6. @R6 M=D // Reduce R4 by 1. @R4 D=M-1 M=D // If R4 is still > 0 then loop. @STEP D;JGT //Multiplication ends @R2 M=M+1 //R2++ @LOOP 0;JMP //Got LOOP (END) @END 0;JMP //Infinite loop
问题分析与修改建议
核心问题点
- 初始值错误:阶乘的初始乘积应为1(0!和1!的结果都是1),但你把R1初始设为0,后续所有运算都会基于0累加,逻辑完全错误。
- 乘法逻辑混乱:STEP段的运算顺序搞反了,实际应该用当前阶乘结果R1乘以R2,而非用R6累加R1。
- 循环条件错误:当R2等于R0时(比如输入3,R2=3),你直接跳转到END,漏掉了最后一次乘法运算,这是输入3得到8而非6的关键原因之一。
- 冗余寄存器:R3、R5完全未使用,属于冗余定义,可以删除。
具体修改步骤
- 修正初始值:
- 将R1初始设为1,因为阶乘的起始值是1;若R0为0,直接跳转到END返回1。
- 调整循环条件:只有当R2 > R0时才结束循环,R2等于R0时仍需执行乘法。
- 重构乘法逻辑:利用临时寄存器保存当前R1的值,通过累加R2次实现乘法(对应mult.asm的思路),每次循环后R2自增。
修改后的示例代码
// ================================= Factorial ================================== // This program calculates the Factorial F of a given number n // At run time: // - The user should enter the value of n into R0. R0.e. RAM[0] // - The program then calculate the factorial of n R0.e. F(n)=n! // F(n) = n*(n-1)*(n-2)*......*2*1 // - The result F(n) should be saved in RAM[1] // -- You should also consider the F(0) case. // ============================================================================== // 初始化:阶乘初始值为1 @R1 M=1 // 循环计数器从1开始 @R2 M=1 // 处理0!的情况:若R0=0,直接结束 @R0 D=M @END D;JEQ (LOOP) // 判断是否已完成所有乘法:R2 > R0则结束 @R2 D=M @R0 D=D-M @END D;JGT // 保存当前阶乘结果到临时寄存器R3 @R1 D=M @R3 M=D // 重置累加器R4为0,准备累加R2次 @R4 M=0 (MULT_STEP) // 累加R3到R4 @R3 D=M @R4 M=D+M // R2减1,判断是否还需要累加 @R2 D=M-1 M=D @MULT_STEP D;JGT // 将累加结果存入R1,作为新的阶乘结果 @R4 D=M @R1 M=D // 循环计数器自增,进入下一轮 @R2 M=M+1 @LOOP 0;JMP (END) @END 0;JMP // 无限循环终止
测试输入3时,程序会依次计算11=1,12=2,2*3=6,最终R1存入6,符合预期;输入0时直接返回1,满足要求。
内容的提问来源于stack exchange,提问作者Boss Fappy200
相关产品推荐
相关产品推荐

