【问题标题】:Understanding Hack Assembly Language code理解 Hack 汇编语言代码
【发布时间】:2021-11-27 04:22:07
【问题描述】:

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

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

【问题讨论】:

  • 他们没有给你汇编语言语法的参考吗?就是想。如果您粘贴整个代码块并将其集中在一个问题上也会更好。

标签: assembly nand2tetris


【解决方案1】:

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

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

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

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


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

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


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

另外两个指令序列:@END... D;JLE 说,将标签 END 的地址加载到 A 中,然后有条件地跳转到该指令序列,如果 D

最后两个指令序列表示总是跳转到标签 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的地址,该地址被传输当条件成立时(即 D


这种条件分支可能是 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 的循环条件表示何时停留在循环中,而在汇编中我们告诉处理器何时退出循环以便测试相反的条件。

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

【讨论】:

  • 我快到了 XD 但我有一个问题,你怎么知道 while 循环正在执行表达式 >= 0?再次感谢~
  • 抱歉,打错了。
  • 这段代码的问题是要求将 RAM[1] 和 RAM[2] 相乘并存储在 RAM[3] 中。但是,我仍然不太明白其中的逻辑。提供的伪代码是 PSEUDOCODE: x=R1, y=R2 R3=0 while(x > 0) { R3 += y ; X - ;那么 R3=0 是否像 sum=0 一样?还有,你怎么知道是x--?再次感谢:") 为这么多问题道歉
  • Nvm,为了更好的参考,我在这里发布了整个代码,我不久前才发现了 Stack Overflow。所以我不知道我可以编辑已经发布的问题。 :")
  • 是的,这是重复加法的乘法。对于 x--,查看成组的汇编代码,看看是如何完成的:从 @1 开始,推理它的作用以及它是如何使用的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-16
  • 2010-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多