1

我的老师给了我这个示例代码来学习,我仍然不明白,与汇编语言代码和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   

--> 谢谢,也许有不同的解释我就能得到它:") 我还是个新手请多多包涵

4

1 回答 1

4

至少有 3 个级别可以理解此类代码:

  1. 每个单独的指令做什么(每行汇编)?这些在教程文本中进行了解释,但大多数指令只是将一些数据从一个寄存器或内存位置或直接移动到另一个寄存器(或内存位置)的指令。他们中的一些人计算而不是/不仅仅是移动数据,例如将两个东西加在一起。这些实现了处理器状态的微小变化,并且需要一系列指令来完成任何重要的事情。不过,我们需要了解这些最原始的操作才能遵循程序。

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

  3. 然而,在更高的层次上,我们如何使用这些原语完成诸如 while 循环、if-then-else、for 循环和计算表达式之类的控制结构。


在 nand2tetris 中,有两大类指令。在汇编语言中用@ 标记的那些会加载带有地址的A 寄存器。如何使用它取决于随后的说明。@ 形式将标签作为操作数,但该标签可以是代码标签或数据标签,由程序来做一些明智的事情。不以@ 开头的那些是计算性的,可以在寄存器之间移动数据,加减,以及将数据从内存移动到寄存器或以其他方式移动。

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


所以,第一个两条指令序列说:用 R1 的地址加载 A 寄存器,然后下一条指令说,用 A 的内存中的值加载 D。在那里,D=M 意味着 D 寄存器获取 M 的值, 内存,其中隐含的意思是 A 或 memory[A] 处的内存。

另外两个指令序列:@END... D;JLE 表示,将标签 END 的地址加载到 A 中,然后有条件地跳转到该指令序列,如果 D <= 0。因此,处理器将有条件地执行 PC=A (或不)。

最后的两条指令序列表示总是跳转到标签 END,大概就在那儿,所以程序以一个什么都不做的无限循环结束,这是在简单处理器上结束程序的常用方法。

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

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

if ( x <= 0 ) goto END;

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


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

while ( x > 0 ) {
    <loop-body>
}

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

Loop1Top:
    if ( x <= 0 ) goto Loop1End;
    <loop-body>
    goto Loop1Top;
Loop1End:

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

我们没有看到程序的其余部分,所以这只是有根据的推测。

于 2021-11-27T05:53:57.693 回答