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

Nand2tetris VMtranslator优化遇A=-5非法操作错误求助

问题定位与修复方案

错误根源分析

CPU模拟器抛出A = -5非法操作,本质是访问了负数内存地址。查看你的return逻辑:

@5
D=A
@LCL
A=M-D  // 若LCL的值小于5,M-D会产生负数,导致A寄存器为-5
D=M
@R14
M=D

出现该问题说明函数调用时的栈帧初始化不完整,LCL指向的地址没有足够的栈帧数据(至少需要5个位置保存返回地址、LCL、ARG、THIS、THAT)。

调用逻辑的核心修复

你的isCalled分支代码缺少栈帧保存和ARG/SP初始化的关键步骤,导致函数执行时LCL未正确指向完整栈帧头部:

  1. 补全isCalled分支的栈帧保存逻辑:
    原分支仅跳转到函数入口,未保存调用方寄存器状态,也未设置ARG和SP,需补充和else分支对齐的核心流程。
  2. 统一所有调用的栈帧初始化标准:
    无论是否复用调用逻辑,都必须确保:
    • 返回地址压栈
    • LCL、ARG、THIS、THAT依次压栈
    • 设置ARG为SP-nArgs-5
    • 设置LCL为当前SP
    • 跳转到函数入口

修改后的isCalled分支示例:

if(isCalled(operator, segment, offset)){
    sprintf(output, "@%s$retC.%i\nD=A\n@R15\nM=D\n"
                    "// 保存返回地址到栈\n"
                    "@%s$retC.%i\nD=A\n@SP\nM=M+1\nA=M-1\nM=D\n"
                    "// 保存调用方寄存器\n"
                    "@LCL\nD=M\n@SP\nM=M+1\nA=M-1\nM=D\n"
                    "@ARG\nD=M\n@SP\nM=M+1\nA=M-1\nM=D\n"
                    "@THIS\nD=M\n@SP\nM=M+1\nA=M-1\nM=D\n"
                    "@THAT\nD=M\n@SP\nM=M+1\nA=M-1\nM=D\n"
                    "// 设置ARG和LCL\n"
                    "@SP\nD=M\n@5\nD=D-A\n@%li\nD=D-A\n@ARG\nM=D\n"
                    "@SP\nD=M\n@LCL\nM=D\n"
                    "@%s\n0;JMP\n"
                    "(%s$retC.%i)\n",
                    segment, count, segment, count,
                    strtol(offset, NULL, 10),
                    segment, segment, count);
    count++;
}

Return逻辑的健壮性优化

在RESTORE代码开头添加LCL合法性检查(可选调试用),避免非法地址访问:

// RESTORE CODE
(RESTORE)
@LCL
D=M
@5
D=D-A
@INVALID_LCL  // 若LCL<5,跳转到错误处理标记
D;JLT
// 原RESTORE逻辑继续
@5
D=A
@LCL
A=M-D
D=M
@R14
M=D
...

代码缩减的进阶方案

  1. 提取公共子程序:
    将调用时的寄存器保存、return时的寄存器恢复逻辑,单独做成(SAVE_FRAME)和(RESTORE_FRAME)公共子程序,所有调用/return逻辑直接跳转复用,避免重复生成代码。
  2. 复用返回标签:
    对同一函数名+参数数量的调用,共用同一个返回标签(比如用functionName+nArgs的哈希值替代全局count),减少冗余标签生成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:52:51