了解 Hack 汇编语言代码

2 assembly nand2tetris

我的老师给了我这个示例代码来学习,我仍然不明白它,与汇编语言代码和nand2tetris有关。有人可以解释一下吗?

更新:(我发布了整个代码)

 // PSEUDO CODE
    // x=R1
    // y=R2
    // R3=0
    // while(x > 0) {
    //     R3 += y
    //     x--
    // }
    
    @R1
    D=M
    @x
    M=D // x = R1

    @R2
    D=M
    @y
    M=D // y = R2

    @0
    D=A
    @R3
    M=D // R3 = 0

(WHILE)
    // begin of loop condition
    @x
    D=M 
    @END
    D;JLE   // if x <= 0 proceed to END      
    // end of loop condition

    // begin body of while- could someone help explain this part? Thanks :")
    @y
    D=M // D = y
    @R3
    M=D+M   // sum = sum + y
    @1
    D=A // D = 1
    @x
    M=M-D   


    @WHILE
    0;JMP   
(END)   
    @END
    0;JMP   
Run Code Online (Sandbox Code Playgroud)

--> 谢谢你,也许通过不同的解释我就能得到它:“)我还是个新手,请耐心等待

Eri*_*idt 7

理解此类代码至少有 3 个层次:

\n
    \n
  1. 每条指令的作用是什么(汇编的每一行)? \xc2\xa0 这些在教程文本中进行了解释,但大多数指令只是将一些数据从一个寄存器或内存位置或立即指令移动到另一个寄存器(或内存) \xc2\xa0 其中一些计算而不只是移动数据,例如将两个东西加在一起。\xc2\xa0 这些完成处理器状态的微小变化,并且需要指令序列来完成以下任何操作\xc2\xa0 尽管如此,我们仍然需要理解这些最原始的操作才能遵循程序。

    \n
  2. \n
  3. 最基本的操作(我们在高级语言中看到的)是如何执行的。\xc2\xa0 所有汇编语言都使用某种形式的 if-goto-label 来控制循环和 if-then-else 等结构。\xc2\xa0 if-goto-label 形式是这样说的:“如果这是 true(或 false),则将指令流更改为其他位置的其他序列,但如果它是 false(或 true),则继续执行当前的操作,顺序指令流”。\xc2\xa0 条件分支通常涉及诸如“if a > b then goto Label;”之类的结构。所以所有处理器都可以做到这一点,但是这样的条件涉及很多操作数,因此许多处理器将它们分成几个指令。\xc2\xa0(a,b是操作数,>是另一个,因为有许多不同的关系运算符,然后 Label 是另一个操作数;这是 4 个操作数,通常超过一条指令可以完成的操作数,因此指令集将这些操作分成两个或多个指令,因此每个指令只有 2 个左右的操作数。)

    \n
  4. \n
  5. 然而在更高的层面上,我们如何使用这些原语来实现像 while 循环、if-then-else、for 循环和计算表达式这样的控制结构。

    \n
  6. \n
\n
\n

在nand2tetris中,有两大类指令。\xc2\xa0 在汇编语言中用@标记的指令加载A寄存器的地址。\xc2\xa0 如何使用它取决于后续指令。\xc2\xa0 @ form 将标签作为操作数,但该标签可以是代码标签或数据标签,并且由程序来执行一些明智的操作。\xc2\xa0 不以 @ 开头的标签是计算性的,并且可以在寄存器之间移动数据,加或减,以及将数据从内存移动到寄存器,或者反之亦然。

\n

在最原始的级别,条件分支是通过将标签目标加载到 A 寄存器中,然后执行一些计算测试和分支来完成的,这将通过加载程序计数器(或者使用中的值)有条件地转移指令流的控制A寄存器与否!

\n
\n

因此,前两条指令序列表示:将 R1 的地址加载到 A 寄存器,然后下一条指令表示,将 A 处内存中的值加载到 D。\xc2\xa0 其中,D=M 表示 D 寄存器获取M 的值,Memory,其中隐式表示 A 处的内存或内存[A]。

\n

另外两个指令序列: @END...D;JLE 表示将标号 END 的地址加载到 A 中,然后有条件地分支到该指令序列,如果 D <= 0.\xc2\xa0 那么,处理器将有条件地分支到该指令序列执行 PC=A(或不执行)。

\n

最后两条指令序列表示总是跳转到标签 END,这大概就在那里,因此程序以不执行任何操作的无限循环结束自身,这是在简单处理器上结束程序的常见方式。

\n

用法 @x 是对标记为 x 的数据单元/位置的引用。\xc2\xa0 M=D 表示写入内存,D=M 表示从内存读取。\xc2\xa0 因此,有一个名为 x 的变量,它是有时更新,有时查阅。

\n

至于 while 循环,它正在做类似的事情

\n
if ( x <= 0 ) goto END;\n
Run Code Online (Sandbox Code Playgroud)\n

为了完成这个条件测试和分支,首先将数据标签x的地址加载到A中,然后在那里访问/读取内存并将其加载到D中(D=M);接下来代码标签 END 的地址被加载到 A.\xc2\xa0 因此,当D;JLE执行时,D 保存 x 中值的副本,这是通过 JLE 测试的,并且 A 还保存 END 的地址,即当条件成立(D <= 0)时,传输到 PC(PC=A)。

\n
\n

这种条件分支可能是 while 循环的一部分,如下所示:

\n
while ( x > 0 ) {\n    <loop-body>\n}\n
Run Code Online (Sandbox Code Playgroud)\n

将转换为 if-goto-label 形式,如下所示:

\n
Loop1Top:\n    if ( x <= 0 ) goto Loop1End;\n    <loop-body>\n    goto Loop1Top;\nLoop1End:\n
Run Code Online (Sandbox Code Playgroud)\n

您可以看到 C 和汇编 if-goto 的条件是相反的,因为它们的意义/含义是相反的:在 C 中,while 的循环条件表示何时留在循环中,而在汇编中,我们告诉处理器何时停止退出循环,以便测试相反的条件。

\n

我们没有看到该计划的其余部分,因此这只是有根据的猜测。

\n