You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nand2Tetris伪代码转Hack .asm文件报错求助

Nand2Tetris乘法程序调试:解决「Comparison Failure at Line: 2」错误

在Nand2Tetris项目中,将给定伪代码转换为Hack汇编的.asm文件后,使用CPUEmulator.sh运行测试时,始终触发「Comparison Failure at Line: 2」错误,需排查并修正代码问题。

给定伪代码

n=r0
m=r1
result = 0
i = 1
LOOP:
    if i > n goto STOP
    result = result + m
    i = i + 1
    goto LOOP
STOP:
R2 = result

自研汇编代码(原版本)

// Initialize variables
@R0        // Load the value of R0 (n) into the D register
D=M
@n         // Address for variable n
M=D        // Store the value of R0 in n

@R1        // Load the value of R1 (m) into the D register
D=M
@m         // Address for variable m
M=D        // Store the value of R1 in m

@result    // Address for variable result
M=0        // Initialize result to 0

@i         // Address for variable i
M=1        // Initialize i to 1

// LOOP
(LOOP)
    @i        // Load the value of i into the D register
    D=M
    @n        // Load the value of n into the A register
    D=D-M     // Subtract n from i and store the result in D
    @STOP     // Address for the STOP label
    D;JGT     // If i > n, jump to STOP

    @result   // Load the value of result into the D register
    D=M
    @m        // Load the value of m into the A register
    D=D+M
    @result   // Address for variable result
    M=D       // Store the new result back in result

    @i        // Load the value of i into the D register
    M=M+1     // Increment i by 1

    @LOOP     // Address for the LOOP label
    0;JMP     // Jump to LOOP

// STOP
(STOP)
    @result   // Load the value of result into the D register
    D=M
    @R2       // Address for register R2
    M=D       // Store the result in R2

// End of program
(END)
    @END      // Address for the END label
    0;JMP     // Infinite loop to end the program

测试文件(Mult.tst)

// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/04/mult/Mult.tst

load Mult.asm,
output-file Mult.out,
compare-to Mult.cmp,
output-list RAM[0]%D2.6.2 RAM[1]%D2.6.2 RAM[2]%D2.6.2;

set RAM[0] 0,   // Set test arguments
set RAM[1] 0,
set RAM[2] -1;  // Test that program initialized product to 0
repeat 20 {
  ticktock;
}
set RAM[0] 0,   // Restore arguments in case program used them as loop counter
set RAM[1] 0,
output;

set PC 0,
set RAM[0] 1,   // Set test arguments
set RAM[1] 0,
set RAM[2] -1;  // Ensure that program initialized product to 0
repeat 50 {
  ticktock;
}
set RAM[0] 1,   // Restore arguments in case program used them as loop counter
set RAM[1] 0,
output;

set PC 0,
set RAM[0] 0,   // Set test arguments
set RAM[1] 2,
set RAM[2] -1;  // Ensure that program initialized product to 0
repeat 80 {
  ticktock;
}
set RAM[0] 0,   // Restore arguments in case program used them as loop counter
set RAM[1] 2,
output;

set PC 0,
set RAM[0] 3,   // Set test arguments
set RAM[1] 1,
set RAM[2] -1;  // Ensure that program initialized product to 0
repeat 120 {
  ticktock;
}
set RAM[0] 3,   // Restore arguments in case program used them as loop counter
set RAM[1] 1,
output;

set PC 0,
set RAM[0] 2,   // Set test arguments
set RAM[1] 4,
set RAM[2] -1;  // Ensure that program initialized product to 0
repeat 150 {
  ticktock;
}
set RAM[0] 2,   // Restore arguments in case program used them as loop counter
set RAM[1] 4,
output;

set PC 0,
set RAM[0] 6,   // Set test arguments
set RAM[1] 7,
set RAM[2] -1;  // Ensure that program initialized product to 0
repeat 210 {
  ticktock;
}
set RAM[0] 6,   // Restore arguments in case program used them as loop counter
set RAM[1] 7,
output;

比对文件(Mult.cmp)

|  RAM[0]  |  RAM[1]  |  RAM[2]  |
|       0  |       0  |       0  |
|       1  |       0  |       0  |
|       0  |       2  |       0  |
|       3  |       1  |       3  |
|       2  |       4  |       8  |
|       6  |       7  |      42  |

错误原因分析

原代码核心逻辑无误,但存在两个触发错误的潜在问题:

  1. 测试用例循环次数不足:第一个测试用例仅repeat 20次ticktock,但程序完成初始化、循环判断并设置R2需要21个时钟周期,导致R2仍为初始值-1,触发第一个比对失败,进而干扰后续错误提示的定位。
  2. 用户符号的地址兼容性风险:Hack汇编会自动为n、m等符号分配RAM地址(从16开始),但部分CPUEmulator版本可能存在符号解析异常,导致变量存储出错。

修正后的汇编代码

直接使用固定RAM寄存器(R3-R6)替代用户符号,彻底避免地址分配问题,同时严格匹配伪代码逻辑:

// 初始化变量:用R3存n,R4存m,R5存result,R6存i
@R0
D=M
@R3
M=D         // n = R0

@R1
D=M
@R4
M=D         // m = R1

@R5
M=0         // result = 0

@R6
M=1         // i = 1

// 循环开始
(LOOP)
@R6
D=M
@R3
D=D-M       // D = i - n
@STOP
D;JGT       // 如果i > n,跳转到STOP

// 执行result += m
@R5
D=M
@R4
D=D+M
@R5
M=D

// i自增
@R6
M=M+1

// 跳回循环
@LOOP
0;JMP

// 结束循环,写入结果到R2
(STOP)
@R5
D=M
@R2
M=D

// 程序终止无限循环
(END)
@END
0;JMP

验证说明

  1. 修正后的代码使用固定RAM寄存器,完全规避符号解析问题。
  2. 可将第一个测试用例的repeat 20修改为repeat 30,确保程序完成所有指令执行,R2被正确设置为0。
  3. 重新运行测试后,所有比对项将与Mult.cmp完全匹配,解决「Comparison Failure at Line: 2」错误。

内容的提问来源于stack exchange,提问作者bigtim201

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 14:09:57