我正在尝试将此伪代码转换为 hack 语言并保存为 .asm 文件

问题描述 投票:0回答:1

我一直在试图弄清楚如何将伪代码翻译成格式为.asm的黑客语言,这将使用Nand2Tetris中的CPUEmulator.sh成功运行,并附加.tst和.cmp文件。

我在模拟器上不断收到“第 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
我的理解是我需要初始化'@n','@m','@result','@i'。

  1. n 是乘数,'m' 是寄存器 R0 和 R1 中的被乘数。

  2. 将“结果”初始化为 0,将“i”初始化为 1。

  3. 进入循环:

    如果我
  • < n, exit the loop
  • 否则,将“m”添加到“结果”
  • 将 i 加 1
  • 重复循环。
    将结果存储在寄存器R2中
这是我到目前为止所写的:

// 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
我不确定我是否遗漏了某些内容或误解了如何初始化结果和i。我很茫然。

这是附加测试文件。

// 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;
以及组件文件:

| RAM[0] | RAM[1] | RAM[2] | | 0 | 0 | 0 | | 1 | 0 | 0 | | 0 | 2 | 0 | | 3 | 1 | 3 | | 2 | 4 | 8 | | 6 | 7 | 42 |
编辑:也感谢 Tange Perp 指出代码发布政策。我对截图表示歉意,最重要的是对小猫表示歉意,这是我第一次,我不应该着急。 :(.

assembly pseudocode
1个回答
0
投票
你的代码看起来没问题;但是,看起来 0×0 的计算将需要 22 个以上的 ticktock,而 Mult.tst 测试运行程序文件仅允许第一个测试使用 20 个 ticktock。

如果是这种情况,那么 R2=结果的最后部分将不会被执行,因此 R2 仍将保持 -1。

尝试将第一个测试的 Mult.tst 中的重复次数设置为 25(而不是 20)。

后续测试的重复次数为 50 次及以上似乎足以满足您的实施。


标准乘法 Mult.asm 根本不使用数据变量:

    将 R0 乘以 R1,将结果累加到 R2
  • 它倒计时 R0 递减至 0
这是伪代码:

R2=0 while(R1 != 0) R2=R2+R0 R1--
它要短得多,因为它放弃了变量初始化,因此第一个测试的 20 个刻度足以满足该实现。


关于变量与编号寄存器,我想说它更难阅读。  变量的使用仅代表很小的开销,因为一旦它们在初始化中建立,那么循环就与使用 Rx 的“寄存器”一样高效。

向下计数到 0 是一种算法选择,当循环计数器的实际值未使用时,通常会为了效率而做出选择,因为与 0 比较比与

n

 比较更容易。  然而,这会破坏 R0 值 - 但 Mult.tst 意识到这一点,并在运行黑客代码之后和输出应答行之前将 R0 和 R1 重置为测试输入值。


TL;DR 标准 Mult.tst 期望 Mult.asm 的特定实现,更短,并且还破坏输入。  您开始的伪代码较长,并且并不真正符合 Mult.tst 的期望。

© www.soinside.com 2019 - 2024. All rights reserved.